From 0e7f22b6e0b12981302743f2f6244a6f4932c2a4 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Thu, 28 Jan 2021 11:57:43 +0300 Subject: [PATCH 01/19] broken wip wip wip --- Cargo.lock | 1 + Cargo.toml | 1 + bin/Cargo.lock | 38 ++++++++++++++++++++++++ bin/Cargo.toml | 1 + bin/run-repl.sh | 7 +++-- bin/src/service_api.rs | 4 +++ src/certificate.rs | 17 +++++++++-- src/lib.rs | 18 ++++++------ src/trust.rs | 52 +++++++++++++++++++++++---------- src/trust_graph.rs | 60 ++++++++++++++++++++++++-------------- src/trust_graph_storage.rs | 58 ++++++++++++++++++++++++------------ 11 files changed, 187 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec78b27..191ca4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1428,6 +1428,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 118552c..7b90e77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,4 @@ ed25519-dalek = { version = "1.0.1", features = ["serde"] } rand = "0.7.0" signature = "1.3.0" serde_with = "1.6.0" +thiserror = "1.0.23" diff --git a/bin/Cargo.lock b/bin/Cargo.lock index c3e3774..9dc6c39 100644 --- a/bin/Cargo.lock +++ b/bin/Cargo.lock @@ -984,6 +984,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -1415,6 +1421,36 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "sqlite" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35f759dc2e373e1edd0a27da87aa9136416360c5077a23643fcd6fcdc9cb9e31" +dependencies = [ + "libc", + "sqlite3-sys", +] + +[[package]] +name = "sqlite3-src" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb25e66d026488228a97e0ad21e3d15ec5998dcd9ad73c97cc277c56a6b314" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "sqlite3-sys" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fec807a1534bd13eeaaec396175d67c79bdc68df55e18a452726ec62a8fb08" +dependencies = [ + "libc", + "sqlite3-src", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -1537,6 +1573,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] @@ -1556,6 +1593,7 @@ dependencies = [ "rmp-serde", "serde_bencode", "serde_json", + "sqlite", "trust-graph", ] diff --git a/bin/Cargo.toml b/bin/Cargo.toml index f456ff0..51ff958 100644 --- a/bin/Cargo.toml +++ b/bin/Cargo.toml @@ -25,3 +25,4 @@ bs58 = "0.3.1" rmp-serde = "0.15.0" bincode = "1.3.1" serde_bencode = "^0.2.3" +sqlite = "0.25.3" diff --git a/bin/run-repl.sh b/bin/run-repl.sh index 7213443..0604ee9 100755 --- a/bin/run-repl.sh +++ b/bin/run-repl.sh @@ -1,5 +1,8 @@ -#!/bin/bash +#!/usr/bin/env bash +set -euo pipefail fce build -mv target/wasm32-wasi/debug/trust-graph.wasm artifacts/ + +rm artifacts/trust-graph.wasm +mv -f target/wasm32-wasi/debug/trust-graph.wasm artifacts/ RUST_LOG="info" fce-repl Config.toml diff --git a/bin/src/service_api.rs b/bin/src/service_api.rs index d54c496..fbaee3b 100644 --- a/bin/src/service_api.rs +++ b/bin/src/service_api.rs @@ -27,8 +27,12 @@ fn insert_cert(certificate: String, duration: u64) -> InsertResult { #[fce] fn looper() { + + let second = std::time::Duration::from_millis(1000); + let mut a = 0; while true { + std::thread::sleep(second); a = a + 1; log::info!("{}", a) } diff --git a/src/certificate.rs b/src/certificate.rs index 3b44a4b..ebb8ed5 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -33,6 +33,17 @@ pub struct Certificate { pub chain: Vec, } +pub enum CerificateError { + DecodeError(String), + ExpirationError { + expires_at: String, + issued_at: String + }, + KeyInCertificateError, + CertificateLengthError, + +} + impl Certificate { pub fn new_unverified(chain: Vec) -> Self { Self { chain } @@ -65,7 +76,7 @@ impl Certificate { expires_at: Duration, issued_at: Duration, cur_time: Duration, - ) -> Result { + ) -> Result { if expires_at.lt(&issued_at) { return Err("Expiration time should be greater than issued time.".to_string()); } @@ -110,7 +121,7 @@ impl Certificate { cert: &Certificate, trusted_roots: &[PublicKey], cur_time: Duration, - ) -> Result<(), String> { + ) -> Result<(), CerificateError> { let chain = &cert.chain; if chain.is_empty() { @@ -159,7 +170,7 @@ impl Certificate { } #[allow(dead_code)] - pub fn decode(arr: &[u8]) -> Result { + pub fn decode(arr: &[u8]) -> Result { let trusts_offset = arr.len() - 2 - 4; if trusts_offset % TRUST_LEN != 0 { return Err("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust. ".to_string()); diff --git a/src/lib.rs b/src/lib.rs index 4436f6e..6b73d6e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,15 +16,15 @@ #![recursion_limit = "512"] #![warn(rust_2018_idioms)] -#![deny( - dead_code, - nonstandard_style, - unused_imports, - unused_mut, - unused_variables, - unused_unsafe, - unreachable_patterns -)] +// #![deny( +// dead_code, +// nonstandard_style, +// unused_imports, +// unused_mut, +// unused_variables, +// unused_unsafe, +// unreachable_patterns +// )] mod certificate; pub mod certificate_serde; diff --git a/src/trust.rs b/src/trust.rs index 1f46d04..b57635a 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -21,6 +21,8 @@ use fluence_identity::signature::Signature; use serde::{Deserialize, Serialize}; use std::convert::TryInto; use std::time::Duration; +use thiserror::Error as ThisError; +use crate::trust::TrustError::{SignatureError, DecodeError}; pub const SIG_LEN: usize = 64; pub const PK_LEN: usize = 32; @@ -55,6 +57,21 @@ fn show_sig(sig: &Signature, f: &mut std::fmt::Formatter<'_>) -> Result<(), std: write!(f, "{}", bs58::encode(&sig.to_bytes()).into_string()) } +#[derive(ThisError, Debug)] +pub enum TrustError { + /// Errors occurred when 'expires_at' date is later then current time. + #[error("Trust is expired at: '{0:?}', current time: '{1:?}'")] + Expired(Duration, Duration), + + /// Errors occured on signature verification + #[error("{0:?}")] + SignatureError(String), + + /// Errors occured on trust decoding from differrent formats + #[error("{0:?}")] + DecodeError(String) +} + impl Trust { #[allow(dead_code)] pub fn new( @@ -90,15 +107,15 @@ impl Trust { } /// Verifies that authorization is cryptographically correct. - pub fn verify(trust: &Trust, issued_by: &PublicKey, cur_time: Duration) -> Result<(), String> { + pub fn verify(trust: &Trust, issued_by: &PublicKey, cur_time: Duration) -> Result<(), TrustError> { if trust.expires_at < cur_time { - return Err("Trust in chain is expired.".to_string()); + return TrustError::Expired(trust.expires_at, cur_time); } let msg: &[u8] = &Self::metadata_bytes(&trust.issued_for, trust.expires_at, trust.issued_at); - KeyPair::verify(issued_by, msg, &trust.signature)?; + KeyPair::verify(issued_by, msg, &trust.signature).map_err(|e| SignatureError(e))?; Ok(()) } @@ -132,17 +149,20 @@ impl Trust { /// Decode a trust from a byte array as produced by `encode`. #[allow(dead_code)] - pub fn decode(arr: &[u8]) -> Result { + pub fn decode(arr: &[u8]) -> Result { if arr.len() != TRUST_LEN { - return Err( - format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}", arr.len()), + return DecodeError( + format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}", + arr.len()) ); } - let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(|err| err.to_string())?; + let pk = PublicKey::from_bytes(&arr[0..PK_LEN]) + .map_err(|err| DecodeError(format!("Cannot decode a public key: {}", err.to_string())))?; let signature = &arr[PK_LEN..PK_LEN + SIG_LEN]; - let signature = Signature::from_bytes(signature).map_err(|err| err.to_string())?; + let signature = Signature::from_bytes(signature) + .map_err(|err| DecodeError(format!("Cannot decode a signature: {}", err.to_string())))?; let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN]; let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap()); @@ -160,7 +180,7 @@ impl Trust { }) } - fn bs58_str_to_vec(str: &str, field: &str) -> Result, String> { + fn bs58_str_to_vec(str: &str, field: &str) -> Result, TrustError> { bs58::decode(str).into_vec().map_err(|e| { format!( "Cannot decode `{}` from base58 format in the trust '{}': {}", @@ -169,12 +189,12 @@ impl Trust { }) } - fn str_to_duration(str: &str, field: &str) -> Result { + fn str_to_duration(str: &str, field: &str) -> Result { let secs = str.parse().map_err(|e| { - format!( + DecodeError(format!( "Cannot parse `{}` field in the trust '{}': {}", field, str, e - ) + )) })?; Ok(Duration::from_secs(secs)) } @@ -184,19 +204,19 @@ impl Trust { signature: &str, expires_at: &str, issued_at: &str, - ) -> Result { + ) -> Result { // PublicKey let issued_for_bytes = Self::bs58_str_to_vec(issued_for, "issued_for")?; let issued_for = PublicKey::from_bytes(issued_for_bytes.as_slice()).map_err(|e| { - format!( + DecodeError(format!( "Cannot decode the public key: {} in the trust '{}'", issued_for, e - ) + )) })?; // 64 bytes signature let signature = Self::bs58_str_to_vec(signature, "signature")?; - let signature = Signature::from_bytes(&signature).map_err(|err| err.to_string())?; + let signature = Signature::from_bytes(&signature).map_err(|err| DecodeError(err.to_string()))?; // Duration let expires_at = Self::str_to_duration(expires_at, "expires_at")?; diff --git a/src/trust_graph.rs b/src/trust_graph.rs index 7f40878..a4f66af 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -14,16 +14,17 @@ * limitations under the License. */ -use crate::certificate::Certificate; +use crate::certificate::{Certificate, CerificateError}; use crate::public_key_hashable::PublicKeyHashable; use crate::revoke::Revoke; use crate::trust::Trust; -use crate::trust_graph_storage::Storage; +use crate::trust_graph_storage::{Storage, StorageError}; use crate::trust_node::{Auth, TrustNode}; use fluence_identity::public_key::PublicKey; use std::borrow::Borrow; use std::collections::{HashSet, VecDeque}; use std::time::Duration; +use crate::trust_graph::TrustGraphError::{InternalStorageError, CertificateCheckError}; /// for simplicity, we store `n` where Weight = 1/n^2 pub type Weight = u32; @@ -32,48 +33,60 @@ pub type Weight = u32; /// TODO serialization/deserialization /// TODO export a certificate from graph #[allow(dead_code)] -pub struct TrustGraph { - storage: Box, +pub struct TrustGraph where S: Storage { + storage: Box, +} + +pub enum TrustGraphError { + InternalStorageError(String), + CertificateCheckError(CerificateError) +} + +impl Into for CerificateError { + fn into(self) -> TrustGraphError { + CertificateCheckError(self) + } } #[allow(dead_code)] -impl TrustGraph { - pub fn new(storage: Box) -> Self { +impl TrustGraph where S: Storage { + pub fn new(storage: Box) -> Self { Self { storage: storage } } /// Insert new root weight - pub fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) { - self.storage.add_root_weight(pk, weight) + pub fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), TrustGraphError> { + self.storage.add_root_weight(pk, weight).map_err(|e| InternalStorageError(e.into())) } /// Get trust by public key - pub fn get(&self, pk: PublicKey) -> Option { - self.storage.get(&pk.into()) + pub fn get(&self, pk: PublicKey) -> Result, TrustGraphError> { + self.storage.get(&pk.into()).map_err(|e| InternalStorageError(e.into())) } // TODO: remove cur_time from api, leave it for tests only /// Certificate is a chain of trusts, add this chain to graph - pub fn add(&mut self, cert: C, cur_time: Duration) -> Result<(), String> + pub fn add(&mut self, cert: C, cur_time: Duration) -> Result<(), TrustGraphError> where C: Borrow, { let roots: Vec = self .storage .root_keys() + .map_err(|e| InternalStorageError(e.into()))? .iter() .cloned() .map(Into::into) .collect(); // Check that certificate is valid and converges to one of the known roots - Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?; + Certificate::verify(cert.borrow(), roots.as_slice(), cur_time).map_err(|e| e.into())?; let mut chain = cert.borrow().chain.iter(); - let root_trust = chain.next().ok_or("empty chain")?; + let root_trust = chain.next().ok_or("empty chain").map_err(|e| InternalStorageError(e.into()))?; let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into(); // Insert new TrustNode for this root_pk if there wasn't one - if self.storage.get(&root_pk).is_none() { + if self.storage.get(&root_pk).map_err(|e| InternalStorageError(e.into()))?.is_none() { let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time); let root_auth = Auth { trust: root_trust.clone(), @@ -103,31 +116,32 @@ impl TrustGraph { } /// Get the maximum weight of trust for one public key. - pub fn weight

(&self, pk: P) -> Option + pub fn weight

(&self, pk: P) -> Result, TrustGraphError> where P: Borrow, { - if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref()) { - return Some(weight); + if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))? { + return Ok(Some(weight)); } let roots: Vec = self .storage .root_keys() + .map_err(|e| InternalStorageError(e.into()))? .iter() .map(|pk| pk.clone().into()) .collect(); // get all possible certificates from the given public key to all roots in the graph let certs = self.get_all_certs(pk, roots.as_slice()); - self.certificates_weight(certs) + Ok(self.certificates_weight(certs)?) } /// Calculate weight from given certificates /// Returns None if there is no such public key /// or some trust between this key and a root key is revoked. /// TODO handle non-direct revocations - pub fn certificates_weight(&self, certs: I) -> Option + pub fn certificates_weight(&self, certs: I) -> Result, TrustGraphError> where C: Borrow, I: IntoIterator, @@ -135,7 +149,9 @@ impl TrustGraph { let mut certs = certs.into_iter().peekable(); // if there are no certificates for the given public key, there is no info about this public key // or some elements of possible certificate chains was revoked - certs.peek()?; + if certs.peek().is_none() { + return Ok(None) + } let mut weight = std::u32::MAX; @@ -146,14 +162,14 @@ impl TrustGraph { .storage .get_root_weight(cert.chain.first()?.issued_for.as_ref()) // This panic shouldn't happen // TODO: why? - .expect("first trust in chain must be in root_weights"); + .map_err(|e| InternalStorageError(e.into()))?; // certificate weight = root weight + 1 * every other element in the chain // (except root, so the formula is `root weight + chain length - 1`) weight = std::cmp::min(weight, root_weight + cert.chain.len() as u32 - 1) } - Some(weight) + Ok(Some(weight)) } /// BF search for all converging paths (chains) in the graph diff --git a/src/trust_graph_storage.rs b/src/trust_graph_storage.rs index 2f8d566..d171d78 100644 --- a/src/trust_graph_storage.rs +++ b/src/trust_graph_storage.rs @@ -5,22 +5,31 @@ use crate::trust_node::{Auth, TrustNode}; use fluence_identity::public_key::PublicKey; use std::collections::HashMap; use std::time::Duration; +use thiserror::Error as ThisError; +use crate::trust_graph_storage::InMemoryStorageError::RevokeError; + +pub trait StorageError {} + + pub trait Storage { - fn get(&self, pk: &PublicKeyHashable) -> Option; - fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode); - fn get_root_weight(&self, pk: &PublicKeyHashable) -> Option; - fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight); - fn root_keys(&self) -> Vec; - fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), String>; + type Error: StorageError + Into; + + fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error>; + fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error>; + + fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result, Self::Error>; + fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error>; + fn root_keys(&self) -> Result, Self::Error>; + fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error>; fn update_auth( &mut self, pk: &PublicKeyHashable, auth: Auth, issued_for: &PublicKey, cur_time: Duration, - ); + ) -> Result<(), Self::Error>; } #[derive(Debug, Default)] @@ -51,34 +60,47 @@ impl InMemoryStorage { } } +#[derive(ThisError, Debug)] +pub enum InMemoryStorageError { + + #[error("{0:?}")] + RevokeError(String) +} + +impl StorageError for InMemoryStorage {} + impl Storage for InMemoryStorage { - fn get(&self, pk: &PublicKeyHashable) -> Option { - self.nodes.get(pk).cloned() + + type Error = InMemoryStorageError; + + fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { + Ok(self.nodes.get(pk).cloned()) } - fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) { + fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error> { &self.nodes.insert(pk, node); + Ok(()) } - fn get_root_weight(&self, pk: &PublicKeyHashable) -> Option { - self.root_weights.get(pk).cloned() + fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { + Ok(self.root_weights.get(pk).cloned()) } - fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) { - &self.root_weights.insert(pk, weight); + fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error> { + Ok(&self.root_weights.insert(pk, weight)); } - fn root_keys(&self) -> Vec { - self.root_weights.keys().cloned().map(Into::into).collect() + fn root_keys(&self) -> Result, Self::Error> { + Ok(self.root_weights.keys().cloned().map(Into::into).collect()) } - fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), String> { + fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error> { match self.nodes.get_mut(&pk) { Some(trust_node) => { trust_node.update_revoke(revoke); Ok(()) } - None => Err("There is no trust with such PublicKey".to_string()), + None => RevokeError("There is no trust with such PublicKey".to_string()), } } From f359dc50902622603aa0eddbd4c907b4322f9ad0 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Mon, 8 Feb 2021 17:35:56 +0300 Subject: [PATCH 02/19] still wip.. --- src/certificate.rs | 3 +- src/revoke.rs | 11 +++- src/trust_graph.rs | 127 +++++++++++++++++++++++++-------------------- 3 files changed, 82 insertions(+), 59 deletions(-) diff --git a/src/certificate.rs b/src/certificate.rs index ebb8ed5..02b3226 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -33,6 +33,7 @@ pub struct Certificate { pub chain: Vec, } +#[derive(Debug)] pub enum CerificateError { DecodeError(String), ExpirationError { @@ -41,7 +42,7 @@ pub enum CerificateError { }, KeyInCertificateError, CertificateLengthError, - + Unexpected(String) } impl Certificate { diff --git a/src/revoke.rs b/src/revoke.rs index 8aa1243..5cabde5 100644 --- a/src/revoke.rs +++ b/src/revoke.rs @@ -20,6 +20,13 @@ use fluence_identity::public_key::PublicKey; use fluence_identity::signature::Signature; use serde::{Deserialize, Serialize}; use std::time::Duration; +use ed25519_dalek::SignatureError; +use crate::revoke::RevokeError::IncorrectSignature; + +#[derive(Debug)] +pub enum RevokeError { + IncorrectSignature(SignatureError) +} /// "A document" that cancels trust created before. /// TODO delete pk from Revoke (it is already in a trust node) @@ -69,13 +76,13 @@ impl Revoke { } /// Verifies that revocation is cryptographically correct. - pub fn verify(revoke: &Revoke) -> Result<(), String> { + pub fn verify(revoke: &Revoke) -> Result<(), RevokeError> { let msg = Revoke::signature_bytes(&revoke.pk, revoke.revoked_at); revoke .revoked_by .verify_strict(msg.as_slice(), &revoke.signature) - .map_err(|err| format!("Revoke has incorrect signature: {:?}", err)) + .map_err(|err| IncorrectSignature(err)) } } diff --git a/src/trust_graph.rs b/src/trust_graph.rs index a4f66af..ce9ffdf 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -24,7 +24,11 @@ use fluence_identity::public_key::PublicKey; use std::borrow::Borrow; use std::collections::{HashSet, VecDeque}; use std::time::Duration; -use crate::trust_graph::TrustGraphError::{InternalStorageError, CertificateCheckError}; +use crate::trust_graph::TrustGraphError::{InternalStorageError, CertificateCheckError, NoRoot, RevokeCheckError}; +use crate::certificate::CerificateError::{CertificateLengthError, Unexpected}; +use crate::revoke::RevokeError; +use std::convert::{From, Into}; +use std::result::Result; /// for simplicity, we store `n` where Weight = 1/n^2 pub type Weight = u32; @@ -37,14 +41,23 @@ pub struct TrustGraph where S: Storage { storage: Box, } +#[derive(Debug)] pub enum TrustGraphError { InternalStorageError(String), - CertificateCheckError(CerificateError) + NoRoot, + CertificateCheckError(CerificateError), + RevokeCheckError(RevokeError), } -impl Into for CerificateError { - fn into(self) -> TrustGraphError { - CertificateCheckError(self) +impl From for TrustGraphError { + fn from(err: CerificateError) -> Self { + CertificateCheckError(err) + } +} + +impl From for TrustGraphError { + fn from(err: RevokeError) -> Self { + RevokeCheckError(err) } } @@ -79,7 +92,7 @@ impl TrustGraph where S: Storage { .map(Into::into) .collect(); // Check that certificate is valid and converges to one of the known roots - Certificate::verify(cert.borrow(), roots.as_slice(), cur_time).map_err(|e| e.into())?; + Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?; let mut chain = cert.borrow().chain.iter(); let root_trust = chain.next().ok_or("empty chain").map_err(|e| InternalStorageError(e.into()))?; @@ -133,7 +146,7 @@ impl TrustGraph where S: Storage { .collect(); // get all possible certificates from the given public key to all roots in the graph - let certs = self.get_all_certs(pk, roots.as_slice()); + let certs = self.get_all_certs(pk, roots.as_slice())?; Ok(self.certificates_weight(certs)?) } @@ -156,17 +169,19 @@ impl TrustGraph where S: Storage { let mut weight = std::u32::MAX; for cert in certs { - let cert = cert.borrow(); + let c = cert.borrow(); + + let first = c.chain.first().ok_or(CertificateCheckError(CertificateLengthError))?; let root_weight = self .storage - .get_root_weight(cert.chain.first()?.issued_for.as_ref()) + .get_root_weight(first.issued_for.as_ref()) // This panic shouldn't happen // TODO: why? - .map_err(|e| InternalStorageError(e.into()))?; + .map_err(|e| InternalStorageError(e.into()))?.ok_or(NoRoot)?; // certificate weight = root weight + 1 * every other element in the chain // (except root, so the formula is `root weight + chain length - 1`) - weight = std::cmp::min(weight, root_weight + cert.chain.len() as u32 - 1) + weight = std::cmp::min(weight, root_weight + c.chain.len() as u32 - 1) } Ok(Some(weight)) @@ -179,7 +194,7 @@ impl TrustGraph where S: Storage { &self, node: &TrustNode, roots: HashSet<&PublicKeyHashable>, - ) -> Vec> { + ) -> Result>, TrustGraphError> { // queue to collect all chains in the trust graph (each chain is a path in the trust graph) let mut chains_queue: VecDeque> = VecDeque::new(); @@ -204,9 +219,10 @@ impl TrustGraph where S: Storage { let auths: Vec = self .storage .get(&last.issued_by.clone().into()) - .expect( - "there cannot be paths without any nodes after adding verified certificates", - ) + .map_err(|e| InternalStorageError(e.into()))? + .ok_or( + CertificateCheckError(Unexpected("there cannot be paths without any nodes after adding verified certificates".to_string())), + )? .authorizations() .cloned() .collect(); @@ -236,26 +252,26 @@ impl TrustGraph where S: Storage { } } - terminated_chains + Ok(terminated_chains) } // TODO: remove `roots` argument from api, leave it for tests and internal usage only /// Get all possible certificates where `issued_for` will be the last element of the chain /// and one of the destinations is the root of this chain. - pub fn get_all_certs

