From fc635c0ef54e0a2492e7ae0084d9685f2ade348b Mon Sep 17 00:00:00 2001 From: Alexey Proshutinskiy Date: Thu, 23 Sep 2021 19:00:24 +0300 Subject: [PATCH] return only valid trusts, couple renamings --- aqua/trust-graph-api.aqua | 24 ++++++-- aqua/trust-graph.aqua | 8 +-- example/aqua/export.aqua | 4 +- example/index.ts | 5 +- service/src/results.rs | 8 +-- service/src/service_api.rs | 24 ++++---- service/src/service_impl.rs | 14 ++--- src/trust_graph.rs | 112 ++++++++++++++++++++++++++++-------- 8 files changed, 137 insertions(+), 62 deletions(-) diff --git a/aqua/trust-graph-api.aqua b/aqua/trust-graph-api.aqua index c92eaeb..b25bc6f 100644 --- a/aqua/trust-graph-api.aqua +++ b/aqua/trust-graph-api.aqua @@ -1,14 +1,14 @@ import "trust-graph.aqua" import "@fluencelabs/aqua-lib/builtin.aqua" -func get_trust_metadata(node: string, issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64) -> GetTrustMetadataResult: +func get_trust_bytes(node: string, issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64) -> GetTrustBytesResult: on node: - result <- TrustGraph.get_trust_metadata(issued_for_peer_id, expires_at_sec, issued_at_sec) + result <- TrustGraph.get_trust_bytes(issued_for_peer_id, expires_at_sec, issued_at_sec) <- result -func issue_trust(node: string, issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64, signed_metadata: []u8) -> IssueTrustResult: +func issue_trust(node: string, issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64, trust_bytes: []u8) -> IssueTrustResult: on node: - result <- TrustGraph.issue_trust(issued_for_peer_id, expires_at_sec, issued_at_sec, signed_metadata) + result <- TrustGraph.issue_trust(issued_for_peer_id, expires_at_sec, issued_at_sec, trust_bytes) <- result func verify_trust(node: string, trust: Trust, issuer_peer_id: string) -> VerifyTrustResult: @@ -23,9 +23,9 @@ func add_trust(node: string, trust: Trust, issuer_peer_id: string) -> AddTrustRe result <- TrustGraph.add_trust(trust, issuer_peer_id, timestamp_sec) <- result -func add_root(node: string, peer_id: string, weight: u32) -> AddRootResult: +func add_root(node: string, peer_id: string, weight_factor: u32) -> AddRootResult: on node: - result <- TrustGraph.add_root(peer_id, weight) + result <- TrustGraph.add_root(peer_id, weight_factor) <- result func get_weight(node: string, peer_id: string) -> WeightResult: @@ -33,3 +33,15 @@ func get_weight(node: string, peer_id: string) -> WeightResult: timestamp_sec <- Peer.timestamp_sec() result <- TrustGraph.get_weight(peer_id, timestamp_sec) <- result + +func get_all_certs(node: string, issued_for: string) -> AllCertsResult: + on node: + timestamp_sec <- Peer.timestamp_sec() + result <- TrustGraph.get_all_certs(issued_for, timestamp_sec) + <- result + +func insert_cert(node: string, certificate: Certificate) -> InsertResult: + on node: + timestamp_sec <- Peer.timestamp_sec() + result <- TrustGraph.insert_cert(certificate, timestamp_sec) + <- result diff --git a/aqua/trust-graph.aqua b/aqua/trust-graph.aqua index ea51774..9f9c371 100644 --- a/aqua/trust-graph.aqua +++ b/aqua/trust-graph.aqua @@ -24,7 +24,7 @@ data AllCertsResult: certificates: []Certificate error: string -data GetTrustMetadataResult: +data GetTrustBytesResult: success: bool error: string result: []u8 @@ -49,12 +49,12 @@ data WeightResult: error: string service TrustGraph("trust-graph"): - add_root(peer_id: string, weight: u32) -> AddRootResult + add_root(peer_id: string, weight_factor: u32) -> AddRootResult add_trust(trust: Trust, issuer_peer_id: string, timestamp_sec: u64) -> AddTrustResult get_all_certs(issued_for: string, timestamp_sec: u64) -> AllCertsResult - get_trust_metadata(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64) -> GetTrustMetadataResult + get_trust_bytes(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64) -> GetTrustBytesResult get_weight(peer_id: string, timestamp_sec: u64) -> WeightResult insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult insert_cert_raw(certificate: string, timestamp_sec: u64) -> InsertResult - issue_trust(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64, signed_metadata: []u8) -> IssueTrustResult + issue_trust(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64, trust_bytes: []u8) -> IssueTrustResult verify_trust(trust: Trust, issuer_peer_id: string, timestamp_sec: u64) -> VerifyTrustResult diff --git a/example/aqua/export.aqua b/example/aqua/export.aqua index 8a4969f..d933cf6 100644 --- a/example/aqua/export.aqua +++ b/example/aqua/export.aqua @@ -1,3 +1,3 @@ -import get_trust_metadata, issue_trust, verify_trust, add_trust, add_root, get_weight from "../../aqua/trust-graph-api.aqua" +import get_trust_bytes, issue_trust, verify_trust, add_trust, add_root, get_weight, get_all_certs, insert_cert from "../../aqua/trust-graph-api.aqua" -export get_trust_metadata, issue_trust, verify_trust, add_trust, add_root, get_weight +export get_trust_bytes, issue_trust, verify_trust, add_trust, add_root, get_weight, get_all_certs, insert_cert diff --git a/example/index.ts b/example/index.ts index a780238..673aa7f 100644 --- a/example/index.ts +++ b/example/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { get_trust_metadata, issue_trust, verify_trust, add_trust, add_root, get_weight } from "./generated/export"; +import { get_trust_bytes, issue_trust, verify_trust, add_trust, add_root, get_weight, } from "./generated/export"; import { Fluence, KeyPair } from "@fluencelabs/fluence"; import { Node } from "@fluencelabs/fluence-network-environment"; const bs58 = require('bs58'); @@ -47,7 +47,7 @@ async function main(environment: Node[]) { let add_root_result = await add_root(local[0].peerId, local[0].peerId, 2); console.log("Add root weight result: %s", add_root_result); - let trust_metadata = await get_trust_metadata(local[0].peerId, local[0].peerId, 99999999999, 0); + let trust_metadata = await get_trust_bytes(local[0].peerId, local[0].peerId, 99999999999, 0); const signed_metadata = await issuer_kp.Libp2pPeerId.privKey.sign(Uint8Array.from(trust_metadata.result)); let root_trust = await issue_trust(local[0].peerId, local[0].peerId, 99999999999, 0, Array.from(signed_metadata)); @@ -62,6 +62,7 @@ async function main(environment: Node[]) { let root_weight_result = await get_weight(local[0].peerId, local[0].peerId); console.log("Root weight: %s", root_weight_result); + // TODO: insert trust to local[1].peerId, get this certs, add local[1].peerId as root in local[1].peerId and insert_certificate return; } diff --git a/service/src/results.rs b/service/src/results.rs index 8af7010..3347c80 100644 --- a/service/src/results.rs +++ b/service/src/results.rs @@ -96,21 +96,21 @@ impl From> for AddRootResult { } #[marine] -pub struct GetTrustMetadataResult { +pub struct GetTrustBytesResult { pub success: bool, pub error: String, pub result: Vec, } -impl From, ServiceError>> for GetTrustMetadataResult { +impl From, ServiceError>> for GetTrustBytesResult { fn from(result: Result, ServiceError>) -> Self { match result { - Ok(res) => GetTrustMetadataResult { + Ok(res) => GetTrustBytesResult { success: true, error: "".to_string(), result: res, }, - Err(e) => GetTrustMetadataResult { + Err(e) => GetTrustBytesResult { success: false, error: format!("{}", e), result: vec![], diff --git a/service/src/service_api.rs b/service/src/service_api.rs index 4caf4cd..02b7090 100644 --- a/service/src/service_api.rs +++ b/service/src/service_api.rs @@ -1,10 +1,10 @@ use crate::dto::{Certificate, Trust}; use crate::results::{ - AddRootResult, AddTrustResult, AllCertsResult, GetTrustMetadataResult, InsertResult, + AddRootResult, AddTrustResult, AllCertsResult, GetTrustBytesResult, InsertResult, IssueTrustResult, VerifyTrustResult, WeightResult, }; use crate::service_impl::{ - add_root_impl, add_trust_impl, get_all_certs_impl, get_trust_metadata_imp, get_weight_impl, + add_root_impl, add_trust_impl, get_all_certs_impl, get_trust_bytes_imp, get_weight_impl, insert_cert_impl, insert_cert_impl_raw, issue_trust_impl, verify_trust_impl, }; use marine_rs_sdk::{marine, CallParameters}; @@ -23,7 +23,6 @@ fn insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult { insert_cert_impl(certificate, timestamp_sec).into() } -// TODO: return only valid, delete expired, return max weight #[marine] fn get_weight(peer_id: String, timestamp_sec: u64) -> WeightResult { get_weight_impl(peer_id.clone(), timestamp_sec) @@ -31,20 +30,19 @@ fn get_weight(peer_id: String, timestamp_sec: u64) -> WeightResult { .into() } -// TODO: return only valid, delete expired +// TODO: delete expired #[marine] fn get_all_certs(issued_for: String, timestamp_sec: u64) -> AllCertsResult { get_all_certs_impl(issued_for, timestamp_sec).into() } #[marine] -/// could add only a host of a trust graph service -// TODO: rename to add_root_weight_factor -fn add_root(peer_id: String, weight: u32) -> AddRootResult { +/// could add only a owner of a trust graph service +fn add_root(peer_id: String, weight_factor: u32) -> AddRootResult { let call_parameters: CallParameters = marine_rs_sdk::get_call_parameters(); let init_peer_id = call_parameters.init_peer_id.clone(); if call_parameters.service_creator_peer_id == init_peer_id { - add_root_impl(peer_id, weight).into() + add_root_impl(peer_id, weight_factor).into() } else { return AddRootResult { success: false, @@ -54,12 +52,12 @@ fn add_root(peer_id: String, weight: u32) -> AddRootResult { } #[marine] -fn get_trust_metadata( +fn get_trust_bytes( issued_for_peer_id: String, expires_at_sec: u64, issued_at_sec: u64, -) -> GetTrustMetadataResult { - get_trust_metadata_imp(issued_for_peer_id, expires_at_sec, issued_at_sec).into() +) -> GetTrustBytesResult { + get_trust_bytes_imp(issued_for_peer_id, expires_at_sec, issued_at_sec).into() } #[marine] @@ -67,13 +65,13 @@ fn issue_trust( issued_for_peer_id: String, expires_at_sec: u64, issued_at_sec: u64, - signed_metadata: Vec, + trust_bytes: Vec, ) -> IssueTrustResult { issue_trust_impl( issued_for_peer_id, expires_at_sec, issued_at_sec, - signed_metadata, + trust_bytes, ) .into() } diff --git a/service/src/service_impl.rs b/service/src/service_impl.rs index adc6c60..8994f47 100644 --- a/service/src/service_impl.rs +++ b/service/src/service_impl.rs @@ -82,11 +82,11 @@ fn extract_public_key(peer_id: String) -> Result { .map_err(|e| ServiceError::PublicKeyExtractionError(e.to_string())) } -pub fn get_weight_impl(peer_id: String, _timestamp_sec: u64) -> Result { +pub fn get_weight_impl(peer_id: String, timestamp_sec: u64) -> Result { check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; let tg = get_data().lock(); let public_key = extract_public_key(peer_id)?; - let weight = tg.weight(public_key)?; + let weight = tg.weight(public_key, Duration::from_secs(timestamp_sec))?; Ok(weight) } @@ -106,13 +106,13 @@ pub fn insert_cert_impl_raw(certificate: String, timestamp_sec: u64) -> Result<( pub fn get_all_certs_impl( issued_for: String, - _timestamp_sec: u64, + timestamp_sec: u64, ) -> Result, ServiceError> { check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; let tg = get_data().lock(); let public_key = extract_public_key(issued_for)?; - let certs = tg.get_all_certs(public_key)?; + let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?; Ok(certs.into_iter().map(|c| c.into()).collect()) } @@ -130,7 +130,7 @@ pub fn add_root_impl(peer_id: String, weight: u32) -> Result<(), ServiceError> { Ok(()) } -pub fn get_trust_metadata_imp( +pub fn get_trust_bytes_imp( peer_id: String, expires_at_sec: u64, issued_at_sec: u64, @@ -147,12 +147,12 @@ pub fn issue_trust_impl( peer_id: String, expires_at_sec: u64, issued_at_sec: u64, - signed_metadata: Vec, + trust_bytes: Vec, ) -> Result { let public_key = extract_public_key(peer_id)?; let expires_at_sec = Duration::from_secs(expires_at_sec); let issued_at_sec = Duration::from_secs(issued_at_sec); - let signature = Signature::from_bytes_with_public_key(&public_key, signed_metadata); + let signature = Signature::from_bytes_with_public_key(&public_key, trust_bytes); Ok(Trust::from(trust_graph::Trust::new( public_key, expires_at_sec, diff --git a/src/trust_graph.rs b/src/trust_graph.rs index 4863932..9ab5f1c 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -131,7 +131,7 @@ where { Trust::verify(trust.borrow(), issued_by.borrow(), cur_time)?; - let issued_by_weight = self.weight(issued_by.borrow().clone().borrow())?; + let issued_by_weight = self.weight(issued_by.borrow().clone().borrow(), cur_time)?; if issued_by_weight == 0u32 { return Ok(0u32); @@ -188,7 +188,7 @@ where } /// Get the maximum weight of trust for one public key. - pub fn weight

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

(&self, pk: P, cur_time: Duration) -> Result where P: Borrow, { @@ -197,7 +197,7 @@ where } // get all possible certificates from the given public key to all roots in the graph - let certs = self.get_all_certs(pk)?; + let certs = self.get_all_certs(pk, cur_time)?; self.certificates_weight_factor(certs) .map(|wf| wf.map(get_weight_from_factor).unwrap_or(0u32)) } @@ -251,11 +251,16 @@ where &self, node: &TrustNode, roots: HashSet<&PK>, + cur_time: Duration, ) -> 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(); - let node_auths: Vec = node.authorizations().cloned().collect(); + let node_auths: Vec = node + .authorizations() + .cloned() + .filter(|auth| auth.trust.expires_at > cur_time) + .collect(); // put all auth in the queue as the first possible paths through the graph for auth in node_auths { chains_queue.push_back(vec![auth]); @@ -279,6 +284,7 @@ where .ok_or(CertificateCheckError(Unexpected))? .authorizations() .cloned() + .filter(|auth| auth.trust.expires_at > cur_time) .collect(); for auth in auths { @@ -311,7 +317,11 @@ where /// 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) -> Result, TrustGraphError> + pub fn get_all_certs

( + &self, + issued_for: P, + cur_time: Duration, + ) -> Result, TrustGraphError> where P: Borrow, { @@ -323,7 +333,7 @@ where match issued_for_node { Some(node) => Ok(self - .bf_search_paths(&node, roots)? + .bf_search_paths(&node, roots, cur_time)? .iter() .map(|auths| { // TODO: can avoid cloning here by returning &Certificate @@ -528,13 +538,13 @@ mod tests { graph.add(cert1, current_time()).unwrap(); let root_weight = get_weight_from_factor(1); - let w1 = graph.weight(key_pairs[0].public()).unwrap(); + let w1 = graph.weight(key_pairs[0].public(), current_time()).unwrap(); assert_eq!(w1, root_weight * 2u32.pow(0)); - let w2 = graph.weight(key_pairs[1].public()).unwrap(); + let w2 = graph.weight(key_pairs[1].public(), current_time()).unwrap(); assert_eq!(w2, root_weight / 2u32.pow(1)); - let w3 = graph.weight(key_pairs[9].public()).unwrap(); + let w3 = graph.weight(key_pairs[9].public(), current_time()).unwrap(); assert_eq!(w3, root_weight / 2u32.pow(9)); let node = graph.get(key_pairs[9].public()).unwrap().unwrap(); @@ -590,12 +600,12 @@ mod tests { ); graph.revoke(revoke2).unwrap(); - let w1 = graph.weight(key_pair1.public()).unwrap(); + let w1 = graph.weight(key_pair1.public(), current_time()).unwrap(); // all upper trusts are revoked for this public key - let w2 = graph.weight(key_pair2.public()).unwrap(); - let w3 = graph.weight(key_pair3.public()).unwrap(); - let w_last1 = graph.weight(last_pk1).unwrap(); - let w_last2 = graph.weight(last_pk2).unwrap(); + let w2 = graph.weight(key_pair2.public(), current_time()).unwrap(); + let w3 = graph.weight(key_pair3.public(), current_time()).unwrap(); + let w_last1 = graph.weight(last_pk1, current_time()).unwrap(); + let w_last2 = graph.weight(last_pk2, current_time()).unwrap(); assert_eq!(w1, get_weight_from_factor(4)); assert_eq!(w2, 0); // revoked @@ -618,7 +628,7 @@ mod tests { graph.add(cert.clone(), current_time()).unwrap(); let certs = graph - .get_all_certs(key_pairs.last().unwrap().public()) + .get_all_certs(key_pairs.last().unwrap().public(), current_time()) .unwrap(); assert_eq!(certs.len(), 1); @@ -645,7 +655,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).unwrap(); + let certs = graph.get_all_certs(t.issued_for, current_time()).unwrap(); assert_eq!(certs.len(), 1); } @@ -696,17 +706,23 @@ mod tests { graph.add(cert2, current_time()).unwrap(); graph.add(cert3, current_time()).unwrap(); - let certs1 = graph.get_all_certs(key_pair1.public()).unwrap(); + let certs1 = graph + .get_all_certs(key_pair1.public(), current_time()) + .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()).unwrap(); + let certs2 = graph + .get_all_certs(key_pair2.public(), current_time()) + .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()).unwrap(); + let certs3 = graph + .get_all_certs(key_pair3.public(), current_time()) + .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); @@ -737,11 +753,16 @@ mod tests { let weight = graph .add_trust(trust.clone(), issued_by.public(), cur_time) .unwrap(); - assert_eq!(weight, graph.weight(issued_by.public()).unwrap() / 2); + assert_eq!( + weight, + graph.weight(issued_by.public(), current_time()).unwrap() / 2 + ); cert.chain.push(trust); - let certs = graph.get_all_certs(trust_kp.public()).unwrap(); + let certs = graph + .get_all_certs(trust_kp.public(), current_time()) + .unwrap(); assert_eq!(certs.len(), 1); assert_eq!(certs[0], cert); } @@ -771,13 +792,18 @@ mod tests { let weight = graph .add_trust(trust.clone(), issued_by.public(), cur_time) .unwrap(); - assert_eq!(weight, graph.weight(issued_by.public()).unwrap() / 2); + assert_eq!( + weight, + graph.weight(issued_by.public(), current_time()).unwrap() / 2 + ); let target_cert = Certificate { chain: vec![cert.chain[0].clone(), trust], }; - let certs = graph.get_all_certs(trust_kp.public()).unwrap(); + let certs = graph + .get_all_certs(trust_kp.public(), current_time()) + .unwrap(); assert_eq!(certs.len(), 1); assert_eq!(certs[0], target_cert); } @@ -804,6 +830,44 @@ mod tests { ); graph.revoke(revoke.clone()).unwrap(); - assert_eq!(0, graph.weight(revoked.public()).unwrap()); + assert_eq!(0, graph.weight(revoked.public(), current_time()).unwrap()); + } + + #[test] + fn test_expired_trust() { + let (key_pairs, mut cert) = generate_cert_with_len(5, HashMap::new()).unwrap(); + let cur_time = current_time(); + + let st = InMemoryStorage::new(); + let mut graph = TrustGraph::new(st); + let root1_pk = key_pairs[0].public(); + graph + .add_root_weight_factor(root1_pk.clone().into(), 2) + .unwrap(); + graph.add(cert.clone(), cur_time).unwrap(); + + let issued_by = key_pairs.last().unwrap(); + let trust_kp = KeyPair::generate_ed25519(); + let expired_time = cur_time.checked_add(one_minute()).unwrap(); + let trust = Trust::create(issued_by, trust_kp.public(), expired_time, cur_time); + + let weight = graph + .add_trust(trust.clone(), issued_by.public(), cur_time) + .unwrap(); + assert_eq!( + weight, + graph.weight(issued_by.public(), cur_time).unwrap() / 2 + ); + + cert.chain.push(trust); + + let certs = graph.get_all_certs(trust_kp.public(), cur_time).unwrap(); + assert_eq!(certs.len(), 1); + assert_eq!(certs[0], cert); + + let certs = graph + .get_all_certs(trust_kp.public(), expired_time) + .unwrap(); + assert_eq!(certs.len(), 0); } }