The problem of access control and permissions is solved with centralized CAs (Certificate Authority) in web 2.0. However, such problem is urgent and becomes even more challenging considering a decentralized nature of web 3.0. TrustGraph is our point of view on the solution for this challenge.
TrustGraph is a bottom layer of trust for open p2p networks: every peer may be provided with SSL-like certificates that promoted over the network. Service providers and peers can treat certificate holders differently based on their certificate set.
TrustGraph is a basic component that allows storing and managing certificates without additional logic about how to decide whom to trust and whom to treat as unreliable.
The problem of peer choice and prioritization is very urgent in p2p networks. We can't use the network reliably and predictably without trust to any network participant. We also should mark and avoid malicious peers. In addition we need to control our application access and permissions in runtime, so it performs continuously without interruptions and redeployments.
TrustGraph is basically a directed graph with one root at least, vertices are peer ids, and edges are one of the two types of cryptographic relations: trust and revocation.
**Root** is a peer id that we unconditionally trust until it is removed, and is defined by the node owner. Every root has characteristics that represent the maximum length for a chain of trusts.
**Trust** is a cryptographic relation representing that peer A trusts peer B until this trust expires or is revoked. Trust relation is transitive. If peer A trusts peer B, and peer B trusts peer C, it results in peer A trusts peer C transitively. Trust relation means that you trust to connect, compute or store based on your business logic and chosen metrics. For example, if you want to perform some computation and some well-known peers do that, and are trusted by others you trust, so you can safely use them for computing but not to store sensitive information (personal keys, etc).
**Certificate** is a chain of trusts started with a self-signed root trust. Considering Trust and Certificate data structures, it is possible to track the chain of trust relations: the `issued_for` field of the first trust in a chain indicates a root peer id, second — whom root trusts, etc. So if we have a chain `R->A->B->C` in the certificate it looks like a chain of the following trusts: `R->R`, `R->A`, `A->B`, `B->C`. A certificate is tamperproof since it is a composition of signed trusts.
So peerA is trusted by peerB if there is a path between them in the instance of TrustGraph. The selection of certificates is subjective and defined by a node owner by choice of roots and maximum chain lengths. For now, there are no default metrics for a general case.
**Revocation** is a cryptographic relation representing that a peer A considers a peer C malicious or unreliable. For example, all chains containing paths from A to C will not be treated as valid. So if A trusts a peer B, and B trusts C, a peer A has no trust to C transitively, it would have otherwise.
Every peer has a **weight**. A weight signifies a power of 2 or zero. If there is no path from any root to a peer, given revocations, its weight equals zero. The closer to the root, the bigger the weight. Weights are also subjective and relevant in the scope of a local TrustGraph.
Trust is transitive in terms of cryptographic relations. On the other hand, a subset of trusts and certificates is subjective for each network participant because of the choice of roots.
- if you want to issue revocation not by `INIT_PEER_ID` check the Sig service [docs](https://doc.fluence.dev/docs/fluence-js/3_in_depth#signing-service)
6. By default, trusts/revocations signed with the client's private key. To sign with different keys see the Sig service [documentation](https://doc.fluence.dev/docs/fluence-js/3_in_depth#signing-service).
You can specify in runtime who can access service functionality based on the local TrustGraph (certificates, weights). It's possible to check where the proof comes from based on [tetraplets](https://doc.fluence.dev/docs/knowledge_security). For example, only peers that have a non-zero weight can execute a service function `trusted_call(weight: WeightResult) -> u8`.
- Inside your service you need to check tetraplets like [this](https://github.com/fluencelabs/registry/blob/main/service/src/misc.rs#L37) to be sure that they are resulted from the local TrustGraph
- How we can interpret a certificate and/or a peer weight?
- A certificate contains a path from the root to the target peer we are looking for. A weight represents the presence of these certificates and peers' closeness to the root.
- Weights are calculated based on the existence of a chain of trusts from the roots. For example, if we have a root with a maximum chain length equal 4 and have a chain `R -> A -> B -> C`, so the corresponding weights of peers are `8`, `4`, `2`, `1`. Weights are the same if there are no changes in the paths.
As long as we have no metrics, all trust/revocation logic is a TrustGraph user's responsibility.
- All peers are untrusted by default. Trust is unmeasured, weight represents how far the peer is from the root, the bigger weight, the closer to the root, so if you want to increase the weight of the target peer, you should obtain the trust from the root or peers who are closer to the root than this peer.
- Weights calculated **locally** based on certificates that contain immutable signed trusts. Weights are subjective and have meaning only locally to this exact peer.
High-level API is defined in the [trust-graph-api.aqua](./aqua/trust-graph-api.aqua) module. API Reference soon will be available in the documentation.