(&self, issued_for: P, roots: &[PublicKey]) -> Vec + pub fn get_all_certs

(&self, issued_for: P, roots: &[PublicKey]) -> Result, TrustGraphError> where P: Borrow, { // get all auths (edges) for issued public key - let issued_for_node = self.storage.get(issued_for.borrow().as_ref()); + let issued_for_node = self.storage.get(issued_for.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))?; let roots = roots.iter().map(|pk| pk.as_ref()); - let keys = self.storage.root_keys(); + let keys = self.storage.root_keys().map_err(|e| InternalStorageError(e.into()))?; let roots = keys.iter().chain(roots).collect(); match issued_for_node { - Some(node) => self - .bf_search_paths(&node, roots) + Some(node) => Ok(self + .bf_search_paths(&node, roots)? .iter() .map(|auths| { // TODO: can avoid cloning here by returning &Certificate @@ -272,18 +288,18 @@ impl TrustGraph where S: Storage { ); c.chain.len() > 1 }) - .collect(), - None => Vec::new(), + .collect()), + None => Ok(Vec::new()), } } /// Mark public key as revoked. - pub fn revoke(&mut self, revoke: Revoke) -> Result<(), String> { + pub fn revoke(&mut self, revoke: Revoke) -> Result<(), TrustGraphError> { Revoke::verify(&revoke)?; let pk: PublicKeyHashable = revoke.pk.clone().into(); - self.storage.revoke(&pk, revoke) + self.storage.revoke(&pk, revoke).map_err(|e| InternalStorageError(e.into())) } /// Check information about new certificates and about revoked certificates. @@ -329,7 +345,7 @@ mod tests { keys: HashMap, expires_at: Duration, issued_at: Duration, - ) -> (Vec, Certificate) { + ) -> Result<(Vec, Certificate), TrustGraphError> { assert!(len > 2); let root_kp = KeyPair::generate(); @@ -351,18 +367,17 @@ mod tests { // TODO: why `issued_at = issued_at - 60 seconds`? issued_at.checked_sub(Duration::from_secs(60)).unwrap(), current_time(), - ) - .unwrap(); + )?; key_pairs.push(kp); } - (key_pairs, cert) + Ok((key_pairs, cert)) } fn generate_cert_with_len( len: usize, keys: HashMap, - ) -> (Vec, Certificate) { + ) -> Result<(Vec, Certificate), TrustGraphError> { let cur_time = current_time(); let far_future = cur_time.checked_add(one_minute()).unwrap(); @@ -406,7 +421,7 @@ mod tests { chain_keys.insert(5, key_pair1.clone()); chain_keys.insert(6, key_pair2.clone()); - let (key_pairs1, cert1) = generate_cert_with(10, chain_keys, far_future * 2, far_future); + let (key_pairs1, cert1) = generate_cert_with(10, chain_keys, far_future * 2, far_future).expect(""); // Use key_pair1 and key_pair2 for 7th and 8th trust in the cert chain let mut chain_keys = HashMap::new(); @@ -414,7 +429,7 @@ mod tests { chain_keys.insert(8, key_pair2.clone()); let (key_pairs2, cert2) = - generate_cert_with(10, chain_keys, far_far_future * 2, far_far_future); + generate_cert_with(10, chain_keys, far_far_future * 2, far_far_future).unwrap(); let st = Box::new(InMemoryStorage::new()); let mut graph = TrustGraph::new(st); @@ -424,7 +439,7 @@ mod tests { graph.add_root_weight(root2_pk.into(), 0); graph.add(cert1, cur_time).unwrap(); - let node2 = graph.get(key_pair2.public_key()).unwrap(); + let node2 = graph.get(key_pair2.public_key()).unwrap().unwrap(); let auth_by_kp1 = node2 .authorizations() .find(|a| a.issued_by == key_pair1.public_key()) @@ -434,7 +449,7 @@ mod tests { graph.add(cert2, cur_time).unwrap(); - let node2 = graph.get(key_pair2.public_key()).unwrap(); + let node2 = graph.get(key_pair2.public_key()).unwrap().unwrap(); let auth_by_kp1 = node2 .authorizations() .find(|a| a.issued_by == key_pair1.public_key()) @@ -445,7 +460,7 @@ mod tests { #[test] fn test_one_cert_in_graph() { - let (key_pairs, cert1) = generate_cert_with_len(10, HashMap::new()); + let (key_pairs, cert1) = generate_cert_with_len(10, HashMap::new()).unwrap(); let last_trust = cert1.chain[9].clone(); let st = Box::new(InMemoryStorage::new()); @@ -456,16 +471,16 @@ mod tests { graph.add(cert1, current_time()).unwrap(); - let w1 = graph.weight(key_pairs[0].public_key()).unwrap(); + let w1 = graph.weight(key_pairs[0].public_key()).unwrap().unwrap(); assert_eq!(w1, 1); - let w2 = graph.weight(key_pairs[1].public_key()).unwrap(); + let w2 = graph.weight(key_pairs[1].public_key()).unwrap().unwrap(); assert_eq!(w2, 2); - let w3 = graph.weight(key_pairs[9].public_key()).unwrap(); + let w3 = graph.weight(key_pairs[9].public_key()).unwrap().unwrap(); assert_eq!(w3, 10); - let node = graph.get(key_pairs[9].public_key()).unwrap(); + let node = graph.get(key_pairs[9].public_key()).unwrap().unwrap(); let auths: Vec<&Auth> = node.authorizations().collect(); assert_eq!(auths.len(), 1); @@ -483,14 +498,14 @@ mod tests { chain_keys.insert(5, key_pair2.clone()); chain_keys.insert(7, key_pair3.clone()); - let (key_pairs1, cert1) = generate_cert_with_len(10, chain_keys); + let (key_pairs1, cert1) = generate_cert_with_len(10, chain_keys).unwrap(); let mut chain_keys = HashMap::new(); chain_keys.insert(7, key_pair1.clone()); chain_keys.insert(6, key_pair2.clone()); chain_keys.insert(5, key_pair3.clone()); - let (key_pairs2, cert2) = generate_cert_with_len(10, chain_keys); + let (key_pairs2, cert2) = generate_cert_with_len(10, chain_keys).unwrap(); let st = Box::new(InMemoryStorage::new()); let mut graph = TrustGraph::new(st); @@ -510,12 +525,12 @@ mod tests { let revoke2 = Revoke::create(&key_pairs2[5], key_pairs2[6].public_key(), current_time()); graph.revoke(revoke2).unwrap(); - let w1 = graph.weight(key_pair1.public_key()).unwrap(); + let w1 = graph.weight(key_pair1.public_key()).unwrap().unwrap(); // all upper trusts are revoked for this public key - let w2 = graph.weight(key_pair2.public_key()); - let w3 = graph.weight(key_pair3.public_key()).unwrap(); - let w_last1 = graph.weight(last_pk1).unwrap(); - let w_last2 = graph.weight(last_pk2).unwrap(); + let w2 = graph.weight(key_pair2.public_key()).unwrap(); + let w3 = graph.weight(key_pair3.public_key()).unwrap().unwrap(); + let w_last1 = graph.weight(last_pk1).unwrap().unwrap(); + let w_last2 = graph.weight(last_pk2).unwrap().unwrap(); assert_eq!(w1, 4); assert_eq!(w2.is_none(), true); @@ -526,7 +541,7 @@ mod tests { #[test] fn test_get_one_cert() { - let (key_pairs, cert) = generate_cert_with_len(5, HashMap::new()); + let (key_pairs, cert) = generate_cert_with_len(5, HashMap::new()).unwrap(); let st = Box::new(InMemoryStorage::new()); let mut graph = TrustGraph::new(st); @@ -535,7 +550,7 @@ mod tests { graph.add(cert.clone(), current_time()).unwrap(); - let certs = graph.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk]); + let certs = graph.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk]).unwrap(); assert_eq!(certs.len(), 1); assert_eq!(certs[0], cert); @@ -543,7 +558,7 @@ mod tests { #[test] fn test_chain_from_root_to_another_root() { - let (_, cert) = generate_cert_with_len(6, HashMap::new()); + let (_, cert) = generate_cert_with_len(6, HashMap::new()).unwrap(); let st = Box::new(InMemoryStorage::new()); let mut graph = TrustGraph::new(st); @@ -555,7 +570,7 @@ mod tests { graph.add(cert.clone(), current_time()).unwrap(); let t = cert.chain[5].clone(); - let certs = graph.get_all_certs(t.issued_for, &[]); + let certs = graph.get_all_certs(t.issued_for, &[]).unwrap(); assert_eq!(certs.len(), 1); } @@ -571,21 +586,21 @@ mod tests { chain_keys.insert(3, key_pair2.clone()); chain_keys.insert(4, key_pair3.clone()); - let (key_pairs1, cert1) = generate_cert_with_len(5, chain_keys); + let (key_pairs1, cert1) = generate_cert_with_len(5, chain_keys).unwrap(); let mut chain_keys = HashMap::new(); chain_keys.insert(4, key_pair1.clone()); chain_keys.insert(3, key_pair2.clone()); chain_keys.insert(2, key_pair3.clone()); - let (key_pairs2, cert2) = generate_cert_with_len(5, chain_keys); + let (key_pairs2, cert2) = generate_cert_with_len(5, chain_keys).unwrap(); let mut chain_keys = HashMap::new(); chain_keys.insert(3, key_pair1.clone()); chain_keys.insert(4, key_pair2.clone()); chain_keys.insert(2, key_pair3.clone()); - let (key_pairs3, cert3) = generate_cert_with_len(5, chain_keys); + let (key_pairs3, cert3) = generate_cert_with_len(5, chain_keys).unwrap(); let st = Box::new(InMemoryStorage::new()); let mut graph = TrustGraph::new(st); @@ -602,17 +617,17 @@ mod tests { let roots_values = [root1_pk, root2_pk, root3_pk]; - let certs1 = graph.get_all_certs(key_pair1.public_key(), &roots_values); + let certs1 = graph.get_all_certs(key_pair1.public_key(), &roots_values).unwrap(); let lenghts1: Vec = certs1.iter().map(|c| c.chain.len()).collect(); let check_lenghts1: Vec = vec![3, 4, 4, 5, 5]; assert_eq!(lenghts1, check_lenghts1); - let certs2 = graph.get_all_certs(key_pair2.public_key(), &roots_values); + let certs2 = graph.get_all_certs(key_pair2.public_key(), &roots_values).unwrap(); let lenghts2: Vec = certs2.iter().map(|c| c.chain.len()).collect(); let check_lenghts2: Vec = vec![4, 4, 4, 5, 5]; assert_eq!(lenghts2, check_lenghts2); - let certs3 = graph.get_all_certs(key_pair3.public_key(), &roots_values); + let certs3 = graph.get_all_certs(key_pair3.public_key(), &roots_values).unwrap(); let lenghts3: Vec = certs3.iter().map(|c| c.chain.len()).collect(); let check_lenghts3: Vec = vec![3, 3, 5]; assert_eq!(lenghts3, check_lenghts3); From e2183b4180b42db0bf6023cfbb6f19f128a347a4 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Tue, 9 Feb 2021 13:26:44 +0300 Subject: [PATCH 03/19] huge mess with errors, but it works! --- src/certificate.rs | 64 +++++++++++++------- src/revoke.rs | 6 +- src/trust.rs | 33 ++++++----- src/trust_graph.rs | 116 +++++++++++++++++++++++++++---------- src/trust_graph_storage.rs | 41 ++++++++----- 5 files changed, 178 insertions(+), 82 deletions(-) diff --git a/src/certificate.rs b/src/certificate.rs index 02b3226..ab92c9b 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -14,11 +14,16 @@ * limitations under the License. */ +use crate::certificate::CerificateError::{ + CertificateLengthError, DecodeError, ExpirationError, KeyInCertificateError, MalformedRoot, + NoTrustedRoot, VerificationError, +}; use crate::trust::{Trust, TRUST_LEN}; use fluence_identity::key_pair::KeyPair; use fluence_identity::public_key::PublicKey; use std::str::FromStr; use std::time::Duration; +use thiserror::Error as ThisError; /// Serialization format of a certificate. /// TODO @@ -33,16 +38,27 @@ pub struct Certificate { pub chain: Vec, } -#[derive(Debug)] +#[derive(ThisError, Debug)] pub enum CerificateError { + #[error("Error while decoding a certificate: {0}")] DecodeError(String), + #[error("Certificate is expired. Issued at {issued_at:?} and expired at {expires_at:?}")] ExpirationError { expires_at: String, - issued_at: String + issued_at: String, }, + #[error("Certificate does not contain a trusted root.")] + NoTrustedRoot, + #[error("Root trust did not pass verification: {0}")] + MalformedRoot(String), + #[error("There is no `issued_by` public key in a certificate")] KeyInCertificateError, + #[error("The certificate must have at least 1 trust")] CertificateLengthError, - Unexpected(String) + #[error("Trust {0} in chain did not pass verification: {1}")] + VerificationError(usize, String), + #[error("Unexpected error: {0}")] + Unexpected(String), } impl Certificate { @@ -79,7 +95,10 @@ impl Certificate { cur_time: Duration, ) -> Result { if expires_at.lt(&issued_at) { - return Err("Expiration time should be greater than issued time.".to_string()); + return Err(ExpirationError { + expires_at: format!("{:?}", expires_at), + issued_at: format!("{:?}", issued_at), + }); } // first, verify given certificate @@ -100,7 +119,7 @@ impl Certificate { } if previous_trust_num == -1 { - return Err("Your public key should be in certificate.".to_string()); + return Err(KeyInCertificateError); }; // splitting old chain to add new trust after given public key @@ -126,15 +145,15 @@ impl Certificate { let chain = &cert.chain; if chain.is_empty() { - return Err("The certificate must have at least 1 trust".to_string()); + return Err(CertificateLengthError); } // check root trust and its existence in trusted roots list let root = &chain[0]; Trust::verify(root, &root.issued_for, cur_time) - .map_err(|e| format!("Root trust did not pass verification: {}", e))?; + .map_err(|e| MalformedRoot(format!("{}", e)))?; if !trusted_roots.contains(&root.issued_for) { - return Err("Certificate does not contain a trusted root.".to_string()); + return Err(NoTrustedRoot); } // check if every element in a chain is not expired and has the correct signature @@ -143,12 +162,8 @@ impl Certificate { let trust_giver = &chain[trust_id - 1]; - Trust::verify(trust, &trust_giver.issued_for, cur_time).map_err(|e| { - format!( - "Trust {} in chain did not pass verification: {}", - trust_id, e - ) - })?; + Trust::verify(trust, &trust_giver.issued_for, cur_time) + .map_err(|e| VerificationError(trust_id, format!("{}", e)))?; } Ok(()) @@ -174,13 +189,13 @@ impl Certificate { pub fn decode(arr: &[u8]) -> Result { let trusts_offset = arr.len() - 2 - 4; if trusts_offset % TRUST_LEN != 0 { - return Err("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust. ".to_string()); + return Err(DecodeError("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust. ".to_string())); } let number_of_trusts = trusts_offset / TRUST_LEN; if number_of_trusts < 2 { - return Err("The certificate must have at least 2 trusts.".to_string()); + return Err(CertificateLengthError); } // TODO do match different formats and versions @@ -193,7 +208,7 @@ impl Certificate { let from = i * TRUST_LEN + 6; let to = (i + 1) * TRUST_LEN + 6; let slice = &arr[from..to]; - let t = Trust::decode(slice)?; + let t = Trust::decode(slice).map_err(|e| DecodeError(format!("{}", e)))?; chain.push(t); } @@ -213,7 +228,7 @@ impl std::fmt::Display for Certificate { } impl FromStr for Certificate { - type Err = String; + type Err = CerificateError; fn from_str(s: &str) -> Result { let str_lines: Vec<&str> = s.lines().collect(); @@ -223,7 +238,10 @@ impl FromStr for Certificate { let _version = str_lines[1]; if (str_lines.len() - 2) % 4 != 0 { - return Err(format!("Incorrect format of the certificate: {}", s)); + return Err(DecodeError(format!( + "Incorrect format of the certificate: {}", + s + ))); } let num_of_trusts = (str_lines.len() - 2) / 4; @@ -235,7 +253,13 @@ impl FromStr for Certificate { str_lines[i + 1], str_lines[i + 2], str_lines[i + 3], - )?; + ) + .map_err(|e| { + DecodeError(format!( + "Cannot convert trust number {} from string: {}", + i, e + )) + })?; trusts.push(trust); } diff --git a/src/revoke.rs b/src/revoke.rs index 5cabde5..35aa8f9 100644 --- a/src/revoke.rs +++ b/src/revoke.rs @@ -14,18 +14,18 @@ * limitations under the License. */ +use crate::revoke::RevokeError::IncorrectSignature; use crate::trust::{EXPIRATION_LEN, PK_LEN}; +use ed25519_dalek::SignatureError; use fluence_identity::key_pair::KeyPair; use fluence_identity::public_key::PublicKey; use fluence_identity::signature::Signature; use serde::{Deserialize, Serialize}; use std::time::Duration; -use ed25519_dalek::SignatureError; -use crate::revoke::RevokeError::IncorrectSignature; #[derive(Debug)] pub enum RevokeError { - IncorrectSignature(SignatureError) + IncorrectSignature(SignatureError), } /// "A document" that cancels trust created before. diff --git a/src/trust.rs b/src/trust.rs index b57635a..74a5721 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -14,6 +14,7 @@ * limitations under the License. */ +use crate::trust::TrustError::{DecodeError, SignatureError}; use derivative::Derivative; use fluence_identity::key_pair::KeyPair; use fluence_identity::public_key::PublicKey; @@ -22,7 +23,6 @@ use serde::{Deserialize, Serialize}; use std::convert::TryInto; use std::time::Duration; use thiserror::Error as ThisError; -use crate::trust::TrustError::{SignatureError, DecodeError}; pub const SIG_LEN: usize = 64; pub const PK_LEN: usize = 32; @@ -69,7 +69,7 @@ pub enum TrustError { /// Errors occured on trust decoding from differrent formats #[error("{0:?}")] - DecodeError(String) + DecodeError(String), } impl Trust { @@ -107,9 +107,13 @@ impl Trust { } /// Verifies that authorization is cryptographically correct. - pub fn verify(trust: &Trust, issued_by: &PublicKey, cur_time: Duration) -> Result<(), TrustError> { + pub fn verify( + trust: &Trust, + issued_by: &PublicKey, + cur_time: Duration, + ) -> Result<(), TrustError> { if trust.expires_at < cur_time { - return TrustError::Expired(trust.expires_at, cur_time); + return Err(TrustError::Expired(trust.expires_at, cur_time)); } let msg: &[u8] = @@ -151,18 +155,20 @@ impl Trust { #[allow(dead_code)] pub fn decode(arr: &[u8]) -> Result { if arr.len() != TRUST_LEN { - return DecodeError( + return Err(DecodeError( format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}", arr.len()) - ); + )); } - let pk = PublicKey::from_bytes(&arr[0..PK_LEN]) - .map_err(|err| DecodeError(format!("Cannot decode a public key: {}", err.to_string())))?; + let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(|err| { + DecodeError(format!("Cannot decode a public key: {}", err.to_string())) + })?; let signature = &arr[PK_LEN..PK_LEN + SIG_LEN]; - let signature = Signature::from_bytes(signature) - .map_err(|err| DecodeError(format!("Cannot decode a signature: {}", err.to_string())))?; + let signature = Signature::from_bytes(signature).map_err(|err| { + DecodeError(format!("Cannot decode a signature: {}", err.to_string())) + })?; let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN]; let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap()); @@ -182,10 +188,10 @@ impl Trust { fn bs58_str_to_vec(str: &str, field: &str) -> Result, TrustError> { bs58::decode(str).into_vec().map_err(|e| { - format!( + DecodeError(format!( "Cannot decode `{}` from base58 format in the trust '{}': {}", field, str, e - ) + )) }) } @@ -216,7 +222,8 @@ impl Trust { // 64 bytes signature let signature = Self::bs58_str_to_vec(signature, "signature")?; - let signature = Signature::from_bytes(&signature).map_err(|err| DecodeError(err.to_string()))?; + let signature = + Signature::from_bytes(&signature).map_err(|err| DecodeError(err.to_string()))?; // Duration let expires_at = Self::str_to_duration(expires_at, "expires_at")?; diff --git a/src/trust_graph.rs b/src/trust_graph.rs index ce9ffdf..a099e26 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -14,21 +14,23 @@ * limitations under the License. */ -use crate::certificate::{Certificate, CerificateError}; +use crate::certificate::CerificateError::{CertificateLengthError, Unexpected}; +use crate::certificate::{CerificateError, Certificate}; use crate::public_key_hashable::PublicKeyHashable; use crate::revoke::Revoke; +use crate::revoke::RevokeError; use crate::trust::Trust; -use crate::trust_graph_storage::{Storage, StorageError}; +use crate::trust_graph::TrustGraphError::{ + CertificateCheckError, InternalStorageError, NoRoot, RevokeCheckError, +}; +use crate::trust_graph_storage::Storage; use crate::trust_node::{Auth, TrustNode}; use fluence_identity::public_key::PublicKey; use std::borrow::Borrow; use std::collections::{HashSet, VecDeque}; -use std::time::Duration; -use crate::trust_graph::TrustGraphError::{InternalStorageError, CertificateCheckError, NoRoot, RevokeCheckError}; -use crate::certificate::CerificateError::{CertificateLengthError, Unexpected}; -use crate::revoke::RevokeError; use std::convert::{From, Into}; use std::result::Result; +use std::time::Duration; /// for simplicity, we store `n` where Weight = 1/n^2 pub type Weight = u32; @@ -37,7 +39,10 @@ pub type Weight = u32; /// TODO serialization/deserialization /// TODO export a certificate from graph #[allow(dead_code)] -pub struct TrustGraph where S: Storage { +pub struct TrustGraph +where + S: Storage, +{ storage: Box, } @@ -62,19 +67,30 @@ impl From for TrustGraphError { } #[allow(dead_code)] -impl TrustGraph where S: Storage { +impl TrustGraph +where + S: Storage, +{ pub fn new(storage: Box) -> Self { Self { storage: storage } } /// Insert new root weight - pub fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), TrustGraphError> { - self.storage.add_root_weight(pk, weight).map_err(|e| InternalStorageError(e.into())) + pub fn add_root_weight( + &mut self, + pk: PublicKeyHashable, + weight: Weight, + ) -> Result<(), TrustGraphError> { + self.storage + .add_root_weight(pk, weight) + .map_err(|e| InternalStorageError(e.into())) } /// Get trust by public key pub fn get(&self, pk: PublicKey) -> Result, TrustGraphError> { - self.storage.get(&pk.into()).map_err(|e| InternalStorageError(e.into())) + self.storage + .get(&pk.into()) + .map_err(|e| InternalStorageError(e.into())) } // TODO: remove cur_time from api, leave it for tests only @@ -95,18 +111,26 @@ impl TrustGraph where S: Storage { Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?; let mut chain = cert.borrow().chain.iter(); - let root_trust = chain.next().ok_or("empty chain").map_err(|e| InternalStorageError(e.into()))?; + let root_trust = chain + .next() + .ok_or("empty chain") + .map_err(|e| InternalStorageError(e.into()))?; let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into(); // Insert new TrustNode for this root_pk if there wasn't one - if self.storage.get(&root_pk).map_err(|e| InternalStorageError(e.into()))?.is_none() { + if self + .storage + .get(&root_pk) + .map_err(|e| InternalStorageError(e.into()))? + .is_none() + { let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time); let root_auth = Auth { trust: root_trust.clone(), issued_by: root_trust.issued_for.clone(), }; trust_node.update_auth(root_auth); - self.storage.insert(root_pk, trust_node); + self.storage.insert(root_pk, trust_node).map_err(|e| InternalStorageError(e.into()))?; } // Insert remaining trusts to the graph @@ -120,7 +144,7 @@ impl TrustGraph where S: Storage { }; self.storage - .update_auth(&pk, auth, &root_trust.issued_for, cur_time); + .update_auth(&pk, auth, &root_trust.issued_for, cur_time).map_err(|e| InternalStorageError(e.into()))?; previous_trust = trust; } @@ -133,7 +157,11 @@ impl TrustGraph where S: Storage { where P: Borrow, { - if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))? { + if let Some(weight) = self + .storage + .get_root_weight(pk.borrow().as_ref()) + .map_err(|e| InternalStorageError(e.into()))? + { return Ok(Some(weight)); } @@ -163,7 +191,7 @@ impl TrustGraph where S: Storage { // if there are no certificates for the given public key, there is no info about this public key // or some elements of possible certificate chains was revoked if certs.peek().is_none() { - return Ok(None) + return Ok(None); } let mut weight = std::u32::MAX; @@ -171,13 +199,17 @@ impl TrustGraph where S: Storage { for cert in certs { let c = cert.borrow(); - let first = c.chain.first().ok_or(CertificateCheckError(CertificateLengthError))?; + let first = c + .chain + .first() + .ok_or(CertificateCheckError(CertificateLengthError))?; let root_weight = self .storage .get_root_weight(first.issued_for.as_ref()) // This panic shouldn't happen // TODO: why? - .map_err(|e| InternalStorageError(e.into()))?.ok_or(NoRoot)?; + .map_err(|e| InternalStorageError(e.into()))? + .ok_or(NoRoot)?; // certificate weight = root weight + 1 * every other element in the chain // (except root, so the formula is `root weight + chain length - 1`) @@ -220,9 +252,10 @@ impl TrustGraph where S: Storage { .storage .get(&last.issued_by.clone().into()) .map_err(|e| InternalStorageError(e.into()))? - .ok_or( - CertificateCheckError(Unexpected("there cannot be paths without any nodes after adding verified certificates".to_string())), - )? + .ok_or(CertificateCheckError(Unexpected( + "there cannot be paths without any nodes after adding verified certificates" + .to_string(), + )))? .authorizations() .cloned() .collect(); @@ -258,15 +291,25 @@ impl TrustGraph where S: Storage { // TODO: remove `roots` argument from api, leave it for tests and internal usage only /// Get all possible certificates where `issued_for` will be the last element of the chain /// and one of the destinations is the root of this chain. - pub fn get_all_certs

(&self, issued_for: P, roots: &[PublicKey]) -> Result, TrustGraphError> + pub fn get_all_certs

( + &self, + issued_for: P, + roots: &[PublicKey], + ) -> Result, TrustGraphError> where P: Borrow, { // get all auths (edges) for issued public key - let issued_for_node = self.storage.get(issued_for.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))?; + let issued_for_node = self + .storage + .get(issued_for.borrow().as_ref()) + .map_err(|e| InternalStorageError(e.into()))?; let roots = roots.iter().map(|pk| pk.as_ref()); - let keys = self.storage.root_keys().map_err(|e| InternalStorageError(e.into()))?; + let keys = self + .storage + .root_keys() + .map_err(|e| InternalStorageError(e.into()))?; let roots = keys.iter().chain(roots).collect(); match issued_for_node { @@ -299,7 +342,9 @@ impl TrustGraph where S: Storage { let pk: PublicKeyHashable = revoke.pk.clone().into(); - self.storage.revoke(&pk, revoke).map_err(|e| InternalStorageError(e.into())) + self.storage + .revoke(&pk, revoke) + .map_err(|e| InternalStorageError(e.into())) } /// Check information about new certificates and about revoked certificates. @@ -421,7 +466,8 @@ mod tests { chain_keys.insert(5, key_pair1.clone()); chain_keys.insert(6, key_pair2.clone()); - let (key_pairs1, cert1) = generate_cert_with(10, chain_keys, far_future * 2, far_future).expect(""); + let (key_pairs1, cert1) = + generate_cert_with(10, chain_keys, far_future * 2, far_future).expect(""); // Use key_pair1 and key_pair2 for 7th and 8th trust in the cert chain let mut chain_keys = HashMap::new(); @@ -550,7 +596,9 @@ mod tests { graph.add(cert.clone(), current_time()).unwrap(); - let certs = graph.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk]).unwrap(); + let certs = graph + .get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk]) + .unwrap(); assert_eq!(certs.len(), 1); assert_eq!(certs[0], cert); @@ -617,17 +665,23 @@ mod tests { let roots_values = [root1_pk, root2_pk, root3_pk]; - let certs1 = graph.get_all_certs(key_pair1.public_key(), &roots_values).unwrap(); + let certs1 = graph + .get_all_certs(key_pair1.public_key(), &roots_values) + .unwrap(); let lenghts1: Vec = certs1.iter().map(|c| c.chain.len()).collect(); let check_lenghts1: Vec = vec![3, 4, 4, 5, 5]; assert_eq!(lenghts1, check_lenghts1); - let certs2 = graph.get_all_certs(key_pair2.public_key(), &roots_values).unwrap(); + let certs2 = graph + .get_all_certs(key_pair2.public_key(), &roots_values) + .unwrap(); let lenghts2: Vec = certs2.iter().map(|c| c.chain.len()).collect(); let check_lenghts2: Vec = vec![4, 4, 4, 5, 5]; assert_eq!(lenghts2, check_lenghts2); - let certs3 = graph.get_all_certs(key_pair3.public_key(), &roots_values).unwrap(); + let certs3 = graph + .get_all_certs(key_pair3.public_key(), &roots_values) + .unwrap(); let lenghts3: Vec = certs3.iter().map(|c| c.chain.len()).collect(); let check_lenghts3: Vec = vec![3, 3, 5]; assert_eq!(lenghts3, check_lenghts3); diff --git a/src/trust_graph_storage.rs b/src/trust_graph_storage.rs index d171d78..d37c9db 100644 --- a/src/trust_graph_storage.rs +++ b/src/trust_graph_storage.rs @@ -1,26 +1,24 @@ use crate::public_key_hashable::PublicKeyHashable; use crate::revoke::Revoke; use crate::trust_graph::Weight; +use crate::trust_graph_storage::InMemoryStorageError::RevokeError; use crate::trust_node::{Auth, TrustNode}; use fluence_identity::public_key::PublicKey; use std::collections::HashMap; use std::time::Duration; use thiserror::Error as ThisError; -use crate::trust_graph_storage::InMemoryStorageError::RevokeError; - -pub trait StorageError {} - +pub trait StorageError: std::error::Error {} pub trait Storage { - type Error: StorageError + Into; fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error>; fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error>; fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result, Self::Error>; - fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error>; + fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) + -> Result<(), Self::Error>; fn root_keys(&self) -> Result, Self::Error>; fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error>; fn update_auth( @@ -62,15 +60,19 @@ impl InMemoryStorage { #[derive(ThisError, Debug)] pub enum InMemoryStorageError { - - #[error("{0:?}")] - RevokeError(String) + #[error("InMemoryStorageError::RevokeError {0:?}")] + RevokeError(String), } -impl StorageError for InMemoryStorage {} +impl From for String { + fn from(err: InMemoryStorageError) -> Self { + err.into() + } +} + +impl StorageError for InMemoryStorageError {} impl Storage for InMemoryStorage { - type Error = InMemoryStorageError; fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { @@ -86,8 +88,13 @@ impl Storage for InMemoryStorage { Ok(self.root_weights.get(pk).cloned()) } - fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error> { - Ok(&self.root_weights.insert(pk, weight)); + fn add_root_weight( + &mut self, + pk: PublicKeyHashable, + weight: Weight, + ) -> Result<(), Self::Error> { + &self.root_weights.insert(pk, weight); + Ok({}) } fn root_keys(&self) -> Result, Self::Error> { @@ -100,7 +107,9 @@ impl Storage for InMemoryStorage { trust_node.update_revoke(revoke); Ok(()) } - None => RevokeError("There is no trust with such PublicKey".to_string()), + None => Err(RevokeError( + "There is no trust with such PublicKey".to_string(), + )), } } @@ -110,15 +119,17 @@ impl Storage for InMemoryStorage { auth: Auth, issued_for: &PublicKey, cur_time: Duration, - ) { + ) -> Result<(), InMemoryStorageError> { match self.nodes.get_mut(&pk) { Some(trust_node) => { trust_node.update_auth(auth); + Ok({}) } None => { let mut trust_node = TrustNode::new(issued_for.clone(), cur_time); trust_node.update_auth(auth); self.nodes.insert(pk.clone(), trust_node); + Ok({}) } } } From 7ae745c3c3af732efbf9abf61311a469013909d8 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Tue, 9 Feb 2021 14:31:41 +0300 Subject: [PATCH 04/19] wasm with error handling compiles --- bin/Cargo.lock | 1 + bin/Cargo.toml | 1 + bin/src/service_api.rs | 13 ---- bin/src/storage_impl.rs | 147 ++++++++++++++++++++++++------------- src/certificate.rs | 2 +- src/lib.rs | 2 +- src/trust_graph_storage.rs | 2 +- 7 files changed, 99 insertions(+), 69 deletions(-) diff --git a/bin/Cargo.lock b/bin/Cargo.lock index 9dc6c39..425b0ae 100644 --- a/bin/Cargo.lock +++ b/bin/Cargo.lock @@ -1594,6 +1594,7 @@ dependencies = [ "serde_bencode", "serde_json", "sqlite", + "thiserror", "trust-graph", ] diff --git a/bin/Cargo.toml b/bin/Cargo.toml index 51ff958..0c614ca 100644 --- a/bin/Cargo.toml +++ b/bin/Cargo.toml @@ -26,3 +26,4 @@ rmp-serde = "0.15.0" bincode = "1.3.1" serde_bencode = "^0.2.3" sqlite = "0.25.3" +thiserror = "1.0.23" diff --git a/bin/src/service_api.rs b/bin/src/service_api.rs index fbaee3b..5ba6d5f 100644 --- a/bin/src/service_api.rs +++ b/bin/src/service_api.rs @@ -25,19 +25,6 @@ fn insert_cert(certificate: String, duration: u64) -> InsertResult { } } -#[fce] -fn looper() { - - let second = std::time::Duration::from_millis(1000); - - let mut a = 0; - while true { - std::thread::sleep(second); - a = a + 1; - log::info!("{}", a) - } -} - #[fce] fn test() -> String { let mut tg = get_data().lock(); diff --git a/bin/src/storage_impl.rs b/bin/src/storage_impl.rs index f672bce..3ce2ef8 100644 --- a/bin/src/storage_impl.rs +++ b/bin/src/storage_impl.rs @@ -9,14 +9,19 @@ use parking_lot::Mutex; use fce_sqlite_connector; use fce_sqlite_connector::Connection; use fce_sqlite_connector::Value; +use fce_sqlite_connector::Error as InternalSqliteError; use std::str::FromStr; use std::time::Duration; -use trust_graph::{Auth, PublicKeyHashable, Revoke, Storage, TrustGraph, TrustNode, Weight}; -use std::ops::Deref; +use trust_graph::{Auth, PublicKeyHashable, Revoke, Storage, TrustGraph, TrustNode, Weight, StorageError}; +use thiserror::Error as ThisError; +use crate::storage_impl::SqliteStorageError::{SqliteError, EncodeError, ConvertionError, DecodeError, Unexpected, RevokeError}; +use rmp_serde::encode::Error as RmpEncodeError; +use rmp_serde::decode::Error as RmpDecodeError; +use std::convert::From; -static INSTANCE: OnceCell> = OnceCell::new(); +static INSTANCE: OnceCell>> = OnceCell::new(); -pub fn get_data() -> &'static Mutex { +pub fn get_data() -> &'static Mutex> { INSTANCE.get_or_init(|| { let db_path = "/tmp/users123123.sqlite"; let connection = fce_sqlite_connector::open(db_path).unwrap(); @@ -46,127 +51,163 @@ impl SqliteStorage { } } +#[derive(ThisError, Debug)] +pub enum SqliteStorageError { + #[error("Unexpected: {0}")] + Unexpected(String), + #[error("{0}")] + SqliteError(InternalSqliteError), + #[error("{0}")] + EncodeError(String), + #[error("{0}")] + DecodeError(String), + #[error("There is no entry for {0}")] + ConvertionError(String), + #[error("Cannot revoke a trust: {0}")] + RevokeError(String) +} + +impl From for SqliteStorageError { + fn from(err: InternalSqliteError) -> Self { + SqliteError(err) + } +} + +impl From for SqliteStorageError { + fn from(err: RmpEncodeError) -> Self { + EncodeError(format!("{}", err)) + } +} + +impl From for SqliteStorageError { + fn from(err: RmpDecodeError) -> Self { + DecodeError(format!("{}", err)) + } +} + +impl From for String { + fn from(err: SqliteStorageError) -> Self { + err.into() + } +} + +impl StorageError for SqliteStorageError {} + impl Storage for SqliteStorage { - fn get(&self, pk: &PublicKeyHashable) -> Option { + + type Error = SqliteStorageError; + + fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { let mut cursor = self .connection - .prepare("SELECT trustnode FROM trustnodes WHERE public_key = ?") - .expect("unexpected: 'get' request should be correct") + .prepare("SELECT trustnode FROM trustnodes WHERE public_key = ?")? .cursor(); cursor - .bind(&[Value::String(format!("{}", pk))]) - .expect("unexpected: 'public_key' field should be string"); + .bind(&[Value::String(format!("{}", pk))])?; match cursor.next().unwrap() { Some(r) => { log::info!("row: {:?}", r); let tn_bin: &[u8] = r[0] - .as_binary() - .expect("unexpected: 'trustnode' in a table should be as binary"); + .as_binary().ok_or(ConvertionError("cannot get trustnode as binary".to_string()))?; log::info!("binary: {:?}", tn_bin); - let trust_node: TrustNode = rmp_serde::from_read_ref(tn_bin) - // let trust_node: TrustNode = bincode::deserialize(tn_bin) - // let trust_node: TrustNode = serde_bencode::de::from_bytes(tn_bin) - .expect("unexpected: 'trustnode' should be as correct binary"); + let trust_node: TrustNode = rmp_serde::from_read_ref(tn_bin)?; log::info!("trustnode: {:?}", trust_node); - Some(trust_node) + Ok(Some(trust_node)) } - None => None, + None => Ok(None), } } - fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) { + fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error> { let mut cursor = self .connection - .prepare("INSERT OR REPLACE INTO trustnodes VALUES (?, ?)") - .unwrap() + .prepare("INSERT OR REPLACE INTO trustnodes VALUES (?, ?)")? .cursor(); - let tn_vec = rmp_serde::to_vec(&node).unwrap(); - // let tn_vec = bincode::serialize(&node).unwrap(); - let tn_vec = serde_bencode::to_bytes(&node).unwrap(); + let tn_vec = rmp_serde::to_vec(&node)?; log::info!("insert: {:?}", tn_vec); cursor - .bind(&[Value::String(format!("{}", pk)), Value::Binary(tn_vec)]) - .unwrap(); + .bind(&[Value::String(format!("{}", pk)), Value::Binary(tn_vec)])?; - cursor.next().unwrap(); + cursor.next()?; + Ok({}) } - fn get_root_weight(&self, pk: &PublicKeyHashable) -> Option { + fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { let mut cursor = self .connection - .prepare("SELECT public_key,weight FROM roots WHERE public_key = ?") - .unwrap() + .prepare("SELECT public_key,weight FROM roots WHERE public_key = ?")? .cursor(); - cursor.bind(&[Value::String(format!("{}", pk))]).unwrap(); + cursor.bind(&[Value::String(format!("{}", pk))])?; - if let Some(row) = cursor.next().unwrap() { + if let Some(row) = cursor.next()? { log::info!("row: {:?}", row); - let w = u32::try_from(row[1].as_integer().unwrap()).unwrap(); + let w = u32::try_from(row[1].as_integer().ok_or(ConvertionError("cannot get weight as integer".to_string()))?) + .map_err(|e| Unexpected(format!("Unexpected. Cannot convert weight to u32: {}", e)))?; - Some(w) + Ok(Some(w)) } else { - None + Ok(None) } } - fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) { + fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error> { log::info!("add root: {} weight: {}", pk, weight); let mut cursor = self .connection - .prepare("INSERT OR REPLACE INTO roots VALUES (?, ?)") - .unwrap() + .prepare("INSERT OR REPLACE INTO roots VALUES (?, ?)")? .cursor(); cursor .bind(&[ Value::String(format!("{}", pk)), Value::Integer(i64::from(weight)), - ]) - .unwrap(); + ])?; - cursor.next().unwrap(); + cursor.next()?; + Ok({}) } - fn root_keys(&self) -> Vec { + fn root_keys(&self) -> Result, Self::Error> { let mut cursor = self .connection - .prepare("SELECT public_key,weight FROM roots") - .unwrap() + .prepare("SELECT public_key,weight FROM roots")? .cursor(); let mut roots = vec![]; - while let Some(row) = cursor.next().unwrap() { + while let Some(row) = cursor.next()? { log::info!("row: {:?}", row); + let pk = row[0].as_string() + .ok_or(ConvertionError("cannot get public key as binary".to_string()))?; let pk: PublicKeyHashable = - PublicKeyHashable::from_str(row[0].as_string().unwrap()).unwrap(); + PublicKeyHashable::from_str(pk).map_err(|e| DecodeError(e.to_string()))?; roots.push(pk) } - roots + Ok(roots) } - fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), String> { - match self.get(&pk) { + fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error> { + match self.get(&pk)? { Some(mut trust_node) => { trust_node.update_revoke(revoke); - self.insert(pk.clone(), trust_node); + self.insert(pk.clone(), trust_node)?; Ok(()) } - None => Err("There is no trust with such PublicKey".to_string()), + None => Err(RevokeError("There is no trust with such PublicKey".to_string())), } } @@ -176,8 +217,8 @@ impl Storage for SqliteStorage { auth: Auth, issued_for: &PublicKey, cur_time: Duration, - ) { - match self.get(&pk) { + ) -> Result<(), Self::Error> { + match self.get(&pk)? { Some(mut trust_node) => { trust_node.update_auth(auth); self.insert(pk.clone(), trust_node) @@ -185,7 +226,7 @@ impl Storage for SqliteStorage { None => { let mut trust_node = TrustNode::new(issued_for.clone(), cur_time); trust_node.update_auth(auth); - self.insert(pk.clone(), trust_node); + self.insert(pk.clone(), trust_node) } } } diff --git a/src/certificate.rs b/src/certificate.rs index ab92c9b..ecd7d39 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -42,7 +42,7 @@ pub struct Certificate { pub enum CerificateError { #[error("Error while decoding a certificate: {0}")] DecodeError(String), - #[error("Certificate is expired. Issued at {issued_at:?} and expired at {expires_at:?}")] + #[error("Certificate is expired. Issued at {issued_at} and expired at {expires_at}")] ExpirationError { expires_at: String, issued_at: String, diff --git a/src/lib.rs b/src/lib.rs index 6b73d6e..bd09408 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,5 +42,5 @@ pub use crate::public_key_hashable::PublicKeyHashable; pub use crate::revoke::Revoke; pub use crate::trust::Trust; pub use crate::trust_graph::{TrustGraph, Weight}; -pub use crate::trust_graph_storage::Storage; +pub use crate::trust_graph_storage::{Storage, StorageError}; pub use crate::trust_node::{Auth, TrustNode}; diff --git a/src/trust_graph_storage.rs b/src/trust_graph_storage.rs index d37c9db..ffa19c3 100644 --- a/src/trust_graph_storage.rs +++ b/src/trust_graph_storage.rs @@ -119,7 +119,7 @@ impl Storage for InMemoryStorage { auth: Auth, issued_for: &PublicKey, cur_time: Duration, - ) -> Result<(), InMemoryStorageError> { + ) -> Result<(), Self::Error> { match self.nodes.get_mut(&pk) { Some(trust_node) => { trust_node.update_auth(auth); From e89452c0b0ac82ec4556e8b12eb3b5f41bc6540d Mon Sep 17 00:00:00 2001 From: DieMyst Date: Tue, 9 Feb 2021 15:50:21 +0300 Subject: [PATCH 05/19] first fce method with result, it works i guess --- bin/Cargo.lock | 37 ---------------------- bin/Cargo.toml | 1 - bin/src/service_api.rs | 34 +++++++++++++++------ bin/src/storage_impl.rs | 68 ++++++++++++++++++++++++----------------- src/certificate.rs | 18 +++++++---- src/revoke.rs | 4 ++- src/trust_graph.rs | 30 +++++++++++++----- 7 files changed, 102 insertions(+), 90 deletions(-) diff --git a/bin/Cargo.lock b/bin/Cargo.lock index 425b0ae..2eb3a9f 100644 --- a/bin/Cargo.lock +++ b/bin/Cargo.lock @@ -984,12 +984,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" - [[package]] name = "ppv-lite86" version = "0.2.10" @@ -1421,36 +1415,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "sqlite" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f759dc2e373e1edd0a27da87aa9136416360c5077a23643fcd6fcdc9cb9e31" -dependencies = [ - "libc", - "sqlite3-sys", -] - -[[package]] -name = "sqlite3-src" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb25e66d026488228a97e0ad21e3d15ec5998dcd9ad73c97cc277c56a6b314" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "sqlite3-sys" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fec807a1534bd13eeaaec396175d67c79bdc68df55e18a452726ec62a8fb08" -dependencies = [ - "libc", - "sqlite3-src", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -1593,7 +1557,6 @@ dependencies = [ "rmp-serde", "serde_bencode", "serde_json", - "sqlite", "thiserror", "trust-graph", ] diff --git a/bin/Cargo.toml b/bin/Cargo.toml index 0c614ca..69c1ad0 100644 --- a/bin/Cargo.toml +++ b/bin/Cargo.toml @@ -25,5 +25,4 @@ bs58 = "0.3.1" rmp-serde = "0.15.0" bincode = "1.3.1" serde_bencode = "^0.2.3" -sqlite = "0.25.3" thiserror = "1.0.23" diff --git a/bin/src/service_api.rs b/bin/src/service_api.rs index 5ba6d5f..70d41aa 100644 --- a/bin/src/service_api.rs +++ b/bin/src/service_api.rs @@ -1,28 +1,44 @@ use crate::storage_impl::get_data; use fluence::fce; use fluence_identity::KeyPair; +use std::convert::{From, Into}; +use std::fmt::Display; +use std::str::FromStr; use std::time::Duration; use trust_graph::Certificate; -use std::str::FromStr; struct InsertResult { ret_code: u32, error: String, } -// TODO: some sort of auth? -fn insert_cert(certificate: String, duration: u64) -> InsertResult { +impl From> for InsertResult { + fn from(result: Result<(), String>) -> Self { + match result { + Ok(()) => InsertResult { + ret_code: 0, + error: "".to_string(), + }, + Err(e) => InsertResult { + ret_code: 1, + error: e, + }, + } + } +} +fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), String> { let duration = Duration::from_millis(duration); - let certificate = Certificate::from_str(&certificate).unwrap(); + let certificate = Certificate::from_str(&certificate)?; let mut tg = get_data().lock(); - tg.add(certificate, duration).unwrap(); + tg.add(certificate, duration)?; + Ok(()) +} - return InsertResult { - ret_code: 0, - error: "".to_string() - } +// TODO: some sort of auth? +fn insert_cert(certificate: String, duration: u64) -> InsertResult { + insert_cert_impl(certificate, duration).into() } #[fce] diff --git a/bin/src/storage_impl.rs b/bin/src/storage_impl.rs index 3ce2ef8..256ff36 100644 --- a/bin/src/storage_impl.rs +++ b/bin/src/storage_impl.rs @@ -2,22 +2,26 @@ // check if trust is already in list before adding // if there is an older trust - don't add received trust +use crate::storage_impl::SqliteStorageError::{ + ConvertionError, DecodeError, EncodeError, RevokeError, SqliteError, Unexpected, +}; use core::convert::TryFrom; +use fce_sqlite_connector; +use fce_sqlite_connector::Connection; +use fce_sqlite_connector::Error as InternalSqliteError; +use fce_sqlite_connector::Value; use fluence_identity::public_key::PublicKey; use once_cell::sync::OnceCell; use parking_lot::Mutex; -use fce_sqlite_connector; -use fce_sqlite_connector::Connection; -use fce_sqlite_connector::Value; -use fce_sqlite_connector::Error as InternalSqliteError; +use rmp_serde::decode::Error as RmpDecodeError; +use rmp_serde::encode::Error as RmpEncodeError; +use std::convert::From; use std::str::FromStr; use std::time::Duration; -use trust_graph::{Auth, PublicKeyHashable, Revoke, Storage, TrustGraph, TrustNode, Weight, StorageError}; use thiserror::Error as ThisError; -use crate::storage_impl::SqliteStorageError::{SqliteError, EncodeError, ConvertionError, DecodeError, Unexpected, RevokeError}; -use rmp_serde::encode::Error as RmpEncodeError; -use rmp_serde::decode::Error as RmpDecodeError; -use std::convert::From; +use trust_graph::{ + Auth, PublicKeyHashable, Revoke, Storage, StorageError, TrustGraph, TrustNode, Weight, +}; static INSTANCE: OnceCell>> = OnceCell::new(); @@ -64,7 +68,7 @@ pub enum SqliteStorageError { #[error("There is no entry for {0}")] ConvertionError(String), #[error("Cannot revoke a trust: {0}")] - RevokeError(String) + RevokeError(String), } impl From for SqliteStorageError { @@ -94,7 +98,6 @@ impl From for String { impl StorageError for SqliteStorageError {} impl Storage for SqliteStorage { - type Error = SqliteStorageError; fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { @@ -103,14 +106,14 @@ impl Storage for SqliteStorage { .prepare("SELECT trustnode FROM trustnodes WHERE public_key = ?")? .cursor(); - cursor - .bind(&[Value::String(format!("{}", pk))])?; + cursor.bind(&[Value::String(format!("{}", pk))])?; match cursor.next().unwrap() { Some(r) => { log::info!("row: {:?}", r); - let tn_bin: &[u8] = r[0] - .as_binary().ok_or(ConvertionError("cannot get trustnode as binary".to_string()))?; + let tn_bin: &[u8] = r[0].as_binary().ok_or(ConvertionError( + "cannot get trustnode as binary".to_string(), + ))?; log::info!("binary: {:?}", tn_bin); @@ -135,8 +138,7 @@ impl Storage for SqliteStorage { log::info!("insert: {:?}", tn_vec); - cursor - .bind(&[Value::String(format!("{}", pk)), Value::Binary(tn_vec)])?; + cursor.bind(&[Value::String(format!("{}", pk)), Value::Binary(tn_vec)])?; cursor.next()?; Ok({}) @@ -153,8 +155,12 @@ impl Storage for SqliteStorage { if let Some(row) = cursor.next()? { log::info!("row: {:?}", row); - let w = u32::try_from(row[1].as_integer().ok_or(ConvertionError("cannot get weight as integer".to_string()))?) - .map_err(|e| Unexpected(format!("Unexpected. Cannot convert weight to u32: {}", e)))?; + let w = u32::try_from( + row[1] + .as_integer() + .ok_or(ConvertionError("cannot get weight as integer".to_string()))?, + ) + .map_err(|e| Unexpected(format!("Unexpected. Cannot convert weight to u32: {}", e)))?; Ok(Some(w)) } else { @@ -162,18 +168,21 @@ impl Storage for SqliteStorage { } } - fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error> { + fn add_root_weight( + &mut self, + pk: PublicKeyHashable, + weight: Weight, + ) -> Result<(), Self::Error> { log::info!("add root: {} weight: {}", pk, weight); let mut cursor = self .connection .prepare("INSERT OR REPLACE INTO roots VALUES (?, ?)")? .cursor(); - cursor - .bind(&[ - Value::String(format!("{}", pk)), - Value::Integer(i64::from(weight)), - ])?; + cursor.bind(&[ + Value::String(format!("{}", pk)), + Value::Integer(i64::from(weight)), + ])?; cursor.next()?; Ok({}) @@ -189,8 +198,9 @@ impl Storage for SqliteStorage { while let Some(row) = cursor.next()? { log::info!("row: {:?}", row); - let pk = row[0].as_string() - .ok_or(ConvertionError("cannot get public key as binary".to_string()))?; + let pk = row[0].as_string().ok_or(ConvertionError( + "cannot get public key as binary".to_string(), + ))?; let pk: PublicKeyHashable = PublicKeyHashable::from_str(pk).map_err(|e| DecodeError(e.to_string()))?; @@ -207,7 +217,9 @@ impl Storage for SqliteStorage { self.insert(pk.clone(), trust_node)?; Ok(()) } - None => Err(RevokeError("There is no trust with such PublicKey".to_string())), + None => Err(RevokeError( + "There is no trust with such PublicKey".to_string(), + )), } } diff --git a/src/certificate.rs b/src/certificate.rs index ecd7d39..f8c84ac 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -14,7 +14,7 @@ * limitations under the License. */ -use crate::certificate::CerificateError::{ +use crate::certificate::CertificateError::{ CertificateLengthError, DecodeError, ExpirationError, KeyInCertificateError, MalformedRoot, NoTrustedRoot, VerificationError, }; @@ -39,7 +39,7 @@ pub struct Certificate { } #[derive(ThisError, Debug)] -pub enum CerificateError { +pub enum CertificateError { #[error("Error while decoding a certificate: {0}")] DecodeError(String), #[error("Certificate is expired. Issued at {issued_at} and expired at {expires_at}")] @@ -61,6 +61,12 @@ pub enum CerificateError { Unexpected(String), } +impl From for String { + fn from(err: CertificateError) -> Self { + format!("{}", err) + } +} + impl Certificate { pub fn new_unverified(chain: Vec) -> Self { Self { chain } @@ -93,7 +99,7 @@ impl Certificate { expires_at: Duration, issued_at: Duration, cur_time: Duration, - ) -> Result { + ) -> Result { if expires_at.lt(&issued_at) { return Err(ExpirationError { expires_at: format!("{:?}", expires_at), @@ -141,7 +147,7 @@ impl Certificate { cert: &Certificate, trusted_roots: &[PublicKey], cur_time: Duration, - ) -> Result<(), CerificateError> { + ) -> Result<(), CertificateError> { let chain = &cert.chain; if chain.is_empty() { @@ -186,7 +192,7 @@ impl Certificate { } #[allow(dead_code)] - pub fn decode(arr: &[u8]) -> Result { + pub fn decode(arr: &[u8]) -> Result { let trusts_offset = arr.len() - 2 - 4; if trusts_offset % TRUST_LEN != 0 { return Err(DecodeError("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust. ".to_string())); @@ -228,7 +234,7 @@ impl std::fmt::Display for Certificate { } impl FromStr for Certificate { - type Err = CerificateError; + type Err = CertificateError; fn from_str(s: &str) -> Result { let str_lines: Vec<&str> = s.lines().collect(); diff --git a/src/revoke.rs b/src/revoke.rs index 35aa8f9..582e23a 100644 --- a/src/revoke.rs +++ b/src/revoke.rs @@ -22,9 +22,11 @@ use fluence_identity::public_key::PublicKey; use fluence_identity::signature::Signature; use serde::{Deserialize, Serialize}; use std::time::Duration; +use thiserror::Error as ThisError; -#[derive(Debug)] +#[derive(ThisError, Debug)] pub enum RevokeError { + #[error("Signature is incorrect: {0}")] IncorrectSignature(SignatureError), } diff --git a/src/trust_graph.rs b/src/trust_graph.rs index a099e26..7d2f55f 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -14,8 +14,8 @@ * limitations under the License. */ -use crate::certificate::CerificateError::{CertificateLengthError, Unexpected}; -use crate::certificate::{CerificateError, Certificate}; +use crate::certificate::CertificateError::{CertificateLengthError, Unexpected}; +use crate::certificate::{Certificate, CertificateError}; use crate::public_key_hashable::PublicKeyHashable; use crate::revoke::Revoke; use crate::revoke::RevokeError; @@ -31,6 +31,7 @@ use std::collections::{HashSet, VecDeque}; use std::convert::{From, Into}; use std::result::Result; use std::time::Duration; +use thiserror::Error as ThisError; /// for simplicity, we store `n` where Weight = 1/n^2 pub type Weight = u32; @@ -46,20 +47,30 @@ where storage: Box, } -#[derive(Debug)] +#[derive(ThisError, Debug)] pub enum TrustGraphError { + #[error("Internal storage error: {0}")] InternalStorageError(String), + #[error("There is no root for this certificate.")] NoRoot, - CertificateCheckError(CerificateError), + #[error("Certificate check error: {0}")] + CertificateCheckError(CertificateError), + #[error("Error on revoking a trust: {0}")] RevokeCheckError(RevokeError), } -impl From for TrustGraphError { - fn from(err: CerificateError) -> Self { +impl From for TrustGraphError { + fn from(err: CertificateError) -> Self { CertificateCheckError(err) } } +impl From for String { + fn from(err: TrustGraphError) -> Self { + format!("{}", err) + } +} + impl From for TrustGraphError { fn from(err: RevokeError) -> Self { RevokeCheckError(err) @@ -130,7 +141,9 @@ where issued_by: root_trust.issued_for.clone(), }; trust_node.update_auth(root_auth); - self.storage.insert(root_pk, trust_node).map_err(|e| InternalStorageError(e.into()))?; + self.storage + .insert(root_pk, trust_node) + .map_err(|e| InternalStorageError(e.into()))?; } // Insert remaining trusts to the graph @@ -144,7 +157,8 @@ where }; self.storage - .update_auth(&pk, auth, &root_trust.issued_for, cur_time).map_err(|e| InternalStorageError(e.into()))?; + .update_auth(&pk, auth, &root_trust.issued_for, cur_time) + .map_err(|e| InternalStorageError(e.into()))?; previous_trust = trust; } From 3a9530b92d647fd8f8196105301a610cd43ce753 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 10 Feb 2021 15:23:51 +0300 Subject: [PATCH 06/19] proxy structs, get_all_certs and insert functions --- bin/src/main.rs | 2 ++ bin/src/proxy_structs.rs | 46 ++++++++++++++++++++++++ bin/src/results.rs | 71 +++++++++++++++++++++++++++++++++++++ bin/src/service_api.rs | 75 +++++++++++++++++++++++++--------------- 4 files changed, 166 insertions(+), 28 deletions(-) create mode 100644 bin/src/proxy_structs.rs create mode 100644 bin/src/results.rs diff --git a/bin/src/main.rs b/bin/src/main.rs index 6029831..a899667 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -2,6 +2,8 @@ use fluence::WasmLoggerBuilder; mod service_api; mod storage_impl; +mod results; +mod proxy_structs; pub fn main() { WasmLoggerBuilder::new() diff --git a/bin/src/proxy_structs.rs b/bin/src/proxy_structs.rs new file mode 100644 index 0000000..e12a4aa --- /dev/null +++ b/bin/src/proxy_structs.rs @@ -0,0 +1,46 @@ +use trust_graph::{Trust as TGTrust, Certificate as TGCertificate}; +use fluence::fce; + +#[fce] +pub struct Certificate { + pub chain: Vec, +} + +impl From for Certificate { + + fn from(t: TGCertificate) -> Self { + let chain: Vec = t.chain.into_iter().map(|t| t.into()).collect(); + return Certificate { + chain + } + } +} + +#[fce] +pub struct Trust { + /// For whom this certificate is issued, base58 + pub issued_for: String, + /// Expiration date of a trust, in secs + pub expires_at: u64, + /// Signature of a previous trust in a chain. + /// Signature is self-signed if it is a root trust, base58 + pub signature: String, + /// Creation time of a trust, in secs + pub issued_at: u64, +} + +impl From for Trust { + + fn from(t: TGTrust) -> Self { + let issued_for = bs58::encode(t.issued_for.to_bytes()).into_string(); + let signature = bs58::encode(t.signature.to_bytes()).into_string(); + let expires_at = t.expires_at.as_secs(); + let issued_at = t.issued_at.as_secs(); + return Trust { + issued_for, + expires_at, + signature, + issued_at + } + } +} \ No newline at end of file diff --git a/bin/src/results.rs b/bin/src/results.rs new file mode 100644 index 0000000..98b0861 --- /dev/null +++ b/bin/src/results.rs @@ -0,0 +1,71 @@ +use fluence::fce; +use crate::proxy_structs::Certificate; + +#[fce] +pub struct InsertResult { + pub ret_code: u32, + pub error: String, +} + +impl From> for InsertResult { + fn from(result: Result<(), String>) -> Self { + match result { + Ok(()) => InsertResult { + ret_code: 0, + error: "".to_string(), + }, + Err(e) => InsertResult { + ret_code: 1, + error: e, + }, + } + } +} + +#[fce] +pub struct WeightResult { + pub ret_code: u32, + pub weight: Vec, + pub error: String +} + +impl From, String>> for WeightResult { + fn from(result: Result, String>) -> Self { + match result { + Ok(wo) => WeightResult { + ret_code: 0, + weight: wo.map(|w| vec![w]).unwrap_or(vec![]), + error: "".to_string(), + }, + Err(e) => WeightResult { + ret_code: 1, + weight: vec![], + error: e, + }, + } + } +} + +#[fce] +pub struct AllCertsResult { + pub ret_code: u32, + pub certificates: Vec, + pub error: String +} + +impl From, String>> for AllCertsResult { + fn from(result: Result, String>) -> Self { + match result { + Ok(certs) => AllCertsResult { + ret_code: 0, + certificates: certs, + error: "".to_string(), + }, + Err(e) => AllCertsResult { + ret_code: 1, + certificates: vec![], + error: e, + }, + } + } +} \ No newline at end of file diff --git a/bin/src/service_api.rs b/bin/src/service_api.rs index 70d41aa..730700b 100644 --- a/bin/src/service_api.rs +++ b/bin/src/service_api.rs @@ -1,46 +1,65 @@ use crate::storage_impl::get_data; use fluence::fce; -use fluence_identity::KeyPair; +use fluence_identity::{KeyPair, PublicKey}; use std::convert::{From, Into}; use std::fmt::Display; use std::str::FromStr; use std::time::Duration; -use trust_graph::Certificate; - -struct InsertResult { - ret_code: u32, - error: String, -} - -impl From> for InsertResult { - fn from(result: Result<(), String>) -> Self { - match result { - Ok(()) => InsertResult { - ret_code: 0, - error: "".to_string(), - }, - Err(e) => InsertResult { - ret_code: 1, - error: e, - }, - } - } -} +use trust_graph::{Certificate as TGCertificate}; +use crate::proxy_structs::Certificate; +use crate::results::{WeightResult, InsertResult, AllCertsResult}; fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), String> { let duration = Duration::from_millis(duration); - let certificate = Certificate::from_str(&certificate)?; + let certificate = TGCertificate::from_str(&certificate)?; let mut tg = get_data().lock(); tg.add(certificate, duration)?; Ok(()) } +#[fce] // TODO: some sort of auth? fn insert_cert(certificate: String, duration: u64) -> InsertResult { insert_cert_impl(certificate, duration).into() } +fn get_weight_impl(public_key: String) -> Result, String> { + let mut tg = get_data().lock(); + + let public_key = string_to_public_key(public_key)?; + + let weight = tg.weight(public_key)?; + + Ok(weight) +} + +#[fce] +fn get_weight(public_key: String) -> WeightResult { + get_weight_impl(public_key).into() +} + +fn string_to_public_key(public_key: String) -> Result { + let public_key = bs58::decode(public_key) + .into_vec().map_err(|e| format!("Couldn't decode public_key from base58: {}", e))?; + let public_key = PublicKey::from_bytes(&public_key) + .map_err(|e| format!("Couldn't decode public_key: {}", e))?; + + Ok(public_key) +} + +fn get_all_certs(issued_for: String) -> AllCertsResult { + get_all_certs_impl(issued_for).into() +} + +fn get_all_certs_impl(issued_for: String) -> Result, String> { + let mut tg = get_data().lock(); + + let public_key = string_to_public_key(issued_for)?; + let certs = tg.get_all_certs(public_key, &[])?; + Ok(certs.into_iter().map(|c| c.into()).collect()) +} + #[fce] fn test() -> String { let mut tg = get_data().lock(); @@ -52,12 +71,12 @@ fn test() -> String { let expires_at = Duration::new(15, 15); let issued_at = Duration::new(5, 5); - let cert = Certificate::issue_root(&root_kp, second_kp.public_key(), expires_at, issued_at); - tg.add_root_weight(root_kp.public().into(), 0); - tg.add_root_weight(root_kp2.public().into(), 1); - tg.add(cert, Duration::new(10, 10)); + let cert = TGCertificate::issue_root(&root_kp, second_kp.public_key(), expires_at, issued_at); + tg.add_root_weight(root_kp.public().into(), 0).unwrap(); + tg.add_root_weight(root_kp2.public().into(), 1).unwrap(); + tg.add(cert, Duration::new(10, 10)).unwrap(); - let a = tg.get(second_kp.public_key()); + let a = tg.get(second_kp.public_key()).unwrap(); let str = format!("{:?}", a); log::info!("{}", &str); From 5889ad77a33fb9f5b289118be0f4d60f7fcbe9e4 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 10 Feb 2021 15:26:26 +0300 Subject: [PATCH 07/19] fmt --- bin/src/main.rs | 4 ++-- bin/src/proxy_structs.rs | 14 +++++--------- bin/src/results.rs | 8 ++++---- bin/src/service_api.rs | 9 +++++---- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/bin/src/main.rs b/bin/src/main.rs index a899667..6152877 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -1,9 +1,9 @@ use fluence::WasmLoggerBuilder; +mod proxy_structs; +mod results; mod service_api; mod storage_impl; -mod results; -mod proxy_structs; pub fn main() { WasmLoggerBuilder::new() diff --git a/bin/src/proxy_structs.rs b/bin/src/proxy_structs.rs index e12a4aa..9178854 100644 --- a/bin/src/proxy_structs.rs +++ b/bin/src/proxy_structs.rs @@ -1,5 +1,5 @@ -use trust_graph::{Trust as TGTrust, Certificate as TGCertificate}; use fluence::fce; +use trust_graph::{Certificate as TGCertificate, Trust as TGTrust}; #[fce] pub struct Certificate { @@ -7,12 +7,9 @@ pub struct Certificate { } impl From for Certificate { - fn from(t: TGCertificate) -> Self { let chain: Vec = t.chain.into_iter().map(|t| t.into()).collect(); - return Certificate { - chain - } + return Certificate { chain }; } } @@ -30,7 +27,6 @@ pub struct Trust { } impl From for Trust { - fn from(t: TGTrust) -> Self { let issued_for = bs58::encode(t.issued_for.to_bytes()).into_string(); let signature = bs58::encode(t.signature.to_bytes()).into_string(); @@ -40,7 +36,7 @@ impl From for Trust { issued_for, expires_at, signature, - issued_at - } + issued_at, + }; } -} \ No newline at end of file +} diff --git a/bin/src/results.rs b/bin/src/results.rs index 98b0861..714d6d5 100644 --- a/bin/src/results.rs +++ b/bin/src/results.rs @@ -1,5 +1,5 @@ -use fluence::fce; use crate::proxy_structs::Certificate; +use fluence::fce; #[fce] pub struct InsertResult { @@ -26,7 +26,7 @@ impl From> for InsertResult { pub struct WeightResult { pub ret_code: u32, pub weight: Vec, - pub error: String + pub error: String, } impl From, String>> for WeightResult { @@ -50,7 +50,7 @@ impl From, String>> for WeightResult { pub struct AllCertsResult { pub ret_code: u32, pub certificates: Vec, - pub error: String + pub error: String, } impl From, String>> for AllCertsResult { @@ -68,4 +68,4 @@ impl From, String>> for AllCertsResult { }, } } -} \ No newline at end of file +} diff --git a/bin/src/service_api.rs b/bin/src/service_api.rs index 730700b..b0868a3 100644 --- a/bin/src/service_api.rs +++ b/bin/src/service_api.rs @@ -1,3 +1,5 @@ +use crate::proxy_structs::Certificate; +use crate::results::{AllCertsResult, InsertResult, WeightResult}; use crate::storage_impl::get_data; use fluence::fce; use fluence_identity::{KeyPair, PublicKey}; @@ -5,9 +7,7 @@ use std::convert::{From, Into}; use std::fmt::Display; use std::str::FromStr; use std::time::Duration; -use trust_graph::{Certificate as TGCertificate}; -use crate::proxy_structs::Certificate; -use crate::results::{WeightResult, InsertResult, AllCertsResult}; +use trust_graph::Certificate as TGCertificate; fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), String> { let duration = Duration::from_millis(duration); @@ -41,7 +41,8 @@ fn get_weight(public_key: String) -> WeightResult { fn string_to_public_key(public_key: String) -> Result { let public_key = bs58::decode(public_key) - .into_vec().map_err(|e| format!("Couldn't decode public_key from base58: {}", e))?; + .into_vec() + .map_err(|e| format!("Couldn't decode public_key from base58: {}", e))?; let public_key = PublicKey::from_bytes(&public_key) .map_err(|e| format!("Couldn't decode public_key: {}", e))?; From 61fd3cb312bc13daee714f7f6434abfec7f5bb41 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 10 Feb 2021 15:30:10 +0300 Subject: [PATCH 08/19] clippy --- src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bd09408..53cce51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,15 +16,15 @@ #![recursion_limit = "512"] #![warn(rust_2018_idioms)] -// #![deny( -// dead_code, -// nonstandard_style, -// unused_imports, -// unused_mut, -// unused_variables, -// unused_unsafe, -// unreachable_patterns -// )] +#![deny( + dead_code, + nonstandard_style, + unused_imports, + unused_mut, + unused_variables, + unused_unsafe, + unreachable_patterns +)] mod certificate; pub mod certificate_serde; From b10726032e2e8a3401c8aba16d839947032ad648 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Thu, 11 Feb 2021 15:10:18 +0300 Subject: [PATCH 09/19] rename dir, restruct all errors --- src/certificate.rs | 52 ++++++------ src/public_key_hashable.rs | 18 ++++- src/trust.rs | 4 +- src/trust_graph.rs | 78 ++++++------------ src/trust_graph_storage.rs | 50 +++++------- {bin => wasm}/Cargo.lock | 0 {bin => wasm}/Cargo.toml | 0 {bin => wasm}/Config.toml | 0 {bin => wasm}/run-repl.sh | 0 bin/src/proxy_structs.rs => wasm/src/dto.rs | 11 ++- {bin => wasm}/src/main.rs | 2 +- {bin => wasm}/src/results.rs | 2 +- {bin => wasm}/src/service_api.rs | 21 +++-- {bin => wasm}/src/storage_impl.rs | 87 ++++++++++----------- 14 files changed, 145 insertions(+), 180 deletions(-) rename {bin => wasm}/Cargo.lock (100%) rename {bin => wasm}/Cargo.toml (100%) rename {bin => wasm}/Config.toml (100%) rename {bin => wasm}/run-repl.sh (100%) rename bin/src/proxy_structs.rs => wasm/src/dto.rs (76%) rename {bin => wasm}/src/main.rs (95%) rename {bin => wasm}/src/results.rs (97%) rename {bin => wasm}/src/service_api.rs (84%) rename {bin => wasm}/src/storage_impl.rs (71%) diff --git a/src/certificate.rs b/src/certificate.rs index f8c84ac..f5d6537 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -15,10 +15,11 @@ */ use crate::certificate::CertificateError::{ - CertificateLengthError, DecodeError, ExpirationError, KeyInCertificateError, MalformedRoot, - NoTrustedRoot, VerificationError, + CertificateLengthError, DecodeError, DecodeTrustError, ExpirationError, IncorrectByteLength, + IncorrectCertificateFormat, KeyInCertificateError, MalformedRoot, NoTrustedRoot, + VerificationError, }; -use crate::trust::{Trust, TRUST_LEN}; +use crate::trust::{Trust, TrustError, TRUST_LEN}; use fluence_identity::key_pair::KeyPair; use fluence_identity::public_key::PublicKey; use std::str::FromStr; @@ -40,8 +41,12 @@ pub struct Certificate { #[derive(ThisError, Debug)] pub enum CertificateError { - #[error("Error while decoding a certificate: {0}")] - DecodeError(String), + #[error("Incorrect format of the certificate: {0}")] + IncorrectCertificateFormat(String), + #[error("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust")] + IncorrectByteLength, + #[error("Error while decoding a trust in a certificate: {0}")] + DecodeError(TrustError), #[error("Certificate is expired. Issued at {issued_at} and expired at {expires_at}")] ExpirationError { expires_at: String, @@ -50,21 +55,17 @@ pub enum CertificateError { #[error("Certificate does not contain a trusted root.")] NoTrustedRoot, #[error("Root trust did not pass verification: {0}")] - MalformedRoot(String), + MalformedRoot(TrustError), #[error("There is no `issued_by` public key in a certificate")] KeyInCertificateError, #[error("The certificate must have at least 1 trust")] CertificateLengthError, + #[error("Cannot convert trust number {0} from string: {1}")] + DecodeTrustError(usize, TrustError), #[error("Trust {0} in chain did not pass verification: {1}")] - VerificationError(usize, String), - #[error("Unexpected error: {0}")] - Unexpected(String), -} - -impl From for String { - fn from(err: CertificateError) -> Self { - format!("{}", err) - } + VerificationError(usize, TrustError), + #[error("there cannot be paths without any nodes after adding verified certificates")] + Unexpected, } impl Certificate { @@ -156,8 +157,7 @@ impl Certificate { // check root trust and its existence in trusted roots list let root = &chain[0]; - Trust::verify(root, &root.issued_for, cur_time) - .map_err(|e| MalformedRoot(format!("{}", e)))?; + Trust::verify(root, &root.issued_for, cur_time).map_err(|e| MalformedRoot(e))?; if !trusted_roots.contains(&root.issued_for) { return Err(NoTrustedRoot); } @@ -169,7 +169,7 @@ impl Certificate { let trust_giver = &chain[trust_id - 1]; Trust::verify(trust, &trust_giver.issued_for, cur_time) - .map_err(|e| VerificationError(trust_id, format!("{}", e)))?; + .map_err(|e| VerificationError(trust_id, e))?; } Ok(()) @@ -195,7 +195,7 @@ impl Certificate { pub fn decode(arr: &[u8]) -> Result { let trusts_offset = arr.len() - 2 - 4; if trusts_offset % TRUST_LEN != 0 { - return Err(DecodeError("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust. ".to_string())); + return Err(IncorrectByteLength); } let number_of_trusts = trusts_offset / TRUST_LEN; @@ -214,7 +214,7 @@ impl Certificate { let from = i * TRUST_LEN + 6; let to = (i + 1) * TRUST_LEN + 6; let slice = &arr[from..to]; - let t = Trust::decode(slice).map_err(|e| DecodeError(format!("{}", e)))?; + let t = Trust::decode(slice).map_err(|e| DecodeError(e))?; chain.push(t); } @@ -244,10 +244,7 @@ impl FromStr for Certificate { let _version = str_lines[1]; if (str_lines.len() - 2) % 4 != 0 { - return Err(DecodeError(format!( - "Incorrect format of the certificate: {}", - s - ))); + return Err(IncorrectCertificateFormat(s.to_string())); } let num_of_trusts = (str_lines.len() - 2) / 4; @@ -260,12 +257,7 @@ impl FromStr for Certificate { str_lines[i + 2], str_lines[i + 3], ) - .map_err(|e| { - DecodeError(format!( - "Cannot convert trust number {} from string: {}", - i, e - )) - })?; + .map_err(|e| DecodeTrustError(i, e))?; trusts.push(trust); } diff --git a/src/public_key_hashable.rs b/src/public_key_hashable.rs index 1bccaa7..0bc0dea 100644 --- a/src/public_key_hashable.rs +++ b/src/public_key_hashable.rs @@ -16,7 +16,9 @@ use fluence_identity::public_key::PublicKey; +use crate::public_key_hashable::PkError::{Base58DecodeError, BytesDecodeError}; use core::fmt; +use ed25519_dalek::SignatureError; use ref_cast::RefCast; use serde::ser::Serializer; use std::str::FromStr; @@ -24,6 +26,7 @@ use std::{ fmt::{Display, Formatter}, hash::{Hash, Hasher}, }; +use thiserror::Error as ThisError; /// Wrapper to use PublicKey in HashMap #[derive(PartialEq, Eq, Debug, Clone, RefCast)] @@ -81,16 +84,23 @@ impl Display for PublicKeyHashable { } } +#[derive(ThisError, Debug)] +pub enum PkError { + #[error("Invalid string '{0}': {1}")] + Base58DecodeError(String, bs58::decode::Error), + #[error("Invalid bytes {0:?}: {1}")] + BytesDecodeError(Vec, SignatureError), +} + impl FromStr for PublicKeyHashable { - type Err = String; + type Err = PkError; fn from_str(s: &str) -> Result { let bytes = bs58::decode(s) .into_vec() - .map_err(|err| format!("Invalid string '{}': {}", s, err))?; + .map_err(|err| Base58DecodeError(s.to_string(), err))?; - let pk = PublicKey::from_bytes(&bytes) - .map_err(|err| format!("Invalid bytes {:?}: {}", bytes, err))?; + let pk = PublicKey::from_bytes(&bytes).map_err(|err| BytesDecodeError(bytes, err))?; Ok(PublicKeyHashable::from(pk)) } } diff --git a/src/trust.rs b/src/trust.rs index 74a5721..8b1a35a 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -64,11 +64,11 @@ pub enum TrustError { Expired(Duration, Duration), /// Errors occured on signature verification - #[error("{0:?}")] + #[error("{0}")] SignatureError(String), /// Errors occured on trust decoding from differrent formats - #[error("{0:?}")] + #[error("{0}")] DecodeError(String), } diff --git a/src/trust_graph.rs b/src/trust_graph.rs index 7d2f55f..34f9792 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -21,10 +21,11 @@ use crate::revoke::Revoke; use crate::revoke::RevokeError; use crate::trust::Trust; use crate::trust_graph::TrustGraphError::{ - CertificateCheckError, InternalStorageError, NoRoot, RevokeCheckError, + CertificateCheckError, EmptyChain, InternalStorageError, NoRoot, RevokeCheckError, }; use crate::trust_graph_storage::Storage; use crate::trust_node::{Auth, TrustNode}; +use crate::StorageError; use fluence_identity::public_key::PublicKey; use std::borrow::Borrow; use std::collections::{HashSet, VecDeque}; @@ -50,15 +51,23 @@ where #[derive(ThisError, Debug)] pub enum TrustGraphError { #[error("Internal storage error: {0}")] - InternalStorageError(String), + InternalStorageError(Box), #[error("There is no root for this certificate.")] NoRoot, + #[error("Chain is empty")] + EmptyChain, #[error("Certificate check error: {0}")] CertificateCheckError(CertificateError), #[error("Error on revoking a trust: {0}")] RevokeCheckError(RevokeError), } +impl From for TrustGraphError { + fn from(err: T) -> Self { + InternalStorageError(Box::new(err)) + } +} + impl From for TrustGraphError { fn from(err: CertificateError) -> Self { CertificateCheckError(err) @@ -92,16 +101,12 @@ where pk: PublicKeyHashable, weight: Weight, ) -> Result<(), TrustGraphError> { - self.storage - .add_root_weight(pk, weight) - .map_err(|e| InternalStorageError(e.into())) + Ok(self.storage.add_root_weight(pk, weight)?) } /// Get trust by public key pub fn get(&self, pk: PublicKey) -> Result, TrustGraphError> { - self.storage - .get(&pk.into()) - .map_err(|e| InternalStorageError(e.into())) + Ok(self.storage.get(&pk.into())?) } // TODO: remove cur_time from api, leave it for tests only @@ -112,8 +117,7 @@ where { let roots: Vec = self .storage - .root_keys() - .map_err(|e| InternalStorageError(e.into()))? + .root_keys()? .iter() .cloned() .map(Into::into) @@ -122,28 +126,18 @@ where Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?; let mut chain = cert.borrow().chain.iter(); - let root_trust = chain - .next() - .ok_or("empty chain") - .map_err(|e| InternalStorageError(e.into()))?; + let root_trust = chain.next().ok_or(EmptyChain)?; let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into(); // Insert new TrustNode for this root_pk if there wasn't one - if self - .storage - .get(&root_pk) - .map_err(|e| InternalStorageError(e.into()))? - .is_none() - { + if self.storage.get(&root_pk)?.is_none() { let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time); let root_auth = Auth { trust: root_trust.clone(), issued_by: root_trust.issued_for.clone(), }; trust_node.update_auth(root_auth); - self.storage - .insert(root_pk, trust_node) - .map_err(|e| InternalStorageError(e.into()))?; + self.storage.insert(root_pk, trust_node)?; } // Insert remaining trusts to the graph @@ -157,8 +151,7 @@ where }; self.storage - .update_auth(&pk, auth, &root_trust.issued_for, cur_time) - .map_err(|e| InternalStorageError(e.into()))?; + .update_auth(&pk, auth, &root_trust.issued_for, cur_time)?; previous_trust = trust; } @@ -171,18 +164,13 @@ where where P: Borrow, { - if let Some(weight) = self - .storage - .get_root_weight(pk.borrow().as_ref()) - .map_err(|e| InternalStorageError(e.into()))? - { + if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref())? { return Ok(Some(weight)); } let roots: Vec = self .storage - .root_keys() - .map_err(|e| InternalStorageError(e.into()))? + .root_keys()? .iter() .map(|pk| pk.clone().into()) .collect(); @@ -220,9 +208,7 @@ where let root_weight = self .storage - .get_root_weight(first.issued_for.as_ref()) - // This panic shouldn't happen // TODO: why? - .map_err(|e| InternalStorageError(e.into()))? + .get_root_weight(first.issued_for.as_ref())? .ok_or(NoRoot)?; // certificate weight = root weight + 1 * every other element in the chain @@ -264,12 +250,8 @@ where let auths: Vec = self .storage - .get(&last.issued_by.clone().into()) - .map_err(|e| InternalStorageError(e.into()))? - .ok_or(CertificateCheckError(Unexpected( - "there cannot be paths without any nodes after adding verified certificates" - .to_string(), - )))? + .get(&last.issued_by.clone().into())? + .ok_or(CertificateCheckError(Unexpected))? .authorizations() .cloned() .collect(); @@ -314,16 +296,10 @@ where P: Borrow, { // get all auths (edges) for issued public key - let issued_for_node = self - .storage - .get(issued_for.borrow().as_ref()) - .map_err(|e| InternalStorageError(e.into()))?; + let issued_for_node = self.storage.get(issued_for.borrow().as_ref())?; let roots = roots.iter().map(|pk| pk.as_ref()); - let keys = self - .storage - .root_keys() - .map_err(|e| InternalStorageError(e.into()))?; + let keys = self.storage.root_keys()?; let roots = keys.iter().chain(roots).collect(); match issued_for_node { @@ -356,9 +332,7 @@ where let pk: PublicKeyHashable = revoke.pk.clone().into(); - self.storage - .revoke(&pk, revoke) - .map_err(|e| InternalStorageError(e.into())) + Ok(self.storage.revoke(&pk, revoke)?) } /// Check information about new certificates and about revoked certificates. diff --git a/src/trust_graph_storage.rs b/src/trust_graph_storage.rs index ffa19c3..3a79302 100644 --- a/src/trust_graph_storage.rs +++ b/src/trust_graph_storage.rs @@ -1,29 +1,29 @@ -use crate::public_key_hashable::PublicKeyHashable; +use crate::public_key_hashable::PublicKeyHashable as PK; use crate::revoke::Revoke; use crate::trust_graph::Weight; use crate::trust_graph_storage::InMemoryStorageError::RevokeError; use crate::trust_node::{Auth, TrustNode}; use fluence_identity::public_key::PublicKey; use std::collections::HashMap; +use std::fmt::Display; use std::time::Duration; use thiserror::Error as ThisError; -pub trait StorageError: std::error::Error {} +pub trait StorageError: std::error::Error + Display {} pub trait Storage { - type Error: StorageError + Into; + type Error: StorageError + 'static; - fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error>; - fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error>; + fn get(&self, pk: &PK) -> Result, Self::Error>; + fn insert(&mut self, pk: PK, node: TrustNode) -> Result<(), Self::Error>; - fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result, Self::Error>; - fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) - -> Result<(), Self::Error>; - fn root_keys(&self) -> Result, Self::Error>; - fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error>; + fn get_root_weight(&self, pk: &PK) -> Result, Self::Error>; + fn add_root_weight(&mut self, pk: PK, weight: Weight) -> Result<(), Self::Error>; + fn root_keys(&self) -> Result, Self::Error>; + fn revoke(&mut self, pk: &PK, revoke: Revoke) -> Result<(), Self::Error>; fn update_auth( &mut self, - pk: &PublicKeyHashable, + pk: &PK, auth: Auth, issued_for: &PublicKey, cur_time: Duration, @@ -32,8 +32,8 @@ pub trait Storage { #[derive(Debug, Default)] pub struct InMemoryStorage { - nodes: HashMap, - root_weights: HashMap, + nodes: HashMap, + root_weights: HashMap, } impl InMemoryStorage { @@ -64,44 +64,34 @@ pub enum InMemoryStorageError { RevokeError(String), } -impl From for String { - fn from(err: InMemoryStorageError) -> Self { - err.into() - } -} - impl StorageError for InMemoryStorageError {} impl Storage for InMemoryStorage { type Error = InMemoryStorageError; - fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { + fn get(&self, pk: &PK) -> Result, Self::Error> { Ok(self.nodes.get(pk).cloned()) } - fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error> { + fn insert(&mut self, pk: PK, node: TrustNode) -> Result<(), Self::Error> { &self.nodes.insert(pk, node); Ok(()) } - fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { + fn get_root_weight(&self, pk: &PK) -> Result, Self::Error> { Ok(self.root_weights.get(pk).cloned()) } - fn add_root_weight( - &mut self, - pk: PublicKeyHashable, - weight: Weight, - ) -> Result<(), Self::Error> { + fn add_root_weight(&mut self, pk: PK, weight: Weight) -> Result<(), Self::Error> { &self.root_weights.insert(pk, weight); Ok({}) } - fn root_keys(&self) -> Result, Self::Error> { + fn root_keys(&self) -> Result, Self::Error> { Ok(self.root_weights.keys().cloned().map(Into::into).collect()) } - fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error> { + fn revoke(&mut self, pk: &PK, revoke: Revoke) -> Result<(), Self::Error> { match self.nodes.get_mut(&pk) { Some(trust_node) => { trust_node.update_revoke(revoke); @@ -115,7 +105,7 @@ impl Storage for InMemoryStorage { fn update_auth( &mut self, - pk: &PublicKeyHashable, + pk: &PK, auth: Auth, issued_for: &PublicKey, cur_time: Duration, diff --git a/bin/Cargo.lock b/wasm/Cargo.lock similarity index 100% rename from bin/Cargo.lock rename to wasm/Cargo.lock diff --git a/bin/Cargo.toml b/wasm/Cargo.toml similarity index 100% rename from bin/Cargo.toml rename to wasm/Cargo.toml diff --git a/bin/Config.toml b/wasm/Config.toml similarity index 100% rename from bin/Config.toml rename to wasm/Config.toml diff --git a/bin/run-repl.sh b/wasm/run-repl.sh similarity index 100% rename from bin/run-repl.sh rename to wasm/run-repl.sh diff --git a/bin/src/proxy_structs.rs b/wasm/src/dto.rs similarity index 76% rename from bin/src/proxy_structs.rs rename to wasm/src/dto.rs index 9178854..60302a3 100644 --- a/bin/src/proxy_structs.rs +++ b/wasm/src/dto.rs @@ -1,14 +1,13 @@ use fluence::fce; -use trust_graph::{Certificate as TGCertificate, Trust as TGTrust}; #[fce] pub struct Certificate { pub chain: Vec, } -impl From for Certificate { - fn from(t: TGCertificate) -> Self { - let chain: Vec = t.chain.into_iter().map(|t| t.into()).collect(); +impl From for Certificate { + fn from(c: trust_graph::Certificate) -> Self { + let chain: Vec = c.chain.into_iter().map(|t| t.into()).collect(); return Certificate { chain }; } } @@ -26,8 +25,8 @@ pub struct Trust { pub issued_at: u64, } -impl From for Trust { - fn from(t: TGTrust) -> Self { +impl From for Trust { + fn from(t: trust_graph::Trust) -> Self { let issued_for = bs58::encode(t.issued_for.to_bytes()).into_string(); let signature = bs58::encode(t.signature.to_bytes()).into_string(); let expires_at = t.expires_at.as_secs(); diff --git a/bin/src/main.rs b/wasm/src/main.rs similarity index 95% rename from bin/src/main.rs rename to wasm/src/main.rs index 6152877..2b1848b 100644 --- a/bin/src/main.rs +++ b/wasm/src/main.rs @@ -1,6 +1,6 @@ use fluence::WasmLoggerBuilder; -mod proxy_structs; +mod dto; mod results; mod service_api; mod storage_impl; diff --git a/bin/src/results.rs b/wasm/src/results.rs similarity index 97% rename from bin/src/results.rs rename to wasm/src/results.rs index 714d6d5..fa8cdee 100644 --- a/bin/src/results.rs +++ b/wasm/src/results.rs @@ -1,4 +1,4 @@ -use crate::proxy_structs::Certificate; +use crate::dto::Certificate; use fluence::fce; #[fce] diff --git a/bin/src/service_api.rs b/wasm/src/service_api.rs similarity index 84% rename from bin/src/service_api.rs rename to wasm/src/service_api.rs index b0868a3..9ac8de7 100644 --- a/bin/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -1,17 +1,16 @@ -use crate::proxy_structs::Certificate; +use crate::dto::Certificate; use crate::results::{AllCertsResult, InsertResult, WeightResult}; use crate::storage_impl::get_data; use fluence::fce; use fluence_identity::{KeyPair, PublicKey}; -use std::convert::{From, Into}; -use std::fmt::Display; +use std::convert::Into; use std::str::FromStr; use std::time::Duration; -use trust_graph::Certificate as TGCertificate; fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), String> { let duration = Duration::from_millis(duration); - let certificate = TGCertificate::from_str(&certificate)?; + let certificate = + trust_graph::Certificate::from_str(&certificate).map_err(|e| format!("{}", e))?; let mut tg = get_data().lock(); tg.add(certificate, duration)?; @@ -25,7 +24,7 @@ fn insert_cert(certificate: String, duration: u64) -> InsertResult { } fn get_weight_impl(public_key: String) -> Result, String> { - let mut tg = get_data().lock(); + let tg = get_data().lock(); let public_key = string_to_public_key(public_key)?; @@ -49,12 +48,13 @@ fn string_to_public_key(public_key: String) -> Result { Ok(public_key) } +#[fce] fn get_all_certs(issued_for: String) -> AllCertsResult { get_all_certs_impl(issued_for).into() } fn get_all_certs_impl(issued_for: String) -> Result, String> { - let mut tg = get_data().lock(); + let tg = get_data().lock(); let public_key = string_to_public_key(issued_for)?; let certs = tg.get_all_certs(public_key, &[])?; @@ -72,7 +72,12 @@ fn test() -> String { let expires_at = Duration::new(15, 15); let issued_at = Duration::new(5, 5); - let cert = TGCertificate::issue_root(&root_kp, second_kp.public_key(), expires_at, issued_at); + let cert = trust_graph::Certificate::issue_root( + &root_kp, + second_kp.public_key(), + expires_at, + issued_at, + ); tg.add_root_weight(root_kp.public().into(), 0).unwrap(); tg.add_root_weight(root_kp2.public().into(), 1).unwrap(); tg.add(cert, Duration::new(10, 10)).unwrap(); diff --git a/bin/src/storage_impl.rs b/wasm/src/storage_impl.rs similarity index 71% rename from bin/src/storage_impl.rs rename to wasm/src/storage_impl.rs index 256ff36..5176e33 100644 --- a/bin/src/storage_impl.rs +++ b/wasm/src/storage_impl.rs @@ -2,8 +2,9 @@ // check if trust is already in list before adding // if there is an older trust - don't add received trust -use crate::storage_impl::SqliteStorageError::{ - ConvertionError, DecodeError, EncodeError, RevokeError, SqliteError, Unexpected, +use crate::storage_impl::SQLiteStorageError::{ + DecodeError, EncodeError, PublcKeyNotFound, PublicKeyConversion, PublicKeyFromStr, SQLiteError, + TrustNodeConversion, WeightConversionDB, }; use core::convert::TryFrom; use fce_sqlite_connector; @@ -23,9 +24,9 @@ use trust_graph::{ Auth, PublicKeyHashable, Revoke, Storage, StorageError, TrustGraph, TrustNode, Weight, }; -static INSTANCE: OnceCell>> = OnceCell::new(); +static INSTANCE: OnceCell>> = OnceCell::new(); -pub fn get_data() -> &'static Mutex> { +pub fn get_data() -> &'static Mutex> { INSTANCE.get_or_init(|| { let db_path = "/tmp/users123123.sqlite"; let connection = fce_sqlite_connector::open(db_path).unwrap(); @@ -41,64 +42,68 @@ pub fn get_data() -> &'static Mutex> { connection.execute(init_sql).expect("cannot connect to db"); - Mutex::new(TrustGraph::new(Box::new(SqliteStorage::new(connection)))) + Mutex::new(TrustGraph::new(Box::new(SQLiteStorage::new(connection)))) }) } -pub struct SqliteStorage { +pub struct SQLiteStorage { connection: Connection, } -impl SqliteStorage { - pub fn new(connection: Connection) -> SqliteStorage { - SqliteStorage { connection } +impl SQLiteStorage { + pub fn new(connection: Connection) -> SQLiteStorage { + SQLiteStorage { connection } } } #[derive(ThisError, Debug)] -pub enum SqliteStorageError { - #[error("Unexpected: {0}")] - Unexpected(String), +pub enum SQLiteStorageError { #[error("{0}")] - SqliteError(InternalSqliteError), + SQLiteError(InternalSqliteError), #[error("{0}")] - EncodeError(String), + PublicKeyFromStr(String), #[error("{0}")] - DecodeError(String), - #[error("There is no entry for {0}")] - ConvertionError(String), - #[error("Cannot revoke a trust: {0}")] - RevokeError(String), + EncodeError(RmpEncodeError), + #[error("{0}")] + DecodeError(RmpDecodeError), + #[error("Cannot convert weight as integer from DB")] + WeightConversionDB, + #[error("Cannot convert public key as binary from DB")] + PublicKeyConversion, + #[error("Cannot convert trust node as binary from DB")] + TrustNodeConversion, + #[error("Cannot revoke. There is no trust with such PublicKey")] + PublcKeyNotFound, } -impl From for SqliteStorageError { +impl From for SQLiteStorageError { fn from(err: InternalSqliteError) -> Self { - SqliteError(err) + SQLiteError(err) } } -impl From for SqliteStorageError { +impl From for SQLiteStorageError { fn from(err: RmpEncodeError) -> Self { - EncodeError(format!("{}", err)) + EncodeError(err) } } -impl From for SqliteStorageError { +impl From for SQLiteStorageError { fn from(err: RmpDecodeError) -> Self { - DecodeError(format!("{}", err)) + DecodeError(err) } } -impl From for String { - fn from(err: SqliteStorageError) -> Self { +impl From for String { + fn from(err: SQLiteStorageError) -> Self { err.into() } } -impl StorageError for SqliteStorageError {} +impl StorageError for SQLiteStorageError {} -impl Storage for SqliteStorage { - type Error = SqliteStorageError; +impl Storage for SQLiteStorage { + type Error = SQLiteStorageError; fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { let mut cursor = self @@ -111,9 +116,7 @@ impl Storage for SqliteStorage { match cursor.next().unwrap() { Some(r) => { log::info!("row: {:?}", r); - let tn_bin: &[u8] = r[0].as_binary().ok_or(ConvertionError( - "cannot get trustnode as binary".to_string(), - ))?; + let tn_bin: &[u8] = r[0].as_binary().ok_or(TrustNodeConversion)?; log::info!("binary: {:?}", tn_bin); @@ -155,12 +158,8 @@ impl Storage for SqliteStorage { if let Some(row) = cursor.next()? { log::info!("row: {:?}", row); - let w = u32::try_from( - row[1] - .as_integer() - .ok_or(ConvertionError("cannot get weight as integer".to_string()))?, - ) - .map_err(|e| Unexpected(format!("Unexpected. Cannot convert weight to u32: {}", e)))?; + let w = u32::try_from(row[1].as_integer().ok_or(WeightConversionDB)?) + .map_err(|_e| WeightConversionDB)?; Ok(Some(w)) } else { @@ -198,11 +197,9 @@ impl Storage for SqliteStorage { while let Some(row) = cursor.next()? { log::info!("row: {:?}", row); - let pk = row[0].as_string().ok_or(ConvertionError( - "cannot get public key as binary".to_string(), - ))?; + let pk = row[0].as_string().ok_or(PublicKeyConversion)?; let pk: PublicKeyHashable = - PublicKeyHashable::from_str(pk).map_err(|e| DecodeError(e.to_string()))?; + PublicKeyHashable::from_str(pk).map_err(|e| PublicKeyFromStr(e.to_string()))?; roots.push(pk) } @@ -217,9 +214,7 @@ impl Storage for SqliteStorage { self.insert(pk.clone(), trust_node)?; Ok(()) } - None => Err(RevokeError( - "There is no trust with such PublicKey".to_string(), - )), + None => Err(PublcKeyNotFound), } } From feac5dadf60a146f57b19f03696abc4ec1b59ff8 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Thu, 11 Feb 2021 15:16:40 +0300 Subject: [PATCH 10/19] clippy --- identity/src/key_pair.rs | 4 ++-- src/certificate.rs | 10 +++------- src/revoke.rs | 2 +- src/trust.rs | 12 +++++------- src/trust_graph.rs | 8 ++++---- src/trust_graph_storage.rs | 14 +++++++------- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/identity/src/key_pair.rs b/identity/src/key_pair.rs index da17e16..d0e05ce 100644 --- a/identity/src/key_pair.rs +++ b/identity/src/key_pair.rs @@ -144,8 +144,8 @@ impl<'de> serde::Deserialize<'de> for KeyPair { impl Clone for KeyPair { fn clone(&self) -> KeyPair { - let mut sk_bytes = self.key_pair.secret.to_bytes(); - let secret = ed25519_dalek::SecretKey::from_bytes(&mut sk_bytes) + let sk_bytes = self.key_pair.secret.to_bytes(); + let secret = ed25519_dalek::SecretKey::from_bytes(&sk_bytes) .expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k"); let public = ed25519_dalek::PublicKey::from_bytes(&self.key_pair.public.to_bytes()) .expect("ed25519::PublicKey::from_bytes(to_bytes(k)) != k"); diff --git a/src/certificate.rs b/src/certificate.rs index f5d6537..bb24d7f 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -109,11 +109,7 @@ impl Certificate { } // first, verify given certificate - Certificate::verify( - extend_cert, - &[extend_cert.chain[0].issued_for.clone()], - cur_time, - )?; + Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for], cur_time)?; let issued_by_pk = issued_by.public_key(); @@ -157,7 +153,7 @@ impl Certificate { // check root trust and its existence in trusted roots list let root = &chain[0]; - Trust::verify(root, &root.issued_for, cur_time).map_err(|e| MalformedRoot(e))?; + Trust::verify(root, &root.issued_for, cur_time).map_err(MalformedRoot)?; if !trusted_roots.contains(&root.issued_for) { return Err(NoTrustedRoot); } @@ -214,7 +210,7 @@ impl Certificate { let from = i * TRUST_LEN + 6; let to = (i + 1) * TRUST_LEN + 6; let slice = &arr[from..to]; - let t = Trust::decode(slice).map_err(|e| DecodeError(e))?; + let t = Trust::decode(slice).map_err(DecodeError)?; chain.push(t); } diff --git a/src/revoke.rs b/src/revoke.rs index 582e23a..cd7d42e 100644 --- a/src/revoke.rs +++ b/src/revoke.rs @@ -84,7 +84,7 @@ impl Revoke { revoke .revoked_by .verify_strict(msg.as_slice(), &revoke.signature) - .map_err(|err| IncorrectSignature(err)) + .map_err(IncorrectSignature) } } diff --git a/src/trust.rs b/src/trust.rs index 8b1a35a..df45aa0 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -119,7 +119,7 @@ impl Trust { let msg: &[u8] = &Self::metadata_bytes(&trust.issued_for, trust.expires_at, trust.issued_at); - KeyPair::verify(issued_by, msg, &trust.signature).map_err(|e| SignatureError(e))?; + KeyPair::verify(issued_by, msg, &trust.signature).map_err(SignatureError)?; Ok(()) } @@ -166,9 +166,8 @@ impl Trust { })?; let signature = &arr[PK_LEN..PK_LEN + SIG_LEN]; - let signature = Signature::from_bytes(signature).map_err(|err| { - DecodeError(format!("Cannot decode a signature: {}", err.to_string())) - })?; + let signature = Signature::from_bytes(signature) + .map_err(|err| DecodeError(format!("Cannot decode a signature: {}", err)))?; let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN]; let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap()); @@ -180,7 +179,7 @@ impl Trust { Ok(Self { issued_for: pk, - signature: signature, + signature, expires_at: expiration_date, issued_at: issued_date, }) @@ -222,8 +221,7 @@ impl Trust { // 64 bytes signature let signature = Self::bs58_str_to_vec(signature, "signature")?; - let signature = - Signature::from_bytes(&signature).map_err(|err| DecodeError(err.to_string()))?; + let signature = Signature::from_bytes(&signature).map_err(DecodeError)?; // Duration let expires_at = Self::str_to_duration(expires_at, "expires_at")?; diff --git a/src/trust_graph.rs b/src/trust_graph.rs index 34f9792..18c7c8f 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -92,7 +92,7 @@ where S: Storage, { pub fn new(storage: Box) -> Self { - Self { storage: storage } + Self { storage } } /// Insert new root weight @@ -131,10 +131,10 @@ where // Insert new TrustNode for this root_pk if there wasn't one if self.storage.get(&root_pk)?.is_none() { - let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time); + let mut trust_node = TrustNode::new(root_trust.issued_for, cur_time); let root_auth = Auth { trust: root_trust.clone(), - issued_by: root_trust.issued_for.clone(), + issued_by: root_trust.issued_for, }; trust_node.update_auth(root_auth); self.storage.insert(root_pk, trust_node)?; @@ -147,7 +147,7 @@ where let auth = Auth { trust: trust.clone(), - issued_by: previous_trust.issued_for.clone(), + issued_by: previous_trust.issued_for, }; self.storage diff --git a/src/trust_graph_storage.rs b/src/trust_graph_storage.rs index 3a79302..09d2fda 100644 --- a/src/trust_graph_storage.rs +++ b/src/trust_graph_storage.rs @@ -45,7 +45,7 @@ impl InMemoryStorage { .collect(); Self { nodes: HashMap::new(), - root_weights: root_weights, + root_weights, } } @@ -74,7 +74,7 @@ impl Storage for InMemoryStorage { } fn insert(&mut self, pk: PK, node: TrustNode) -> Result<(), Self::Error> { - &self.nodes.insert(pk, node); + self.nodes.insert(pk, node); Ok(()) } @@ -83,8 +83,8 @@ impl Storage for InMemoryStorage { } fn add_root_weight(&mut self, pk: PK, weight: Weight) -> Result<(), Self::Error> { - &self.root_weights.insert(pk, weight); - Ok({}) + self.root_weights.insert(pk, weight); + Ok(()) } fn root_keys(&self) -> Result, Self::Error> { @@ -113,13 +113,13 @@ impl Storage for InMemoryStorage { match self.nodes.get_mut(&pk) { Some(trust_node) => { trust_node.update_auth(auth); - Ok({}) + Ok(()) } None => { - let mut trust_node = TrustNode::new(issued_for.clone(), cur_time); + let mut trust_node = TrustNode::new(*issued_for, cur_time); trust_node.update_auth(auth); self.nodes.insert(pk.clone(), trust_node); - Ok({}) + Ok(()) } } } From 1e9b8ba33b86567db4d27da287cad5bcdfb214f6 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Thu, 11 Feb 2021 17:57:09 +0300 Subject: [PATCH 11/19] structurize errors --- Cargo.lock | 1 + identity/Cargo.lock | 1 + identity/Cargo.toml | 1 + identity/src/key_pair.rs | 3 +-- identity/src/public_key.rs | 18 ++++++++++++++++-- identity/src/signature.rs | 5 +++-- src/lib.rs | 4 ++-- src/public_key_hashable.rs | 21 +++------------------ src/trust.rs | 33 ++++++++++++++++++++------------- wasm/Cargo.lock | 1 + wasm/src/results.rs | 19 ++++++++++--------- wasm/src/service_api.rs | 38 ++++++++++++++++++++++++-------------- 12 files changed, 83 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 191ca4f..1ec8e00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -406,6 +406,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] diff --git a/identity/Cargo.lock b/identity/Cargo.lock index 59a3460..244fe4a 100644 --- a/identity/Cargo.lock +++ b/identity/Cargo.lock @@ -344,6 +344,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] diff --git a/identity/Cargo.toml b/identity/Cargo.toml index fb6f25e..05b335d 100644 --- a/identity/Cargo.toml +++ b/identity/Cargo.toml @@ -16,3 +16,4 @@ rand = "0.7.0" signature = "1.3.0" ed25519 = "1.0.3" serde_with = "1.6.0" +thiserror = "1.0.23" diff --git a/identity/src/key_pair.rs b/identity/src/key_pair.rs index d0e05ce..06a4b54 100644 --- a/identity/src/key_pair.rs +++ b/identity/src/key_pair.rs @@ -79,11 +79,10 @@ impl KeyPair { } /// Verify the Ed25519 signature on a message using the public key. - pub fn verify(pk: &PublicKey, msg: &[u8], signature: &Signature) -> Result<(), String> { + pub fn verify(pk: &PublicKey, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> { // let signature = ed25519_dalek::Signature::from_bytes(signature) // .map_err(|err| format!("Cannot convert bytes to a signature: {:?}", err))?; pk.verify_strict(msg, signature) - .map_err(|err| format!("Signature verification failed: {:?}", err)) } } diff --git a/identity/src/public_key.rs b/identity/src/public_key.rs index be2ffa5..edac73d 100644 --- a/identity/src/public_key.rs +++ b/identity/src/public_key.rs @@ -14,10 +14,20 @@ * limitations under the License. */ +use crate::public_key::PKError::{FromBase58Error, FromBytesError}; use crate::signature::Signature; use core::fmt::Debug; use ed25519_dalek::SignatureError; use serde::{Deserialize, Serialize}; +use thiserror::Error as ThisError; + +#[derive(ThisError, Debug)] +pub enum PKError { + #[error("Cannot decode public key from bytes: {0}")] + FromBytesError(SignatureError), + #[error("Cannot decode public key from base58 format: {0}")] + FromBase58Error(bs58::decode::Error), +} #[derive(Copy, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct PublicKey(pub(crate) ed25519_dalek::PublicKey); @@ -37,9 +47,13 @@ impl PublicKey { self.0.verify_strict(message, &signature.0) } - pub fn from_bytes(bytes: &[u8]) -> Result { - let pk = ed25519_dalek::PublicKey::from_bytes(bytes)?; + pub fn from_base58(str: &str) -> Result { + let bytes = bs58::decode(str).into_vec().map_err(FromBase58Error)?; + Self::from_bytes(&bytes) + } + pub fn from_bytes(bytes: &[u8]) -> Result { + let pk = ed25519_dalek::PublicKey::from_bytes(bytes).map_err(FromBytesError)?; Ok(PublicKey(pk)) } diff --git a/identity/src/signature.rs b/identity/src/signature.rs index 650f4d4..a65355c 100644 --- a/identity/src/signature.rs +++ b/identity/src/signature.rs @@ -15,6 +15,7 @@ */ use serde::{Deserialize, Serialize}; +use signature::Error as SigError; use signature::Signature as SigSignature; #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -33,8 +34,8 @@ impl Signature { self.0.to_bytes() } - pub fn from_bytes(bytes: &[u8]) -> Result { - let sig = ed25519_dalek::Signature::from_bytes(bytes).map_err(|err| err.to_string())?; + pub fn from_bytes(bytes: &[u8]) -> Result { + let sig = ed25519_dalek::Signature::from_bytes(bytes)?; Ok(Signature(sig)) } } diff --git a/src/lib.rs b/src/lib.rs index 53cce51..3e04635 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,11 +36,11 @@ mod trust_graph; mod trust_graph_storage; mod trust_node; -pub use crate::certificate::Certificate; +pub use crate::certificate::{Certificate, CertificateError}; pub use crate::misc::current_time; pub use crate::public_key_hashable::PublicKeyHashable; pub use crate::revoke::Revoke; pub use crate::trust::Trust; -pub use crate::trust_graph::{TrustGraph, Weight}; +pub use crate::trust_graph::{TrustGraph, TrustGraphError, Weight}; pub use crate::trust_graph_storage::{Storage, StorageError}; pub use crate::trust_node::{Auth, TrustNode}; diff --git a/src/public_key_hashable.rs b/src/public_key_hashable.rs index 0bc0dea..809a37c 100644 --- a/src/public_key_hashable.rs +++ b/src/public_key_hashable.rs @@ -14,11 +14,9 @@ * limitations under the License. */ -use fluence_identity::public_key::PublicKey; +use fluence_identity::public_key::{PKError, PublicKey}; -use crate::public_key_hashable::PkError::{Base58DecodeError, BytesDecodeError}; use core::fmt; -use ed25519_dalek::SignatureError; use ref_cast::RefCast; use serde::ser::Serializer; use std::str::FromStr; @@ -26,7 +24,6 @@ use std::{ fmt::{Display, Formatter}, hash::{Hash, Hasher}, }; -use thiserror::Error as ThisError; /// Wrapper to use PublicKey in HashMap #[derive(PartialEq, Eq, Debug, Clone, RefCast)] @@ -84,23 +81,11 @@ impl Display for PublicKeyHashable { } } -#[derive(ThisError, Debug)] -pub enum PkError { - #[error("Invalid string '{0}': {1}")] - Base58DecodeError(String, bs58::decode::Error), - #[error("Invalid bytes {0:?}: {1}")] - BytesDecodeError(Vec, SignatureError), -} - impl FromStr for PublicKeyHashable { - type Err = PkError; + type Err = PKError; fn from_str(s: &str) -> Result { - let bytes = bs58::decode(s) - .into_vec() - .map_err(|err| Base58DecodeError(s.to_string(), err))?; - - let pk = PublicKey::from_bytes(&bytes).map_err(|err| BytesDecodeError(bytes, err))?; + let pk = PublicKey::from_base58(s)?; Ok(PublicKeyHashable::from(pk)) } } diff --git a/src/trust.rs b/src/trust.rs index df45aa0..5336cd7 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -14,10 +14,12 @@ * limitations under the License. */ -use crate::trust::TrustError::{DecodeError, SignatureError}; +use crate::trust::TrustError::{ + DecodeError, IncorrectTrustLength, PublicKeyError, SignatureError, SignatureFromBytesError, +}; use derivative::Derivative; use fluence_identity::key_pair::KeyPair; -use fluence_identity::public_key::PublicKey; +use fluence_identity::public_key::{PKError, PublicKey}; use fluence_identity::signature::Signature; use serde::{Deserialize, Serialize}; use std::convert::TryInto; @@ -65,11 +67,22 @@ pub enum TrustError { /// Errors occured on signature verification #[error("{0}")] - SignatureError(String), + SignatureError(ed25519_dalek::SignatureError), /// Errors occured on trust decoding from differrent formats #[error("{0}")] DecodeError(String), + + #[error("Cannot decode a signature from bytes: {0}")] + SignatureFromBytesError(signature::Error), + + #[error("{0}")] + PublicKeyError(PKError), + + #[error( + "Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {0}" + )] + IncorrectTrustLength(usize), } impl Trust { @@ -155,19 +168,13 @@ impl Trust { #[allow(dead_code)] pub fn decode(arr: &[u8]) -> Result { if arr.len() != TRUST_LEN { - return Err(DecodeError( - format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}", - arr.len()) - )); + return Err(IncorrectTrustLength(arr.len())); } - let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(|err| { - DecodeError(format!("Cannot decode a public key: {}", err.to_string())) - })?; + let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(PublicKeyError)?; let signature = &arr[PK_LEN..PK_LEN + SIG_LEN]; - let signature = Signature::from_bytes(signature) - .map_err(|err| DecodeError(format!("Cannot decode a signature: {}", err)))?; + let signature = Signature::from_bytes(signature).map_err(SignatureFromBytesError)?; let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN]; let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap()); @@ -221,7 +228,7 @@ impl Trust { // 64 bytes signature let signature = Self::bs58_str_to_vec(signature, "signature")?; - let signature = Signature::from_bytes(&signature).map_err(DecodeError)?; + let signature = Signature::from_bytes(&signature).map_err(SignatureFromBytesError)?; // Duration let expires_at = Self::str_to_duration(expires_at, "expires_at")?; diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 2eb3a9f..2e40478 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -441,6 +441,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] diff --git a/wasm/src/results.rs b/wasm/src/results.rs index fa8cdee..dce4cfd 100644 --- a/wasm/src/results.rs +++ b/wasm/src/results.rs @@ -1,4 +1,5 @@ use crate::dto::Certificate; +use crate::service_api::ServiceError; use fluence::fce; #[fce] @@ -7,8 +8,8 @@ pub struct InsertResult { pub error: String, } -impl From> for InsertResult { - fn from(result: Result<(), String>) -> Self { +impl From> for InsertResult { + fn from(result: Result<(), ServiceError>) -> Self { match result { Ok(()) => InsertResult { ret_code: 0, @@ -16,7 +17,7 @@ impl From> for InsertResult { }, Err(e) => InsertResult { ret_code: 1, - error: e, + error: format!("{}", e), }, } } @@ -29,8 +30,8 @@ pub struct WeightResult { pub error: String, } -impl From, String>> for WeightResult { - fn from(result: Result, String>) -> Self { +impl From, ServiceError>> for WeightResult { + fn from(result: Result, ServiceError>) -> Self { match result { Ok(wo) => WeightResult { ret_code: 0, @@ -40,7 +41,7 @@ impl From, String>> for WeightResult { Err(e) => WeightResult { ret_code: 1, weight: vec![], - error: e, + error: format!("{}", e), }, } } @@ -53,8 +54,8 @@ pub struct AllCertsResult { pub error: String, } -impl From, String>> for AllCertsResult { - fn from(result: Result, String>) -> Self { +impl From, ServiceError>> for AllCertsResult { + fn from(result: Result, ServiceError>) -> Self { match result { Ok(certs) => AllCertsResult { ret_code: 0, @@ -64,7 +65,7 @@ impl From, String>> for AllCertsResult { Err(e) => AllCertsResult { ret_code: 1, certificates: vec![], - error: e, + error: format!("{}", e), }, } } diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index 9ac8de7..e81a925 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -1,19 +1,33 @@ use crate::dto::Certificate; use crate::results::{AllCertsResult, InsertResult, WeightResult}; +use crate::service_api::ServiceError::{CertError, PublicKeyDecodeError, TGError}; use crate::storage_impl::get_data; use fluence::fce; +use fluence_identity::public_key::PKError; use fluence_identity::{KeyPair, PublicKey}; use std::convert::Into; use std::str::FromStr; use std::time::Duration; +use thiserror::Error as ThisError; +use trust_graph::{CertificateError, TrustGraphError}; -fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), String> { +#[derive(ThisError, Debug)] +pub enum ServiceError { + #[error("{0}")] + PublicKeyDecodeError(PKError), + + #[error("{0}")] + TGError(TrustGraphError), + #[error("{0}")] + CertError(CertificateError), +} + +fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), ServiceError> { let duration = Duration::from_millis(duration); - let certificate = - trust_graph::Certificate::from_str(&certificate).map_err(|e| format!("{}", e))?; + let certificate = trust_graph::Certificate::from_str(&certificate).map_err(CertError)?; let mut tg = get_data().lock(); - tg.add(certificate, duration)?; + tg.add(certificate, duration).map_err(TGError)?; Ok(()) } @@ -23,12 +37,12 @@ fn insert_cert(certificate: String, duration: u64) -> InsertResult { insert_cert_impl(certificate, duration).into() } -fn get_weight_impl(public_key: String) -> Result, String> { +fn get_weight_impl(public_key: String) -> Result, ServiceError> { let tg = get_data().lock(); let public_key = string_to_public_key(public_key)?; - let weight = tg.weight(public_key)?; + let weight = tg.weight(public_key).map_err(TGError)?; Ok(weight) } @@ -38,12 +52,8 @@ fn get_weight(public_key: String) -> WeightResult { get_weight_impl(public_key).into() } -fn string_to_public_key(public_key: String) -> Result { - let public_key = bs58::decode(public_key) - .into_vec() - .map_err(|e| format!("Couldn't decode public_key from base58: {}", e))?; - let public_key = PublicKey::from_bytes(&public_key) - .map_err(|e| format!("Couldn't decode public_key: {}", e))?; +fn string_to_public_key(public_key: String) -> Result { + let public_key = PublicKey::from_base58(&public_key).map_err(PublicKeyDecodeError)?; Ok(public_key) } @@ -53,11 +63,11 @@ fn get_all_certs(issued_for: String) -> AllCertsResult { get_all_certs_impl(issued_for).into() } -fn get_all_certs_impl(issued_for: String) -> Result, String> { +fn get_all_certs_impl(issued_for: String) -> Result, ServiceError> { let tg = get_data().lock(); let public_key = string_to_public_key(issued_for)?; - let certs = tg.get_all_certs(public_key, &[])?; + let certs = tg.get_all_certs(public_key, &[]).map_err(TGError)?; Ok(certs.into_iter().map(|c| c.into()).collect()) } From fb13bc1cdf41afd43356538c7bd9c0744e12ceff Mon Sep 17 00:00:00 2001 From: DieMyst Date: Thu, 11 Feb 2021 18:14:14 +0300 Subject: [PATCH 12/19] structurize errors --- src/trust.rs | 40 +++++++++++++++++++--------------------- wasm/src/service_api.rs | 17 ++++++++--------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/trust.rs b/src/trust.rs index 5336cd7..4567676 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -15,7 +15,8 @@ */ use crate::trust::TrustError::{ - DecodeError, IncorrectTrustLength, PublicKeyError, SignatureError, SignatureFromBytesError, + Base58DecodeError, DecodePublicKeyError, IncorrectTrustLength, ParseError, PublicKeyError, + SignatureError, SignatureFromBytesError, }; use derivative::Derivative; use fluence_identity::key_pair::KeyPair; @@ -23,6 +24,7 @@ use fluence_identity::public_key::{PKError, PublicKey}; use fluence_identity::signature::Signature; use serde::{Deserialize, Serialize}; use std::convert::TryInto; +use std::num::ParseIntError; use std::time::Duration; use thiserror::Error as ThisError; @@ -70,8 +72,14 @@ pub enum TrustError { SignatureError(ed25519_dalek::SignatureError), /// Errors occured on trust decoding from differrent formats - #[error("{0}")] - DecodeError(String), + #[error("Cannot decode the public key: {0} in the trust: {1}")] + DecodePublicKeyError(String, PKError), + + #[error("Cannot parse `{0}` field in the trust '{1}': {2}")] + ParseError(String, String, ParseIntError), + + #[error("Cannot decode `{0}` from base58 format in the trust '{1}': {2}")] + Base58DecodeError(String, String, bs58::decode::Error), #[error("Cannot decode a signature from bytes: {0}")] SignatureFromBytesError(signature::Error), @@ -193,21 +201,15 @@ impl Trust { } fn bs58_str_to_vec(str: &str, field: &str) -> Result, TrustError> { - bs58::decode(str).into_vec().map_err(|e| { - DecodeError(format!( - "Cannot decode `{}` from base58 format in the trust '{}': {}", - field, str, e - )) - }) + bs58::decode(str) + .into_vec() + .map_err(|e| Base58DecodeError(field.to_string(), str.to_string(), e)) } fn str_to_duration(str: &str, field: &str) -> Result { - let secs = str.parse().map_err(|e| { - DecodeError(format!( - "Cannot parse `{}` field in the trust '{}': {}", - field, str, e - )) - })?; + let secs = str + .parse() + .map_err(|e| ParseError(field.to_string(), str.to_string(), e))?; Ok(Duration::from_secs(secs)) } @@ -219,12 +221,8 @@ impl Trust { ) -> Result { // PublicKey let issued_for_bytes = Self::bs58_str_to_vec(issued_for, "issued_for")?; - let issued_for = PublicKey::from_bytes(issued_for_bytes.as_slice()).map_err(|e| { - DecodeError(format!( - "Cannot decode the public key: {} in the trust '{}'", - issued_for, e - )) - })?; + let issued_for = PublicKey::from_bytes(issued_for_bytes.as_slice()) + .map_err(|e| DecodePublicKeyError(issued_for.to_string(), e))?; // 64 bytes signature let signature = Self::bs58_str_to_vec(signature, "signature")?; diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index e81a925..a05f775 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -1,6 +1,5 @@ use crate::dto::Certificate; use crate::results::{AllCertsResult, InsertResult, WeightResult}; -use crate::service_api::ServiceError::{CertError, PublicKeyDecodeError, TGError}; use crate::storage_impl::get_data; use fluence::fce; use fluence_identity::public_key::PKError; @@ -14,20 +13,20 @@ use trust_graph::{CertificateError, TrustGraphError}; #[derive(ThisError, Debug)] pub enum ServiceError { #[error("{0}")] - PublicKeyDecodeError(PKError), + PublicKeyDecodeError(#[from] PKError), #[error("{0}")] - TGError(TrustGraphError), + TGError(#[from] TrustGraphError), #[error("{0}")] - CertError(CertificateError), + CertError(#[from] CertificateError), } fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), ServiceError> { let duration = Duration::from_millis(duration); - let certificate = trust_graph::Certificate::from_str(&certificate).map_err(CertError)?; + let certificate = trust_graph::Certificate::from_str(&certificate)?; let mut tg = get_data().lock(); - tg.add(certificate, duration).map_err(TGError)?; + tg.add(certificate, duration)?; Ok(()) } @@ -42,7 +41,7 @@ fn get_weight_impl(public_key: String) -> Result, ServiceError> { let public_key = string_to_public_key(public_key)?; - let weight = tg.weight(public_key).map_err(TGError)?; + let weight = tg.weight(public_key)?; Ok(weight) } @@ -53,7 +52,7 @@ fn get_weight(public_key: String) -> WeightResult { } fn string_to_public_key(public_key: String) -> Result { - let public_key = PublicKey::from_base58(&public_key).map_err(PublicKeyDecodeError)?; + let public_key = PublicKey::from_base58(&public_key)?; Ok(public_key) } @@ -67,7 +66,7 @@ fn get_all_certs_impl(issued_for: String) -> Result, ServiceErr let tg = get_data().lock(); let public_key = string_to_public_key(issued_for)?; - let certs = tg.get_all_certs(public_key, &[]).map_err(TGError)?; + let certs = tg.get_all_certs(public_key, &[])?; Ok(certs.into_iter().map(|c| c.into()).collect()) } From 66ace9d3df6866d2161485f6f914e851c90d490f Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 12 Feb 2021 14:27:22 +0300 Subject: [PATCH 13/19] dto conversion, more errors --- identity/src/signature.rs | 9 +++++++- src/trust.rs | 17 +++++++------- wasm/src/dto.rs | 48 +++++++++++++++++++++++++++++++++++++++ wasm/src/service_api.rs | 9 ++++---- 4 files changed, 69 insertions(+), 14 deletions(-) diff --git a/identity/src/signature.rs b/identity/src/signature.rs index a65355c..7ee125c 100644 --- a/identity/src/signature.rs +++ b/identity/src/signature.rs @@ -17,6 +17,13 @@ use serde::{Deserialize, Serialize}; use signature::Error as SigError; use signature::Signature as SigSignature; +use thiserror::Error as ThisError; + +#[derive(ThisError, Debug)] +pub enum SignatureError { + #[error("{0}")] + Error(#[from] SigError), +} #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Signature(pub ed25519_dalek::Signature); @@ -34,7 +41,7 @@ impl Signature { self.0.to_bytes() } - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> Result { let sig = ed25519_dalek::Signature::from_bytes(bytes)?; Ok(Signature(sig)) } diff --git a/src/trust.rs b/src/trust.rs index 4567676..b2db75b 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -15,13 +15,12 @@ */ use crate::trust::TrustError::{ - Base58DecodeError, DecodePublicKeyError, IncorrectTrustLength, ParseError, PublicKeyError, - SignatureError, SignatureFromBytesError, + Base58DecodeError, DecodePublicKeyError, IncorrectTrustLength, ParseError, SignatureError, }; use derivative::Derivative; use fluence_identity::key_pair::KeyPair; use fluence_identity::public_key::{PKError, PublicKey}; -use fluence_identity::signature::Signature; +use fluence_identity::signature::{Signature, SignatureError as SigError}; use serde::{Deserialize, Serialize}; use std::convert::TryInto; use std::num::ParseIntError; @@ -69,7 +68,7 @@ pub enum TrustError { /// Errors occured on signature verification #[error("{0}")] - SignatureError(ed25519_dalek::SignatureError), + SignatureError(#[from] ed25519_dalek::SignatureError), /// Errors occured on trust decoding from differrent formats #[error("Cannot decode the public key: {0} in the trust: {1}")] @@ -82,10 +81,10 @@ pub enum TrustError { Base58DecodeError(String, String, bs58::decode::Error), #[error("Cannot decode a signature from bytes: {0}")] - SignatureFromBytesError(signature::Error), + SignatureFromBytesError(#[from] SigError), #[error("{0}")] - PublicKeyError(PKError), + PublicKeyError(#[from] PKError), #[error( "Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {0}" @@ -179,10 +178,10 @@ impl Trust { return Err(IncorrectTrustLength(arr.len())); } - let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(PublicKeyError)?; + let pk = PublicKey::from_bytes(&arr[0..PK_LEN])?; let signature = &arr[PK_LEN..PK_LEN + SIG_LEN]; - let signature = Signature::from_bytes(signature).map_err(SignatureFromBytesError)?; + let signature = Signature::from_bytes(signature)?; let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN]; let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap()); @@ -226,7 +225,7 @@ impl Trust { // 64 bytes signature let signature = Self::bs58_str_to_vec(signature, "signature")?; - let signature = Signature::from_bytes(&signature).map_err(SignatureFromBytesError)?; + let signature = Signature::from_bytes(&signature)?; // Duration let expires_at = Self::str_to_duration(expires_at, "expires_at")?; diff --git a/wasm/src/dto.rs b/wasm/src/dto.rs index 60302a3..f1628c4 100644 --- a/wasm/src/dto.rs +++ b/wasm/src/dto.rs @@ -1,4 +1,20 @@ use fluence::fce; +use fluence_identity::public_key::PKError; +use fluence_identity::signature::SignatureError; +use fluence_identity::{PublicKey, Signature}; +use std::convert::TryFrom; +use std::time::Duration; +use thiserror::Error as ThisError; + +#[derive(ThisError, Debug)] +pub enum DtoConversionError { + #[error("Cannot convert base58 string to bytes: {0}")] + Base58Error(#[from] bs58::decode::Error), + #[error("Cannot convert string to PublicKey: {0}")] + PublicKeyDecodeError(#[from] PKError), + #[error("Cannot convert string to PublicKey: {0}")] + SignatureDecodeError(#[from] SignatureError), +} #[fce] pub struct Certificate { @@ -12,6 +28,20 @@ impl From for Certificate { } } +impl TryFrom for trust_graph::Certificate { + type Error = DtoConversionError; + + fn try_from(c: Certificate) -> Result { + let chain: Result, DtoConversionError> = c + .chain + .into_iter() + .map(|t| trust_graph::Trust::try_from(t)) + .collect(); + let chain = chain?; + return Ok(trust_graph::Certificate { chain }); + } +} + #[fce] pub struct Trust { /// For whom this certificate is issued, base58 @@ -25,6 +55,24 @@ pub struct Trust { pub issued_at: u64, } +impl TryFrom for trust_graph::Trust { + type Error = DtoConversionError; + + fn try_from(t: Trust) -> Result { + let issued_for = PublicKey::from_base58(&t.issued_for)?; + let signature = bs58::decode(&t.signature).into_vec()?; + let signature = Signature::from_bytes(&signature)?; + let expires_at = Duration::from_secs(t.expires_at); + let issued_at = Duration::from_secs(t.issued_at); + return Ok(trust_graph::Trust { + issued_for, + expires_at, + signature, + issued_at, + }); + } +} + impl From for Trust { fn from(t: trust_graph::Trust) -> Self { let issued_for = bs58::encode(t.issued_for.to_bytes()).into_string(); diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index a05f775..f48bf58 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -14,7 +14,6 @@ use trust_graph::{CertificateError, TrustGraphError}; pub enum ServiceError { #[error("{0}")] PublicKeyDecodeError(#[from] PKError), - #[error("{0}")] TGError(#[from] TrustGraphError), #[error("{0}")] @@ -31,9 +30,11 @@ fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), ServiceErr } #[fce] -// TODO: some sort of auth? -fn insert_cert(certificate: String, duration: u64) -> InsertResult { - insert_cert_impl(certificate, duration).into() +/// add a certificate in string representation to trust graph if it is valid +/// see `Certificate` class for string encoding/decoding +// TODO change `current_time` to time service +fn insert_cert(certificate: String, current_time: u64) -> InsertResult { + insert_cert_impl(certificate, current_time).into() } fn get_weight_impl(public_key: String) -> Result, ServiceError> { From 816b3754a4fa5ae367c7a633f674fb1c71ce126b Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 12 Feb 2021 14:34:23 +0300 Subject: [PATCH 14/19] add cert as string and as json --- wasm/src/service_api.rs | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index f48bf58..916d45c 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -1,10 +1,10 @@ -use crate::dto::Certificate; +use crate::dto::{Certificate, DtoConversionError}; use crate::results::{AllCertsResult, InsertResult, WeightResult}; use crate::storage_impl::get_data; use fluence::fce; use fluence_identity::public_key::PKError; use fluence_identity::{KeyPair, PublicKey}; -use std::convert::Into; +use std::convert::{Into, TryInto}; use std::str::FromStr; use std::time::Duration; use thiserror::Error as ThisError; @@ -18,22 +18,43 @@ pub enum ServiceError { TGError(#[from] TrustGraphError), #[error("{0}")] CertError(#[from] CertificateError), + #[error("{0}")] + DtoError(#[from] DtoConversionError), } -fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), ServiceError> { +fn add_cert(certificate: trust_graph::Certificate, duration: u64) -> Result<(), ServiceError> { let duration = Duration::from_millis(duration); - let certificate = trust_graph::Certificate::from_str(&certificate)?; - let mut tg = get_data().lock(); tg.add(certificate, duration)?; Ok(()) } +fn insert_cert_impl_raw(certificate: String, duration: u64) -> Result<(), ServiceError> { + let certificate = trust_graph::Certificate::from_str(&certificate)?; + + add_cert(certificate, duration)?; + Ok(()) +} + +fn insert_cert_impl(certificate: Certificate, duration: u64) -> Result<(), ServiceError> { + let certificate: trust_graph::Certificate = certificate.try_into()?; + + add_cert(certificate, duration)?; + Ok(()) +} + #[fce] /// add a certificate in string representation to trust graph if it is valid -/// see `Certificate` class for string encoding/decoding +/// see `trust_graph::Certificate` class for string encoding/decoding // TODO change `current_time` to time service -fn insert_cert(certificate: String, current_time: u64) -> InsertResult { +fn insert_cert_raw(certificate: String, current_time: u64) -> InsertResult { + insert_cert_impl_raw(certificate, current_time).into() +} + +#[fce] +/// add a certificate in JSON representation to trust graph if it is valid +/// see `dto::Certificate` class for structure +fn insert_cert(certificate: Certificate, current_time: u64) -> InsertResult { insert_cert_impl(certificate, current_time).into() } From a9d1e72653efc5d7465995f46f96747c066f6922 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 12 Feb 2021 14:42:51 +0300 Subject: [PATCH 15/19] refactoring --- wasm/src/main.rs | 1 + wasm/src/results.rs | 2 +- wasm/src/service_api.rs | 125 ++++++++++----------------------------- wasm/src/service_impl.rs | 63 ++++++++++++++++++++ 4 files changed, 97 insertions(+), 94 deletions(-) create mode 100644 wasm/src/service_impl.rs diff --git a/wasm/src/main.rs b/wasm/src/main.rs index 2b1848b..b1d4d68 100644 --- a/wasm/src/main.rs +++ b/wasm/src/main.rs @@ -3,6 +3,7 @@ use fluence::WasmLoggerBuilder; mod dto; mod results; mod service_api; +mod service_impl; mod storage_impl; pub fn main() { diff --git a/wasm/src/results.rs b/wasm/src/results.rs index dce4cfd..9be3faa 100644 --- a/wasm/src/results.rs +++ b/wasm/src/results.rs @@ -1,5 +1,5 @@ use crate::dto::Certificate; -use crate::service_api::ServiceError; +use crate::service_impl::ServiceError; use fluence::fce; #[fce] diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index 916d45c..c34bce1 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -1,47 +1,9 @@ -use crate::dto::{Certificate, DtoConversionError}; +use crate::dto::Certificate; use crate::results::{AllCertsResult, InsertResult, WeightResult}; -use crate::storage_impl::get_data; +use crate::service_impl::{ + get_all_certs_impl, get_weight_impl, insert_cert_impl, insert_cert_impl_raw, +}; use fluence::fce; -use fluence_identity::public_key::PKError; -use fluence_identity::{KeyPair, PublicKey}; -use std::convert::{Into, TryInto}; -use std::str::FromStr; -use std::time::Duration; -use thiserror::Error as ThisError; -use trust_graph::{CertificateError, TrustGraphError}; - -#[derive(ThisError, Debug)] -pub enum ServiceError { - #[error("{0}")] - PublicKeyDecodeError(#[from] PKError), - #[error("{0}")] - TGError(#[from] TrustGraphError), - #[error("{0}")] - CertError(#[from] CertificateError), - #[error("{0}")] - DtoError(#[from] DtoConversionError), -} - -fn add_cert(certificate: trust_graph::Certificate, duration: u64) -> Result<(), ServiceError> { - let duration = Duration::from_millis(duration); - let mut tg = get_data().lock(); - tg.add(certificate, duration)?; - Ok(()) -} - -fn insert_cert_impl_raw(certificate: String, duration: u64) -> Result<(), ServiceError> { - let certificate = trust_graph::Certificate::from_str(&certificate)?; - - add_cert(certificate, duration)?; - Ok(()) -} - -fn insert_cert_impl(certificate: Certificate, duration: u64) -> Result<(), ServiceError> { - let certificate: trust_graph::Certificate = certificate.try_into()?; - - add_cert(certificate, duration)?; - Ok(()) -} #[fce] /// add a certificate in string representation to trust graph if it is valid @@ -58,64 +20,41 @@ fn insert_cert(certificate: Certificate, current_time: u64) -> InsertResult { insert_cert_impl(certificate, current_time).into() } -fn get_weight_impl(public_key: String) -> Result, ServiceError> { - let tg = get_data().lock(); - - let public_key = string_to_public_key(public_key)?; - - let weight = tg.weight(public_key)?; - - Ok(weight) -} - #[fce] fn get_weight(public_key: String) -> WeightResult { get_weight_impl(public_key).into() } -fn string_to_public_key(public_key: String) -> Result { - let public_key = PublicKey::from_base58(&public_key)?; - - Ok(public_key) -} - #[fce] fn get_all_certs(issued_for: String) -> AllCertsResult { get_all_certs_impl(issued_for).into() } -fn get_all_certs_impl(issued_for: String) -> Result, ServiceError> { - let tg = get_data().lock(); - - let public_key = string_to_public_key(issued_for)?; - let certs = tg.get_all_certs(public_key, &[])?; - Ok(certs.into_iter().map(|c| c.into()).collect()) -} - -#[fce] -fn test() -> String { - let mut tg = get_data().lock(); - - let root_kp = KeyPair::generate(); - let root_kp2 = KeyPair::generate(); - let second_kp = KeyPair::generate(); - - let expires_at = Duration::new(15, 15); - let issued_at = Duration::new(5, 5); - - let cert = trust_graph::Certificate::issue_root( - &root_kp, - second_kp.public_key(), - expires_at, - issued_at, - ); - tg.add_root_weight(root_kp.public().into(), 0).unwrap(); - tg.add_root_weight(root_kp2.public().into(), 1).unwrap(); - tg.add(cert, Duration::new(10, 10)).unwrap(); - - let a = tg.get(second_kp.public_key()).unwrap(); - let str = format!("{:?}", a); - log::info!("{}", &str); - - str -} +// TODO rewrite test after #[fce_test] will be implemented +// #[fce] +// fn test() -> String { +// let mut tg = get_data().lock(); +// +// let root_kp = KeyPair::generate(); +// let root_kp2 = KeyPair::generate(); +// let second_kp = KeyPair::generate(); +// +// let expires_at = Duration::new(15, 15); +// let issued_at = Duration::new(5, 5); +// +// let cert = trust_graph::Certificate::issue_root( +// &root_kp, +// second_kp.public_key(), +// expires_at, +// issued_at, +// ); +// tg.add_root_weight(root_kp.public().into(), 0).unwrap(); +// tg.add_root_weight(root_kp2.public().into(), 1).unwrap(); +// tg.add(cert, Duration::new(10, 10)).unwrap(); +// +// let a = tg.get(second_kp.public_key()).unwrap(); +// let str = format!("{:?}", a); +// log::info!("{}", &str); +// +// str +// } diff --git a/wasm/src/service_impl.rs b/wasm/src/service_impl.rs new file mode 100644 index 0000000..4d2007a --- /dev/null +++ b/wasm/src/service_impl.rs @@ -0,0 +1,63 @@ +use crate::dto::{Certificate, DtoConversionError}; +use crate::storage_impl::get_data; +use fluence_identity::public_key::PKError; +use fluence_identity::PublicKey; +use std::convert::{Into, TryInto}; +use std::str::FromStr; +use std::time::Duration; +use thiserror::Error as ThisError; +use trust_graph::{CertificateError, TrustGraphError}; + +#[derive(ThisError, Debug)] +pub enum ServiceError { + #[error("{0}")] + PublicKeyDecodeError(#[from] PKError), + #[error("{0}")] + TGError(#[from] TrustGraphError), + #[error("{0}")] + CertError(#[from] CertificateError), + #[error("{0}")] + DtoError(#[from] DtoConversionError), +} + +pub fn get_weight_impl(public_key: String) -> Result, ServiceError> { + let tg = get_data().lock(); + let public_key = string_to_public_key(public_key)?; + let weight = tg.weight(public_key)?; + Ok(weight) +} + +fn add_cert(certificate: trust_graph::Certificate, duration: u64) -> Result<(), ServiceError> { + let duration = Duration::from_millis(duration); + let mut tg = get_data().lock(); + tg.add(certificate, duration)?; + Ok(()) +} + +pub fn insert_cert_impl_raw(certificate: String, duration: u64) -> Result<(), ServiceError> { + let certificate = trust_graph::Certificate::from_str(&certificate)?; + + add_cert(certificate, duration)?; + Ok(()) +} + +fn string_to_public_key(public_key: String) -> Result { + let public_key = PublicKey::from_base58(&public_key)?; + + Ok(public_key) +} + +pub fn get_all_certs_impl(issued_for: String) -> Result, ServiceError> { + let tg = get_data().lock(); + + let public_key = string_to_public_key(issued_for)?; + let certs = tg.get_all_certs(public_key, &[])?; + Ok(certs.into_iter().map(|c| c.into()).collect()) +} + +pub fn insert_cert_impl(certificate: Certificate, duration: u64) -> Result<(), ServiceError> { + let certificate: trust_graph::Certificate = certificate.try_into()?; + + add_cert(certificate, duration)?; + Ok(()) +} From 3bcc928a724d8610f86b8528232193d35fa9e676 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 12 Feb 2021 14:54:08 +0300 Subject: [PATCH 16/19] add_root function --- wasm/src/results.rs | 21 +++++++++++++++++++++ wasm/src/service_api.rs | 21 ++++++++++++++++++--- wasm/src/service_impl.rs | 9 ++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/wasm/src/results.rs b/wasm/src/results.rs index 9be3faa..ba7389d 100644 --- a/wasm/src/results.rs +++ b/wasm/src/results.rs @@ -70,3 +70,24 @@ impl From, ServiceError>> for AllCertsResult { } } } + +#[fce] +pub struct AddRootResult { + pub ret_code: u32, + pub error: String, +} + +impl From> for AddRootResult { + fn from(result: Result<(), ServiceError>) -> Self { + match result { + Ok(()) => AddRootResult { + ret_code: 0, + error: "".to_string(), + }, + Err(e) => AddRootResult { + ret_code: 1, + error: format!("{}", e), + }, + } + } +} diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index c34bce1..db44775 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -1,9 +1,9 @@ use crate::dto::Certificate; -use crate::results::{AllCertsResult, InsertResult, WeightResult}; +use crate::results::{AddRootResult, AllCertsResult, InsertResult, WeightResult}; use crate::service_impl::{ - get_all_certs_impl, get_weight_impl, insert_cert_impl, insert_cert_impl_raw, + add_root_impl, get_all_certs_impl, get_weight_impl, insert_cert_impl, insert_cert_impl_raw, }; -use fluence::fce; +use fluence::{fce, CallParameters}; #[fce] /// add a certificate in string representation to trust graph if it is valid @@ -30,6 +30,21 @@ fn get_all_certs(issued_for: String) -> AllCertsResult { get_all_certs_impl(issued_for).into() } +#[fce] +/// could add only a host of a trust graph service +fn add_root(pk: String, weight: u32) -> AddRootResult { + let call_parameters: CallParameters = fluence::get_call_parameters(); + let init_peer_id = call_parameters.init_peer_id.clone(); + if call_parameters.host_id == init_peer_id { + add_root_impl(pk, weight).into() + } else { + return AddRootResult { + ret_code: 1, + error: "Root could add only a host of trust graph service", + }; + } +} + // TODO rewrite test after #[fce_test] will be implemented // #[fce] // fn test() -> String { diff --git a/wasm/src/service_impl.rs b/wasm/src/service_impl.rs index 4d2007a..034c857 100644 --- a/wasm/src/service_impl.rs +++ b/wasm/src/service_impl.rs @@ -6,7 +6,7 @@ use std::convert::{Into, TryInto}; use std::str::FromStr; use std::time::Duration; use thiserror::Error as ThisError; -use trust_graph::{CertificateError, TrustGraphError}; +use trust_graph::{CertificateError, PublicKeyHashable, TrustGraphError}; #[derive(ThisError, Debug)] pub enum ServiceError { @@ -61,3 +61,10 @@ pub fn insert_cert_impl(certificate: Certificate, duration: u64) -> Result<(), S add_cert(certificate, duration)?; Ok(()) } + +pub fn add_root_impl(pk: String, weight: u32) -> Result<(), ServiceError> { + let mut tg = get_data().lock(); + let pk = PublicKey::from_base58(&pk)?.into(); + tg.add_root_weight(pk, weight)?; + Ok(()) +} From 953e0b6f0a8dfa113e9155f5b6dfe4a289957023 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 12 Feb 2021 14:54:38 +0300 Subject: [PATCH 17/19] fix compilation --- wasm/src/service_api.rs | 2 +- wasm/src/service_impl.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index db44775..9188b95 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -40,7 +40,7 @@ fn add_root(pk: String, weight: u32) -> AddRootResult { } else { return AddRootResult { ret_code: 1, - error: "Root could add only a host of trust graph service", + error: "Root could add only a host of trust graph service".to_string(), }; } } diff --git a/wasm/src/service_impl.rs b/wasm/src/service_impl.rs index 034c857..054cd61 100644 --- a/wasm/src/service_impl.rs +++ b/wasm/src/service_impl.rs @@ -6,7 +6,7 @@ use std::convert::{Into, TryInto}; use std::str::FromStr; use std::time::Duration; use thiserror::Error as ThisError; -use trust_graph::{CertificateError, PublicKeyHashable, TrustGraphError}; +use trust_graph::{CertificateError, TrustGraphError}; #[derive(ThisError, Debug)] pub enum ServiceError { From 5ff8d2f8d0f6a0241083616b29687a42e3d0964f Mon Sep 17 00:00:00 2001 From: DieMyst Date: Mon, 15 Feb 2021 12:44:41 +0300 Subject: [PATCH 18/19] transparent, PublicKeyHashable -> PK --- identity/src/signature.rs | 2 +- src/trust.rs | 4 ++-- src/trust_graph.rs | 16 ++++++---------- wasm/src/service_impl.rs | 8 ++++---- wasm/src/storage_impl.rs | 29 ++++++++++++----------------- 5 files changed, 25 insertions(+), 34 deletions(-) diff --git a/identity/src/signature.rs b/identity/src/signature.rs index 7ee125c..81db973 100644 --- a/identity/src/signature.rs +++ b/identity/src/signature.rs @@ -21,7 +21,7 @@ use thiserror::Error as ThisError; #[derive(ThisError, Debug)] pub enum SignatureError { - #[error("{0}")] + #[error(transparent)] Error(#[from] SigError), } diff --git a/src/trust.rs b/src/trust.rs index b2db75b..685689c 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -67,7 +67,7 @@ pub enum TrustError { Expired(Duration, Duration), /// Errors occured on signature verification - #[error("{0}")] + #[error(transparent)] SignatureError(#[from] ed25519_dalek::SignatureError), /// Errors occured on trust decoding from differrent formats @@ -83,7 +83,7 @@ pub enum TrustError { #[error("Cannot decode a signature from bytes: {0}")] SignatureFromBytesError(#[from] SigError), - #[error("{0}")] + #[error(transparent)] PublicKeyError(#[from] PKError), #[error( diff --git a/src/trust_graph.rs b/src/trust_graph.rs index 18c7c8f..4ce0b61 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -16,7 +16,7 @@ use crate::certificate::CertificateError::{CertificateLengthError, Unexpected}; use crate::certificate::{Certificate, CertificateError}; -use crate::public_key_hashable::PublicKeyHashable; +use crate::public_key_hashable::PublicKeyHashable as PK; use crate::revoke::Revoke; use crate::revoke::RevokeError; use crate::trust::Trust; @@ -96,11 +96,7 @@ where } /// Insert new root weight - pub fn add_root_weight( - &mut self, - pk: PublicKeyHashable, - weight: Weight, - ) -> Result<(), TrustGraphError> { + pub fn add_root_weight(&mut self, pk: PK, weight: Weight) -> Result<(), TrustGraphError> { Ok(self.storage.add_root_weight(pk, weight)?) } @@ -127,7 +123,7 @@ where let mut chain = cert.borrow().chain.iter(); let root_trust = chain.next().ok_or(EmptyChain)?; - let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into(); + let root_pk: PK = root_trust.issued_for.clone().into(); // Insert new TrustNode for this root_pk if there wasn't one if self.storage.get(&root_pk)?.is_none() { @@ -225,7 +221,7 @@ where fn bf_search_paths( &self, node: &TrustNode, - roots: HashSet<&PublicKeyHashable>, + roots: HashSet<&PK>, ) -> Result>, TrustGraphError> { // queue to collect all chains in the trust graph (each chain is a path in the trust graph) let mut chains_queue: VecDeque> = VecDeque::new(); @@ -273,7 +269,7 @@ where // - that trust must converge to one of the root weights // - there should be more than 1 trust in the chain let self_signed = last.issued_by == last.trust.issued_for; - let issued_by: &PublicKeyHashable = last.issued_by.as_ref(); + let issued_by: &PK = last.issued_by.as_ref(); let converges_to_root = roots.contains(issued_by); if self_signed && converges_to_root && cur_chain.len() > 1 { @@ -330,7 +326,7 @@ where pub fn revoke(&mut self, revoke: Revoke) -> Result<(), TrustGraphError> { Revoke::verify(&revoke)?; - let pk: PublicKeyHashable = revoke.pk.clone().into(); + let pk: PK = revoke.pk.clone().into(); Ok(self.storage.revoke(&pk, revoke)?) } diff --git a/wasm/src/service_impl.rs b/wasm/src/service_impl.rs index 054cd61..5c7cd80 100644 --- a/wasm/src/service_impl.rs +++ b/wasm/src/service_impl.rs @@ -10,13 +10,13 @@ use trust_graph::{CertificateError, TrustGraphError}; #[derive(ThisError, Debug)] pub enum ServiceError { - #[error("{0}")] + #[error(transparent)] PublicKeyDecodeError(#[from] PKError), - #[error("{0}")] + #[error(transparent)] TGError(#[from] TrustGraphError), - #[error("{0}")] + #[error(transparent)] CertError(#[from] CertificateError), - #[error("{0}")] + #[error(transparent)] DtoError(#[from] DtoConversionError), } diff --git a/wasm/src/storage_impl.rs b/wasm/src/storage_impl.rs index 5176e33..ef43234 100644 --- a/wasm/src/storage_impl.rs +++ b/wasm/src/storage_impl.rs @@ -21,7 +21,7 @@ use std::str::FromStr; use std::time::Duration; use thiserror::Error as ThisError; use trust_graph::{ - Auth, PublicKeyHashable, Revoke, Storage, StorageError, TrustGraph, TrustNode, Weight, + Auth, PublicKeyHashable as PK, Revoke, Storage, StorageError, TrustGraph, TrustNode, Weight, }; static INSTANCE: OnceCell>> = OnceCell::new(); @@ -58,13 +58,13 @@ impl SQLiteStorage { #[derive(ThisError, Debug)] pub enum SQLiteStorageError { - #[error("{0}")] + #[error(transparent)] SQLiteError(InternalSqliteError), #[error("{0}")] PublicKeyFromStr(String), - #[error("{0}")] + #[error(transparent)] EncodeError(RmpEncodeError), - #[error("{0}")] + #[error(transparent)] DecodeError(RmpDecodeError), #[error("Cannot convert weight as integer from DB")] WeightConversionDB, @@ -105,7 +105,7 @@ impl StorageError for SQLiteStorageError {} impl Storage for SQLiteStorage { type Error = SQLiteStorageError; - fn get(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { + fn get(&self, pk: &PK) -> Result, Self::Error> { let mut cursor = self .connection .prepare("SELECT trustnode FROM trustnodes WHERE public_key = ?")? @@ -131,7 +131,7 @@ impl Storage for SQLiteStorage { } } - fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error> { + fn insert(&mut self, pk: PK, node: TrustNode) -> Result<(), Self::Error> { let mut cursor = self .connection .prepare("INSERT OR REPLACE INTO trustnodes VALUES (?, ?)")? @@ -147,7 +147,7 @@ impl Storage for SQLiteStorage { Ok({}) } - fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result, Self::Error> { + fn get_root_weight(&self, pk: &PK) -> Result, Self::Error> { let mut cursor = self .connection .prepare("SELECT public_key,weight FROM roots WHERE public_key = ?")? @@ -167,11 +167,7 @@ impl Storage for SQLiteStorage { } } - fn add_root_weight( - &mut self, - pk: PublicKeyHashable, - weight: Weight, - ) -> Result<(), Self::Error> { + fn add_root_weight(&mut self, pk: PK, weight: Weight) -> Result<(), Self::Error> { log::info!("add root: {} weight: {}", pk, weight); let mut cursor = self .connection @@ -187,7 +183,7 @@ impl Storage for SQLiteStorage { Ok({}) } - fn root_keys(&self) -> Result, Self::Error> { + fn root_keys(&self) -> Result, Self::Error> { let mut cursor = self .connection .prepare("SELECT public_key,weight FROM roots")? @@ -198,8 +194,7 @@ impl Storage for SQLiteStorage { while let Some(row) = cursor.next()? { log::info!("row: {:?}", row); let pk = row[0].as_string().ok_or(PublicKeyConversion)?; - let pk: PublicKeyHashable = - PublicKeyHashable::from_str(pk).map_err(|e| PublicKeyFromStr(e.to_string()))?; + let pk: PK = PK::from_str(pk).map_err(|e| PublicKeyFromStr(e.to_string()))?; roots.push(pk) } @@ -207,7 +202,7 @@ impl Storage for SQLiteStorage { Ok(roots) } - fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error> { + fn revoke(&mut self, pk: &PK, revoke: Revoke) -> Result<(), Self::Error> { match self.get(&pk)? { Some(mut trust_node) => { trust_node.update_revoke(revoke); @@ -220,7 +215,7 @@ impl Storage for SQLiteStorage { fn update_auth( &mut self, - pk: &PublicKeyHashable, + pk: &PK, auth: Auth, issued_for: &PublicKey, cur_time: Duration, From 8a15bf7e2a622a0acec7fa04916f08321a0da487 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Mon, 15 Feb 2021 13:01:22 +0300 Subject: [PATCH 19/19] source --- identity/src/public_key.rs | 4 ++-- identity/src/signature.rs | 8 +++++-- src/certificate.rs | 8 +++---- src/revoke.rs | 2 +- src/trust.rs | 22 ++++++++++++------ src/trust_graph.rs | 26 +++++++++------------ wasm/src/dto.rs | 18 ++++++++++++--- wasm/src/service_impl.rs | 32 +++++++++++++++++++------- wasm/src/storage_impl.rs | 46 +++++++++++++++++--------------------- 9 files changed, 98 insertions(+), 68 deletions(-) diff --git a/identity/src/public_key.rs b/identity/src/public_key.rs index edac73d..72ffae3 100644 --- a/identity/src/public_key.rs +++ b/identity/src/public_key.rs @@ -24,9 +24,9 @@ use thiserror::Error as ThisError; #[derive(ThisError, Debug)] pub enum PKError { #[error("Cannot decode public key from bytes: {0}")] - FromBytesError(SignatureError), + FromBytesError(#[source] SignatureError), #[error("Cannot decode public key from base58 format: {0}")] - FromBase58Error(bs58::decode::Error), + FromBase58Error(#[source] bs58::decode::Error), } #[derive(Copy, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] diff --git a/identity/src/signature.rs b/identity/src/signature.rs index 81db973..d479f6b 100644 --- a/identity/src/signature.rs +++ b/identity/src/signature.rs @@ -21,8 +21,12 @@ use thiserror::Error as ThisError; #[derive(ThisError, Debug)] pub enum SignatureError { - #[error(transparent)] - Error(#[from] SigError), + #[error("{0}")] + Error( + #[from] + #[source] + SigError, + ), } #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] diff --git a/src/certificate.rs b/src/certificate.rs index bb24d7f..a94697b 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -46,7 +46,7 @@ pub enum CertificateError { #[error("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust")] IncorrectByteLength, #[error("Error while decoding a trust in a certificate: {0}")] - DecodeError(TrustError), + DecodeError(#[source] TrustError), #[error("Certificate is expired. Issued at {issued_at} and expired at {expires_at}")] ExpirationError { expires_at: String, @@ -55,15 +55,15 @@ pub enum CertificateError { #[error("Certificate does not contain a trusted root.")] NoTrustedRoot, #[error("Root trust did not pass verification: {0}")] - MalformedRoot(TrustError), + MalformedRoot(#[source] TrustError), #[error("There is no `issued_by` public key in a certificate")] KeyInCertificateError, #[error("The certificate must have at least 1 trust")] CertificateLengthError, #[error("Cannot convert trust number {0} from string: {1}")] - DecodeTrustError(usize, TrustError), + DecodeTrustError(usize, #[source] TrustError), #[error("Trust {0} in chain did not pass verification: {1}")] - VerificationError(usize, TrustError), + VerificationError(usize, #[source] TrustError), #[error("there cannot be paths without any nodes after adding verified certificates")] Unexpected, } diff --git a/src/revoke.rs b/src/revoke.rs index cd7d42e..b40c82f 100644 --- a/src/revoke.rs +++ b/src/revoke.rs @@ -27,7 +27,7 @@ use thiserror::Error as ThisError; #[derive(ThisError, Debug)] pub enum RevokeError { #[error("Signature is incorrect: {0}")] - IncorrectSignature(SignatureError), + IncorrectSignature(#[source] SignatureError), } /// "A document" that cancels trust created before. diff --git a/src/trust.rs b/src/trust.rs index 685689c..8d65c5f 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -67,24 +67,32 @@ pub enum TrustError { Expired(Duration, Duration), /// Errors occured on signature verification - #[error(transparent)] - SignatureError(#[from] ed25519_dalek::SignatureError), + #[error("{0}")] + SignatureError( + #[from] + #[source] + ed25519_dalek::SignatureError, + ), /// Errors occured on trust decoding from differrent formats #[error("Cannot decode the public key: {0} in the trust: {1}")] - DecodePublicKeyError(String, PKError), + DecodePublicKeyError(String, #[source] PKError), #[error("Cannot parse `{0}` field in the trust '{1}': {2}")] - ParseError(String, String, ParseIntError), + ParseError(String, String, #[source] ParseIntError), #[error("Cannot decode `{0}` from base58 format in the trust '{1}': {2}")] - Base58DecodeError(String, String, bs58::decode::Error), + Base58DecodeError(String, String, #[source] bs58::decode::Error), #[error("Cannot decode a signature from bytes: {0}")] SignatureFromBytesError(#[from] SigError), - #[error(transparent)] - PublicKeyError(#[from] PKError), + #[error("{0}")] + PublicKeyError( + #[from] + #[source] + PKError, + ), #[error( "Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {0}" diff --git a/src/trust_graph.rs b/src/trust_graph.rs index 4ce0b61..2b12a17 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -21,7 +21,7 @@ use crate::revoke::Revoke; use crate::revoke::RevokeError; use crate::trust::Trust; use crate::trust_graph::TrustGraphError::{ - CertificateCheckError, EmptyChain, InternalStorageError, NoRoot, RevokeCheckError, + CertificateCheckError, EmptyChain, InternalStorageError, NoRoot, }; use crate::trust_graph_storage::Storage; use crate::trust_node::{Auth, TrustNode}; @@ -57,9 +57,17 @@ pub enum TrustGraphError { #[error("Chain is empty")] EmptyChain, #[error("Certificate check error: {0}")] - CertificateCheckError(CertificateError), + CertificateCheckError( + #[from] + #[source] + CertificateError, + ), #[error("Error on revoking a trust: {0}")] - RevokeCheckError(RevokeError), + RevokeCheckError( + #[from] + #[source] + RevokeError, + ), } impl From for TrustGraphError { @@ -68,24 +76,12 @@ impl From for TrustGraphError { } } -impl From for TrustGraphError { - fn from(err: CertificateError) -> Self { - CertificateCheckError(err) - } -} - impl From for String { fn from(err: TrustGraphError) -> Self { format!("{}", err) } } -impl From for TrustGraphError { - fn from(err: RevokeError) -> Self { - RevokeCheckError(err) - } -} - #[allow(dead_code)] impl TrustGraph where diff --git a/wasm/src/dto.rs b/wasm/src/dto.rs index f1628c4..5e2e068 100644 --- a/wasm/src/dto.rs +++ b/wasm/src/dto.rs @@ -9,11 +9,23 @@ use thiserror::Error as ThisError; #[derive(ThisError, Debug)] pub enum DtoConversionError { #[error("Cannot convert base58 string to bytes: {0}")] - Base58Error(#[from] bs58::decode::Error), + Base58Error( + #[from] + #[source] + bs58::decode::Error, + ), #[error("Cannot convert string to PublicKey: {0}")] - PublicKeyDecodeError(#[from] PKError), + PublicKeyDecodeError( + #[from] + #[source] + PKError, + ), #[error("Cannot convert string to PublicKey: {0}")] - SignatureDecodeError(#[from] SignatureError), + SignatureDecodeError( + #[from] + #[source] + SignatureError, + ), } #[fce] diff --git a/wasm/src/service_impl.rs b/wasm/src/service_impl.rs index 5c7cd80..99842e2 100644 --- a/wasm/src/service_impl.rs +++ b/wasm/src/service_impl.rs @@ -10,14 +10,30 @@ use trust_graph::{CertificateError, TrustGraphError}; #[derive(ThisError, Debug)] pub enum ServiceError { - #[error(transparent)] - PublicKeyDecodeError(#[from] PKError), - #[error(transparent)] - TGError(#[from] TrustGraphError), - #[error(transparent)] - CertError(#[from] CertificateError), - #[error(transparent)] - DtoError(#[from] DtoConversionError), + #[error("{0}")] + PublicKeyDecodeError( + #[from] + #[source] + PKError, + ), + #[error("{0}")] + TGError( + #[from] + #[source] + TrustGraphError, + ), + #[error("{0}")] + CertError( + #[from] + #[source] + CertificateError, + ), + #[error("{0}")] + DtoError( + #[from] + #[source] + DtoConversionError, + ), } pub fn get_weight_impl(public_key: String) -> Result, ServiceError> { diff --git a/wasm/src/storage_impl.rs b/wasm/src/storage_impl.rs index ef43234..0bc22b9 100644 --- a/wasm/src/storage_impl.rs +++ b/wasm/src/storage_impl.rs @@ -3,8 +3,8 @@ // if there is an older trust - don't add received trust use crate::storage_impl::SQLiteStorageError::{ - DecodeError, EncodeError, PublcKeyNotFound, PublicKeyConversion, PublicKeyFromStr, SQLiteError, - TrustNodeConversion, WeightConversionDB, + PublcKeyNotFound, PublicKeyConversion, PublicKeyFromStr, TrustNodeConversion, + WeightConversionDB, }; use core::convert::TryFrom; use fce_sqlite_connector; @@ -58,14 +58,26 @@ impl SQLiteStorage { #[derive(ThisError, Debug)] pub enum SQLiteStorageError { - #[error(transparent)] - SQLiteError(InternalSqliteError), + #[error("{0}")] + SQLiteError( + #[from] + #[source] + InternalSqliteError, + ), #[error("{0}")] PublicKeyFromStr(String), - #[error(transparent)] - EncodeError(RmpEncodeError), - #[error(transparent)] - DecodeError(RmpDecodeError), + #[error("{0}")] + EncodeError( + #[from] + #[source] + RmpEncodeError, + ), + #[error("{0}")] + DecodeError( + #[from] + #[source] + RmpDecodeError, + ), #[error("Cannot convert weight as integer from DB")] WeightConversionDB, #[error("Cannot convert public key as binary from DB")] @@ -76,24 +88,6 @@ pub enum SQLiteStorageError { PublcKeyNotFound, } -impl From for SQLiteStorageError { - fn from(err: InternalSqliteError) -> Self { - SQLiteError(err) - } -} - -impl From for SQLiteStorageError { - fn from(err: RmpEncodeError) -> Self { - EncodeError(err) - } -} - -impl From for SQLiteStorageError { - fn from(err: RmpDecodeError) -> Self { - DecodeError(err) - } -} - impl From for String { fn from(err: SQLiteStorageError) -> Self { err.into()