diff --git a/public/images/GVA.png b/public/images/GVA.png new file mode 100644 index 0000000000000000000000000000000000000000..9c83ecda5c2e8224f9bbca13b7178d883f019ad6 Binary files /dev/null and b/public/images/GVA.png differ diff --git a/public/images/gql.png b/public/images/gql.png new file mode 100644 index 0000000000000000000000000000000000000000..a2a8627ec7d6a569b670fef1b8bde51d8792d0f0 Binary files /dev/null and b/public/images/gql.png differ diff --git a/public/images/gva-archi-general.png b/public/images/gva-archi-general.png new file mode 100644 index 0000000000000000000000000000000000000000..9598b4e1b806309ee52cf33fd053812ab6acd1b4 Binary files /dev/null and b/public/images/gva-archi-general.png differ diff --git a/public/images/gva-fonc1-draft.png b/public/images/gva-fonc1-draft.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f76823d64ef44c002d19d000e573b5667a4ddf Binary files /dev/null and b/public/images/gva-fonc1-draft.png differ diff --git a/public/visios2021/event.md b/public/visios2021/event.md new file mode 100644 index 0000000000000000000000000000000000000000..0bb6d70021966e685911a8a42d31214e64f7b4c1 --- /dev/null +++ b/public/visios2021/event.md @@ -0,0 +1 @@ +Visios 2021 \ No newline at end of file diff --git a/public/visios2021/gva1/index.html b/public/visios2021/gva1/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7296cab1f2b169a6771773ce3afceea2b7e2f590 --- /dev/null +++ b/public/visios2021/gva1/index.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> + +<head> + <title>GVA #1 (GraphQL Verification API)</title> + <meta charset="utf-8"> + <link rel="stylesheet" href="../../common.css"> + <!--<link rel="stylesheet" href="../../lib/mermaid.dark.css">--> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tonsky/FiraCode@1.206/distr/fira_code.css"> +</head> + +<body> + <textarea id="source"></textarea> + <script src="../../lib/mermaid.min.js"></script> + <script src="../../lib/remark-latest.min.js"></script> + <script> + var slideshow = remark.create({ + sourceUrl: 'slideshow.md', + highlightStyle: 'tomorrow-night', + countIncrementalSlides: false + }); + // don't let mermaid automatically load on start + mermaid.initialize({ + theme: 'dark', + startOnLoad: false, + cloneCssStyles: false + }); + + slideshow.on("afterShowSlide", s => { + const [slide] = document.getElementsByClassName("remark-visible"); + mermaid.sequenceConfig = { + diagramMarginY: 0 + }; + mermaid.init(Array.from(slide.getElementsByClassName("mermaid"))); + }); + </script> +</body> + +</html> \ No newline at end of file diff --git a/public/visios2021/gva1/slideshow.md b/public/visios2021/gva1/slideshow.md new file mode 100644 index 0000000000000000000000000000000000000000..31a360fa7334db02f95ccdfaa0c5ab704890762f --- /dev/null +++ b/public/visios2021/gva1/slideshow.md @@ -0,0 +1,417 @@ +class: dark, middle, center + +## GVA #1 (GraphQL Verification API) + + + +_6 janvier 2021_ +_Visios 2021_ +_Librelois <c@elo.tf>_ + +Suivre la présentation sur votre écran : + +`librelois.duniter.io/slides/visios2021/gva1` + +--- + +layout: true +class: dark + +.center[Duniter GVA] + +--- + +## Sommaire + +1. [GraphQL](#gql) +2. [GVA](#gva) +3. [Architecture générale](#archi-general) +4. [Bases de données clé-valeur](#kv) +5. [GVA DB](#gva-db) +6. [Architecture GVA](#gva-archi-indexer) + * [Indexer](#gva-archi-indexer) + * [Server](#gva-archi-query) + * [Query](#gva-archi-query) + * [Mutation](#gva-archi-mut) + * [Subscription](#gva-archi-sub) +7. [Arborescence GVA](#gva-tree) +8. [KV Typed](#kv-typed) + * [Schéma](#kv-schema) + * [Lecture](#kv-read) +9. [Conventions Duniter](#conventions-duniter) +10. [Conventions GVA](#conventions-gva) +11. [Exo1: idty.isMember](#exo1) + +--- + +name: gql + +## .center[GraphQL] + +.center[] + +* Un langage de requête pour API: + * Fournit une description complète et compréhensible des données de votre API. + * Donne aux clients la possibilité de demander exactement ce dont ils ont besoin et rien de plus + * Facilite l'évolution des API dans le temps. + * Permet d'obtenir plusieurs ressources en une seule requête. +-- + +* Un « schéma » défini l'ensemble des requêtes possibles, 3 types de requêtes: + * `Query`: lire des données. + * `Mutation`: modifier des données. + * `Subscription`: s'abonner à des évènements. + +--- + +name: gva + +## .center[GVA] + +.center[GVA := **G**raphql **V**erification **A**PI] + +-- + +<div class="mermaid"> +graph RL + C[[Client]] -->|Query| S + C ==>|Mutation| S + C -. Subscription .-> S + S((GVA SERVER)) -->|read| M[(Mempools)] + S ==>|write| M + S -. Subscribe .-> M + S -->|read| B[(Blockchain)] + S -. Subscribe .-> B +</div> + +-- + * `Query`: lire des données en blockchain où en mempool. + +-- + * `Mutation`: soumettre un document utilisateur + +-- + * `Subscription`: Nouveau bloc, réception d'un document en mempool. + +--- + +name: archi-general + +## .center[Architecture générale] + + + +-- + +* DU**B**P DB: Blocs + DUBP index (pour vérifier un bloc) +-- + +* DU**N**P DB: Peers et HEADs + +--- + +name: kv + +## .center[Bases de données clé-valeur] + +* Pas de table mais des collections de couples clé-valeur +-- + +* Chaque couple clé-valeur est nommé «entrée» ("entry" in english) +-- + +* Les clés sont ordonnées +-- + +* Il est possible de parcourir un intervalle de clés + +#### Exemple : Collection des Transactions émises: + +Clé: account_hash ++ block_number +Valeur: tableau de hashs + +Si je veut les Transactions émises par le compte «SIG(A)» après le bloc `#326`, je requête l'intervalle de clés suivant: + +`[ HASH(SIG(A)) ++ 327 ; HASH(SIG(A)) ++ INTMAX ]` + +--- + +name: gva-db + +## .center[GVA DB] + +Extrait non-exhaustif de la DB actuelle + +| Collection | Clé | Valeur | +|-:|-:|-:| +| blocks_with_ud: | `int` ; | `-` | +| blockchain_time: | `int` ; | `timestamp` | +| txs: | hash ; | `tx` | +| txs_by_issuer: | `script_hash ++ block_number` ; | `[hash]` | +| txs_by_recipient: | `script_hash ++ block_number` ; | `[hash]` | +| scripts_by_pubkey: | `pubkey` ; | `[script]` | +| balances: | `script` ; | `amount` | + +--- + +name: gva-archi-indexer + +## .center[Architecture GVA] + +### .center[Partie «Indexer»] + +<div class="mermaid"> +graph RL + C[DUNITER CORE] -->|apply_block| M + M((GVA MODULE)) -->|call| DW + DW([gva-indexer]) -->|write| D[(GVA DB)] +</div> + +--- + +name: gva-archi-query + +## .center[Architecture GVA] + +### .center[Partie «serveur»: Query] + +<div class="mermaid"> +graph RL + C[[Client]] -->|Query| S + S([gva]) -->|call| R + R([gva-gql]) -->|call| DR + DR([gva-dbs-reader]) -->|read| D[(DBs)] +</div> + +--- + +name: gva-archi-mut + +## .center[Architecture GVA] + +### .center[Partie «serveur»: Mutation] + +<div class="mermaid"> +graph RL + C[[Client]] -->|Mutation| S + S([gva]) -->|call| R + R([gva-gql]) -->|write| MP[(Mempools)] +</div> + +--- + +name: gva-archi-sub + +## .center[Architecture GVA] + +### .center[Partie «serveur»: Subscription] + +<div class="mermaid"> +graph RL + C[[Client]] -. Subscription .-> S + S([gva]) -->|call| R + R([gva-gql]) -. Subscribe .-> D[(DBs)] +</div> + +--- + +name: gva-tree + +## .center[Arborescence GVA] + +* 📂 `rust-libs/modules/gva` + * 📁 db + * 📁 dbs-reader + * 📁 gql + * 📁 indexer + * 📁 src + * ⚙ Cargo.toml + +--- + +name: gva-tree2 + +## .center[Arborescence GVA] + +* 📂 `rust-libs/modules/gva` + * 📂 db + * 📁 src + * ⚙ Cargo.toml + * 📂 dbs-reader + * 📁 src + * ⚙ Cargo.toml + * 📂 gql + * 📁 src + * ⚙ Cargo.toml + * 📂 indexer + * 📁 src + * ⚙ Cargo.toml + * 📁 src + * ⚙ Cargo.toml + +--- + +name: kv-typed + +## .center[KV Typed] + +.center[Couche d'accès aux bases de données.] + +Gère : + +* Typage (déclaration du schéma de la db) +* Concurrence et Transactions (au sens db) +* Souscriptions + +--- + +name: kv-schema + +## .center[KV Typed: Schéma] + +```rust +db_schema!( + Dbname, + [ + ["col1_path", Col1name, KeyType, ValueType], + ["col2_path", Col2name, KeyType, ValueType], + ... + ] +); +``` + +Extrait schéma DB GVA (`rust-libs/modules/gva/db/src/lib.rs`) : + +```rust +db_schema!( + GvaV1, + [ + ["blockchain_time", BlockchainTime, U32BE, u64], + ["txs", Txs, HashKeyV2, GvaTxDbV1], + ["gva_identities", GvaIdentities, PubKeyKeyV2, GvaIdtyDbV1], + ... + ] +); +``` + +--- + +name: kv-read + +## .center[KV Typed: Lecture (1/2)] + +Accès à une collection: + +```rust +db.col_name() +``` + +Méthodes de lecture d'une collection : + +```rust +fn contains_key(&self, k: &K) -> KvResult<bool>; +fn count(&self) -> KvResult<usize>; +fn get(&self, k: &K) -> KvResult<Option<V>>; +fn iter(&self, range: R, f: F) -> D where F:Fn(I<KvRes<(K, V)>>)->D; +fn iter_rev(&self, range: R, f: F) -> D where F: ...; +fn subscribe(&self, subscriber: Subscriber<E>) -> KvResult<()>; +``` + +Exemple, obtenir le solde d'un compte : + +```rust +gva_db.balances().get(&account_script) +``` + +--- + +name: kv-read2 + +## .center[KV Typed: Lecture (2/2)] + +Accès à une collection: + +```rust +db.col_name() +``` + +Méthodes de lecture d'une collection : + +```rust +fn contains_key(&self, k: &K) -> KvResult<bool>; +fn count(&self) -> KvResult<usize>; +fn get(&self, k: &K) -> KvResult<Option<V>>; +fn iter(&self, range: R, f: F) -> D where F:Fn(I<KvRes<(K, V)>>)->D; +fn iter_rev(&self, range: R, f: F) -> D where F: ...; +fn subscribe(&self, subscriber: Subscriber<E>) -> KvResult<()>; +``` + +Exemple, obtenir le montant du DU courant : + +```rust +bc_db.uds_reval().iter_rev(.., |it| it.values().next_res()) +``` + +--- + +name: conventions-duniter + +## .center[Conventions Duniter] + +* Testez votre code (via des tests automatisés) +* Utilisez des nom de variable et de type long et explicite + * S'il y a besoin de commnentaires pour comprendre ce que contient votre variable oü votre type, c'est que son nom n'est pas sufisamment explicite. +* Sufixez les Result par `_res` et les Option par `_opt` +* Les variables à une lettre ne sont autorisées que dans le cas suivant: + * `e`: variante Error d'un Result + * `i`: compteur d'une boucle où d'un itérateur + * `k`: clé d'une « entrée » + * `v`: valeur d'une « entrée » + * `o`: dernier pattern d'un match (signifie "other") + +--- + +name: conventions-gva + +## .center[Conventions GVA] + +* Les types de clés et de valeur doivent être définis dans `rust-libs/modules/gva/db/src/keys|values` + * Exception: si le type sert dans une DB partagée, le placer dans `rust-libs/duniter-dbs/src/keys|values` +* Les requêtes de lecture en DBs doivent : + * Se trouver dans `rust-libs/modules/gva/dbs-reader/src` + * Être des méthodes de `DbsReader` + * Être séparées dans un module par «entité» +* Les résolver doivent se trouver dans `rust-libs/modules/gva/gql/src` + * Pour les `Query`: `rust-libs/modules/gva/gql/src/queries` + * Pour les `Subscription`: `rust-libs/modules/gva/gql/src/subscriptions` +* Les «entités» retournées par les résolver doivent être dans `rust-libs/modules/gva/gql/src/entities` + +--- + +name: exo1 + +## .center[Exo1: idty.isMember] + +#### Setup + +* Cloner le dépôt duniter et suivez les instructions dans `doc/dev/setup_env_dev.md` +* Activez GVA sur un profil de dev: `./target/release/duniter -p dev wizard gva` +* Lancez votre serveur gva: `./target/release/duniter direct_start` +* Ouvrez [http://localhost:30901/gva](http://localhost:30901/gva) dans votre navigateur. + +#### Consignes + +* Récupérez la branche `gva-exo1/pubkey_is_member` +* Implémentez la méthode `DbsReader::pubkey_is_member` dans `rust-libs/modules/gva/dbs-reader/src/idty.rs` et completez le test associé +* Implémentez le résolver `idty` dans `rust-libs/modules/gva/gql/src/queries/idty.rs` et completez le test associé + +--- + +## .center[Merci de votre attention] + +Présentation réalisée avec [remark](https://github.com/gnab/remark). +Graphes réalisés avec [mermaid](https://github.com/knsv/mermaid). + +Retrouvez les sources de cette présentation sur le gitlab de duniter : + +.center[[https://git.duniter.org/librelois/slides](https://git.duniter.org/librelois/slides)]