ĞDev indexer

@HugoTrentesaux ça te dit une d’organiser une petit atelier Subsquid en partage d’écran sur jitsi, qu’on regarde ça ensemble pour ceux que ça intéresse ?

Au niveau de l’indexer v2s, est-ce qu’il ne serait pas possible de récupérer directement le schéma de tous les événements via un call avec tous leurs arguments ? Parce-que c’est assez fastidieux de reproduire chaque événement avec des tests pour les décortiquer dans les logs, puis d’appliquer la bonne requête correspondante.

2 Likes

Un peu de vulgarisation sur ces indexeurs m’intéresserait.

3 Likes

Merci @ManUtopiK ,
Ca fait toujours plaisir de savoir que ce que j’ai fait est utile :smiley:

Le dernier fichier où il reste des erreur est GraphiQL.vue. Il y a des erreurs principalement sur l’objet window et je me demande comment les traiter, manquant de compétence en Vue.js (il me semble que pour injecter des paramètres, il est préférable d’utiliser l’objet window.global ?!)

Pour l’erreur dans ma branche, ça y’est, c’est corrigé. Merci beaucoup du tuyau.
@poka ==> peut être que ça résout ton problème ?!?

Pour gitlab, je suis preneur de conseil pour savoir comment mettre à jour ma branche avec les commit d’autres branches. Apparement, ça devrait arriver dans une prochaine version

Merci @HugoTrentesaux pour tes encouragements,

Grâce à @ManUtopiK et @poka , j’ai pu bien comprendre comment fonctionne l’indexeur et je me suis donc permis d’améliorer la documentation pour les prochains qui passeraient par là :smiley:

Je vais essayer de comprendre comment fonctionne les événements…
Et effectivement, une visio serait la bienvenue, quand tu pourras.
Enfin, je suis également partant pour en apprendre plus sur Subsquid :wink:

2 Likes

Oui effectivement, c’est difficile d’assurer une synchro parfaite de plusieurs sources.

En fait on a les informations de la blockchain sous des formes plus ou moins complètes :

  • Nœud sans archive : événements bruts éparpillés dans les blocs, 1 état minimum dans le dernier bloc (ex: derniers soldes).
  • Nœud archive : événements bruts éparpillés dans les blocs, tous les états dans chaque bloc (ex : historique des soldes).
  • Subsquid : liste des événements. Pas d’états visiblement.
  • Indexer V2S : les événements et états nécessaires aux clients selon nos besoins.

Ce qui m’intrigue encore c’est qu’un nœud archive contenant tous les états peut se construire à partir d’un nœud sans archive. C’est donc une indexation des états.

Il serait donc possible pour un indexer maison de retrouver les mêmes infos depuis un nœud sans archive ?
Gdev indexer a-t-il besoin d’un nœud archive ?

2 Likes

J’ai essayé d’ajouter l’événement identity.IdtyRemoved, sans succès.
Je reçois correctement l’événément dans Polkadot.js mais quand j’essaie de le capter dans l’indexer, ce dernier passe à côté…

Pensant que c’était moi qui m’y prenait incorrectement, j’ai donc tenté de capter un événément “transaction” déjà présent dans l’app. Et même phénomène, l’événement apparaît dans Polkadot.js mais l’app ignore complètement l’événément (et donc il est absent de la base de données).

C’est sûrement un petit détail qui m’échappe… pourtant, je suis tout proche de la solution.
Si une âme charitable venait à passer par là :wink:

C’est super que tu commences à prendre tes marques sur cet environnement ! :slight_smile:

@flodef on peut se refaire une session de peer programming (ou extrem programming comme tu dis aha) demain aprem vers 14h ou 15h si tu veux, sur ton écran cette fois ci pour voir ce que tu as commencé à faire ? Ou tu préfères Samedi ?

1 Like

Ouuuuuuuuuuuui, je suis super partant pour Samedi 14h !!

En fait, le “pair” (peer, c’est la poire :wink: ) programming, c’est une seule des particularité de l’eXtreme Programming. Il y en a plusieurs autres comme les méthodes de tests, les feedbacks, les itérations courtes…
De ce que ce vois, j’ai l’impression que l’équipe dev fonctionne déjà un peu comme ça :smiley:
Sinon, pour celles et ceux qui veulent découvrir, je vous recommande le lien wikipédia qui explique tout ça

1 Like

Subsquid est un framework pour développer un indexeur. Pour l’instant il n’y a que les états dans le mien, car je n’ai rien implémenté, juste pris ce qui était disponible de manière générique pour substrate.

Ce que l’'indexeur fournit, plus que la donnée elle-même (tout est en blockchain), c’est une manière pratique d’y accéder en fonction de nos besoins. Par exemple, pour avoir la liste des transactions d’un compte, il faut parcourir tous les blocs, regarder les événements transactions, et regarder s’ils concernent ce compte. Pour avoir l’historique des soldes d’un compte, il faut parcourir tous les blocs et regarder la valeur du chain state pour ce compte.

Par rapport à l’idée d’un indexeur maison qui retrouve les mêmes infos, le problème est qu’il doit prendre tout en compte parce que d’autres choses que les transactions peuvent faire varier le solde d’un compte : réclamation des DU, frais d’extrinsics (y compris hors transaction), votes de trésorerie, offences… Donc quitte à implémenter les transformations d’états à partir des blocs (transitions d’états), autant prendre le logiciel qui le fait, à savoir Duniter !! Donc un indexeur se branche généralement à un nœud d’archive local pour accéder rapidement à la donnée dont il a besoin.

3 Likes

@poka, J’y suis :smiley:

1 Like

Une curiosité que j’arrive pas à expliquer depuis le début sur cet indexer: Il m’est impossible de récupérer plus de 100 items par requête sur l’API relay, même de manière paginé.

C’est à dire que l’API renvoi hasNextPage false une fois qu’on atteint 100 item au total depuis le début, même avec des pages de 20 items par exemple.

Curieusement, au travers le console hasura directement, je n’ai pas le même comportement, j’arrive bien à récupérer tous les items jusqu’au dernier, que ce soit de manière paginé ou non d’ailleurs.

Exemple:

query  {
  transaction_connection(order_by: {created_at: desc}, first: 20, after: "eyJjcmVhdGVkX2F0IiA6ICIyMDIzLTAzLTA5VDE2OjA1OjEyLjAwMSswMDowMCIsICJpZCIgOiAyNDM5ODJ9") {
    pageInfo {
      endCursor
      hasNextPage
    }
    edges {
      node {
        issuer_pubkey
        receiver_pubkey
        created_at
        issuer {
          identity {
            name
          }
        }
        receiver {
          identity {
            name
          }
        }
        amount
      }
    }
  }
}

(avec ce curseur: eyJjcmVhdGVkX2F0IiA6ICIyMDIzLTAzLTA5VDE2OjA1OjEyLjAwMSswMDowMCIsICJpZCIgOiAyNDM5, et pensez à bien cocher “API relay”)

Via graphiql, on obtient qu’un seul élément, quelque soit ce qu’on met en first., et le bool hasNextPage à false. Même comportement sur Gecko web.

Mais si vous essayez sur la console hasura de la même instance (mot de passe: your_secret), vous aurez bien l’ensemble de la page et hasNextPage à true, car vous êtes admin.

Ca correspond donc aux limitation inscrites côté hasura sur la table transaction:

https://gdev-indexer.p2p.legal/console/data/default/schema/public/tables/transaction/permissions

Mais cette limitation ne devrait pas s’appliquer lorsqu’on pagine la requête :face_with_raised_eyebrow:
Un bug ou une limitation de l’API relay beta ?

1 Like

https://gdev-indexer-graphiql.p2p.legal/ est injoignable au moment où j’écris.

igraphql était mal configuré (url en localhost interdisant d’obtenir la complétion et l’aide du schéma) quand je m’y intéressais. C’est peut-être toujours le cas et ce problème aurait sa cause dans une erreur de config aussi. Je dis ça pour aider… mais j’en sais rien hein :wink:

En effet je ne sais pas pk le container indexer était coupé, je viens de le redémarré. Le soucis de localhost a été reglé.

Si vous avez l’erreur field 'transaction_connection' not found in type: 'query_root' lors de l’execution de la requête proposé, pensez à activer le switch API relay.


Le problème que je soulève se traduit par la limitation aux 100 premiers éléments en scrollant dans les encarts présents en page d’accueil de gecko web (videz votre cache), ainsi que dans l’historique des transactions de chaque adresse, sur web ou mobile.

Pour moi ce comportement est anormal, j’ai donc ouvert une issue, car je ne trouve aucune information à ce sujet.

1 Like

J’ai mis à jour mon indexeur

# first remove volumes because genesis indexing changed)
docker compose -f indexer.yml down -v
# update the image
docker compose -f indexer.yml pull
# start in demon mode
docker compose -f indexer.yml up -d
# follow the logs
docker compose -f indexer.yml logs -f
  • ajoute les certifications forgeron
  • modifie le hash du genesis

Vous pouvez maintenant essayer la requête :

query Smith {
  smith {
    idty_index
  }
}

Note : pas disponible dans le playground https://indexer.gdev.coinduf.eu/, ça doit être un problème de schéma, à mettre à jour

Par contre, l’indexation du genesis ne semble pas encore terminée (c’est si long ??). Avec gcli (cf Ğcli a command line tool for Duniter v2 - #29 by HugoTrentesaux) :

$ gcli indexer check
wss://gdev.p2p.legal:443/ws and https://hasura.gdev.coinduf.eu/v1/graphql have the same genesis hash: 0xf9bb…0dfc
$ gcli indexer latest-block
latest block indexed by https://hasura.gdev.coinduf.eu/v1/graphql is: 0

Gcli arrive bien à contacter mon indexeur, qui lui répond qu’il a le même genesis hash que le noeud Duniter de @poka et dit qu’il est toujours en train d’indexer le bloc 0.

[edit] ça y est, il a fini le genesis !

gcli indexer latest-block
latest block indexed by https://hasura.gdev.coinduf.eu/v1/graphql is: 68298

(par contre, toujours pas de smith, il va falloir que je débugge ça)

J’ai débuggé, c’était encore un problème de format entre le genesis de dev et de prod : Duniter était trop permissif sur le format, et l’indexeur ne savait pas au quel se fier. Donc pour la suite il faudra vraiment se caler sur le format du genesis gtest pour l’indexeur. Tant pis si on perd la compatibilité avec le genesis gdev dont l’utilité est principalement la flexibilité pour les tests d’intégration.

Par contre, il y a toujours un problème de schéma détecté par le playground : la console hasura sait très bien faire la requête, mais le playground retourne une erreur.

L’indexeur est en train d’indexer, il a dépassé le bloc 100 000. Par contre, il y a quelques erreurs d’indexation, il faudra surveiller ça. Peut-être des incohérences des données.

  • résoudre le schéma détecté par le playground (pas de smith dans pnpm schema)
  • observer et comprendre l’origine des erreurs rencontrées lors de l’indexation
3 Likes

Hello,
Dites moi si je dois mettre ceci dans un nouveau sujet dans le forum:

Je constate que les certifications de Pini reçues par Vit sont en double et que le “validated_at” est à “null”

Par ailleurs dans polkadot.js.org/app le “smithsMembership.membership” de vit est à <none> . Parce qu’il n’a pas encore effectué le claimMembership() ?

query ($address: String) {
  smith_cert(where: {receiver: {identity: {pubkey: {_eq: $address}}}}) {
    issuer {
      identity {
        pubkey
        name
        validated_at
        index
      }
    }
  }
}
{
  "data": {
    "smith_cert": [
      {
        "issuer": {
          "identity": {
            "pubkey": "5Dq8xjvkmbz7q4g2LbZgyExD26VSCutfEc6n4W4AfQeVHZqz",
            "name": "h30x",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 2457
          }
        }
      },
      {
        "issuer": {
          "identity": {
            "pubkey": "5CQ8T4qpbYJq7uVsxGPQ5q2df7x3Wa4aRY6HUWMBYjfLZhnn",
            "name": "poka",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 6951
          }
        }
      },
      {
        "issuer": {
          "identity": {
            "pubkey": "5D2DnScFpxoEUXDwZbJH18tRsQMygBSh1F6YCcWvTYzKY2W7",
            "name": "tuxmain",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 7139
          }
        }
      },
      {
        "issuer": {
          "identity": {
            "pubkey": "5GBVhdJUdsGhxozu6R8X6x2pTZvuuW46s7JSU4tiW7Zd3WmY",
            "name": "Pini",
            "validated_at": null,
            "index": 7228
          }
        }
      },
      {
        "issuer": {
          "identity": {
            "pubkey": "5GBVhdJUdsGhxozu6R8X6x2pTZvuuW46s7JSU4tiW7Zd3WmY",
            "name": "Pini",
            "validated_at": null,
            "index": 7228
          }
        }
      }
    ]
  }
}

Si claimMembership n’a pas été appelé, alors l’identité reste dans pendingMembership.

…or pour Vit (index 7174)

smithsMembership.pendingMembership: Option<CommonRuntimeEntitiesSmithsMembershipMetaData>
<none>

Autre constatation pour Poka (index 6951) :
sur polkadot.js.org/app j’ai 9 certifications émises

smithsCert.storageIdtyCertMeta: PalletCertificationIdtyCertMeta
{
  issuedCount: 9
  nextIssuableOn: 2,524,770
  receivedCount: 5
}

Sur l’indexeur j’en ai que 8 affichées:

{
  "data": {
    "smith_cert": [
      {
        "receiver": {
          "identity": {
            "pubkey": "5CCrBS67BrpBx3ihGHc72HZp3eHHbETxWFuNfwbbdoGSJFN8",
            "name": "1000i100",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 1
          }
        }
      },
      {
        "receiver": {
          "identity": {
            "pubkey": "5Dq8xjvkmbz7q4g2LbZgyExD26VSCutfEc6n4W4AfQeVHZqz",
            "name": "h30x",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 2457
          }
        }
      },
      {
        "receiver": {
          "identity": {
            "pubkey": "5DUjwHRqPayt3tAZk1fqEgU99xZB9jzBHKy2sMSTNcc7m9D1",
            "name": "ManUtopiK",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 3595
          }
        }
      },
      {
        "receiver": {
          "identity": {
            "pubkey": "5CtmAELWQ6FGDrAfsfVbGe4CXW4YrpNRTVU27eWzSE6J8ocU",
            "name": "elois",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 6317
          }
        }
      },
      {
        "receiver": {
          "identity": {
            "pubkey": "5D2DnScFpxoEUXDwZbJH18tRsQMygBSh1F6YCcWvTYzKY2W7",
            "name": "tuxmain",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 7139
          }
        }
      },
      {
        "receiver": {
          "identity": {
            "pubkey": "5FH48744BHgNoLBe8syGXbTEnSpGhp8ttdAKW4MWcR7TUKai",
            "name": "vit",
            "validated_at": "2022-12-13T01:35:24.001+00:00",
            "index": 7174
          }
        }
      },
      {
        "receiver": {
          "identity": {
            "pubkey": "5GBVhdJUdsGhxozu6R8X6x2pTZvuuW46s7JSU4tiW7Zd3WmY",
            "name": "Pini",
            "validated_at": null,
            "index": 7228
          }
        }
      },
      {
        "receiver": {
          "identity": {
            "pubkey": "5E58CLNXPFpBWrygp3ry8HyS2hiuQpRuXbZFUaTq7q9gG3Vv",
            "name": "AAAAA",
            "validated_at": null,
            "index": 7237
          }
        }
      }
    ]
  }
}

Etrange, car j’ai accompli toutes les étapes y compris ClaimMembership. J’ai même forgé des blocs avec mon serveur validateur avant qu’il décroche et que je le déclare offline.

Tu peux ajouter le champ “created_on” à ta requête pour voir qu’il s’agit d’une certification qui a été renouvelée.

requête
query ($address: String) {
  smith_cert(where: {receiver: {identity: {pubkey: {_eq: $address}}}}) {
    issuer {
      identity {
        name
        index
      }
    }
    created_on
  }
}
variables
{"address": "5FH48744BHgNoLBe8syGXbTEnSpGhp8ttdAKW4MWcR7TUKai"}
réponse
{
  "data": {
    "smith_cert": [
      {
        "issuer": {
          "identity": {
            "name": "h30x",
            "index": 2457
          }
        },
        "created_on": 1606658
      },
      {
        "issuer": {
          "identity": {
            "name": "poka",
            "index": 6951
          }
        },
        "created_on": 1606258
      },
      {
        "issuer": {
          "identity": {
            "name": "tuxmain",
            "index": 7139
          }
        },
        "created_on": 1606875
      },
      {
        "issuer": {
          "identity": {
            "name": "Pini",
            "index": 7228
          }
        },
        "created_on": 1033152
      },
      {
        "issuer": {
          "identity": {
            "name": "Pini",
            "index": 7228
          }
        },
        "created_on": 1617101
      }
    ]
  }
}

À regarder de plus près. Visiblement l’indexeur utilise le “signer” pour identifier l’identité validée, mais c’est faux, car dans ce cas l’identité est validée par le certificateur. src/processors/identity.ts · master · nodes / duniter-indexer · GitLab. Bug à corriger, donc.

requête

sur subsquid : https://subsquid.gdev.coinduf.eu/

{
  batch(
    limit: 100
    includeAllBlocks: false
    events: [{ name: "Identity.IdtyValidated" }]
  ) {
    header {
      height
    }
  }
}
réponse

regarder les blocs sur un nœud archive pour voir les événements

{
  "data": {
    "batch": [
      {
        "header": {
          "height": 626276
        }
      },
      {
        "header": {
          "height": 1491387
        }
      },
      {
        "header": {
          "height": 1716493
        }
      }
    ]
  }
}

Effectivement, il manque la certification du bloc 2510370. Reste à savoir pourquoi.

Je l’ai trouvée avec la requête subsquid suivante:

requête

sur https://explorer.subsquid.gdev.coinduf.eu/graphql

query MyQuery {
  events(where: {name_eq: "SmithsCert.NewCert", extrinsic: {calls_some: {args_jsonContains: "{\"issuer\": 6951}"}}}) {
    block {
      height
    }
    extrinsic {
      call {
        name
        args
      }
    }
  }
}
réponse
{
  "data": {
    "events": [
      {
        "block": {
          "height": 586196
        },
        "extrinsic": {
          "call": {
            "name": "SmithsCert.add_cert",
            "args": {
              "issuer": 6951,
              "receiver": 7228
            }
          }
        }
      },
      {
        "block": {
          "height": 1534981
        },
        "extrinsic": {
          "call": {
            "name": "SmithsCert.add_cert",
            "args": {
              "issuer": 6951,
              "receiver": 7237
            }
          }
        }
      },
      {
        "block": {
          "height": 1606258
        },
        "extrinsic": {
          "call": {
            "name": "SmithsCert.add_cert",
            "args": {
              "issuer": 6951,
              "receiver": 7174
            }
          }
        }
      },
      {
        "block": {
          "height": 2510370
        },
        "extrinsic": {
          "call": {
            "name": "SmithsCert.add_cert",
            "args": {
              "issuer": 6951,
              "receiver": 7238
            }
          }
        }
      }
    ]
  }
}

Effectivement, et c’était au bloc 1620356. Et si on regarde smithsMembership.membership() à ce bloc, on trouve bien ceci :

Par contre, tu as cessé d’être forgeron au bloc 2504292. Le système a révoqué ton compte, probablement à cause d’un trop long délai hors ligne ou sans renouvellement des session keys, je ne sais pas.


J’espère que tous ces éléments permettront à d’autres d’essayer de débugger en utilisant les outils à disposition.

2 Likes