Can an identity have no associated account?

{
  identity(where: {accountId: {_isNull: true}}) {
    accountId
    account {
      createdOn
    }
    name
    status
    createdInId
    createdOn
    expireOn
    firstEligibleUd
    id
    index
    lastChangeOn
  }
}

{
  "data": {
    "identity": [
      {
        "accountId": null,
        "account": null,
        "name": "0000115597-0c545-000002",
        "status": "REMOVED",
        "createdInId": "0000115597-0c545-000002",
        "createdOn": 115597,
        "expireOn": 129997,
        "firstEligibleUd": null,
        "id": "0000115597-0c545-000002",
        "index": 14574,
        "lastChangeOn": 115597
      },
      {
        "accountId": null,
        "account": null,
        "name": "ChristCosmic",
        "status": "REMOVED",
        "createdInId": "0000069295-23123-000002",
        "createdOn": 69295,
        "expireOn": 945902,
        "firstEligibleUd": null,
        "id": "0000069295-23123-000002",
        "index": 14573,
        "lastChangeOn": 69302
      },
      {
        "accountId": null,
        "account": null,
        "name": "tuxmaintest01",
        "status": "REMOVED",
        "createdInId": "0001317492-bfa3d-000002",
        "createdOn": 1317492,
        "expireOn": 2194183,
        "firstEligibleUd": null,
        "id": "0001317492-bfa3d-000002",
        "index": 14575,
        "lastChangeOn": 1317583
      },
      {
        "accountId": null,
        "account": null,
        "name": "0002192620-ba24f-000002",
        "status": "REMOVED",
        "createdInId": "0002192620-ba24f-000002",
        "createdOn": 2192620,
        "expireOn": 2207020,
        "firstEligibleUd": null,
        "id": "0002192620-ba24f-000002",
        "index": 14578,
        "lastChangeOn": 2192620
      },
      {
        "accountId": null,
        "account": null,
        "name": "0002255022-81425-000002",
        "status": "REMOVED",
        "createdInId": "0002255022-81425-000002",
        "createdOn": 2255022,
        "expireOn": 2269422,
        "firstEligibleUd": null,
        "id": "0002255022-81425-000002",
        "index": 14579,
        "lastChangeOn": 2255022
      },
      {
        "accountId": null,
        "account": null,
        "name": "0002318658-7d776-000002",
        "status": "REMOVED",
        "createdInId": "0002318658-7d776-000002",
        "createdOn": 2318658,
        "expireOn": 2333058,
        "firstEligibleUd": null,
        "id": "0002318658-7d776-000002",
        "index": 14581,
        "lastChangeOn": 2318658
      },
      {
        "accountId": null,
        "account": null,
        "name": "d0p1",
        "status": "REMOVED",
        "createdInId": "0001562241-75850-000002",
        "createdOn": 1562241,
        "expireOn": 2451624,
        "firstEligibleUd": null,
        "id": "0001562241-75850-000002",
        "index": 14576,
        "lastChangeOn": 1575024
      },
      {
        "accountId": null,
        "account": null,
        "name": "0002731824-23863-000002",
        "status": "REMOVED",
        "createdInId": "0002731824-23863-000002",
        "createdOn": 2731824,
        "expireOn": 2746224,
        "firstEligibleUd": null,
        "id": "0002731824-23863-000002",
        "index": 14582,
        "lastChangeOn": 2731824
      },
      {
        "accountId": null,
        "account": null,
        "name": "0002761399-cbfb2-000002",
        "status": "REMOVED",
        "createdInId": "0002761399-cbfb2-000002",
        "createdOn": 2761399,
        "expireOn": 2775799,
        "firstEligibleUd": null,
        "id": "0002761399-cbfb2-000002",
        "index": 14583,
        "lastChangeOn": 2761399
      },
      {
        "accountId": null,
        "account": null,
        "name": "0002920654-af135-000002",
        "status": "REMOVED",
        "createdInId": "0002920654-af135-000002",
        "createdOn": 2920654,
        "expireOn": 2935054,
        "firstEligibleUd": null,
        "id": "0002920654-af135-000002",
        "index": 14584,
        "lastChangeOn": 2920654
      },
      {
        "accountId": null,
        "account": null,
        "name": "0002972030-eb0f1-000003",
        "status": "REMOVED",
        "createdInId": "0002972030-eb0f1-000003",
        "createdOn": 2972030,
        "expireOn": 2986430,
        "firstEligibleUd": null,
        "id": "0002972030-eb0f1-000003",
        "index": 14585,
        "lastChangeOn": 2972030
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003013307-ab747-000002",
        "status": "REMOVED",
        "createdInId": "0003013307-ab747-000002",
        "createdOn": 3013307,
        "expireOn": 3027707,
        "firstEligibleUd": null,
        "id": "0003013307-ab747-000002",
        "index": 14586,
        "lastChangeOn": 3013307
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003111160-d83a2-000002",
        "status": "REMOVED",
        "createdInId": "0003111160-d83a2-000002",
        "createdOn": 3111160,
        "expireOn": 3125560,
        "firstEligibleUd": null,
        "id": "0003111160-d83a2-000002",
        "index": 14587,
        "lastChangeOn": 3111160
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003231555-d5852-000003",
        "status": "REMOVED",
        "createdInId": "0003231555-d5852-000003",
        "createdOn": 3231555,
        "expireOn": 3245955,
        "firstEligibleUd": null,
        "id": "0003231555-d5852-000003",
        "index": 14591,
        "lastChangeOn": 3231555
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003295988-ce40c-000001",
        "status": "REMOVED",
        "createdInId": "0003295988-ce40c-000001",
        "createdOn": 3295988,
        "expireOn": 3310388,
        "firstEligibleUd": null,
        "id": "0003295988-ce40c-000001",
        "index": 14592,
        "lastChangeOn": 3295988
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003221055-dc0af-000002",
        "status": "REMOVED",
        "createdInId": "0003221055-dc0af-000002",
        "createdOn": 3221055,
        "expireOn": 3235455,
        "firstEligibleUd": null,
        "id": "0003221055-dc0af-000002",
        "index": 14590,
        "lastChangeOn": 3221055
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003311459-0dce8-000001",
        "status": "REMOVED",
        "createdInId": "0003311459-0dce8-000001",
        "createdOn": 3311459,
        "expireOn": 3325859,
        "firstEligibleUd": null,
        "id": "0003311459-0dce8-000001",
        "index": 14593,
        "lastChangeOn": 3311459
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003344848-424ab-000001",
        "status": "REMOVED",
        "createdInId": "0003344848-424ab-000001",
        "createdOn": 3344848,
        "expireOn": 3359248,
        "firstEligibleUd": null,
        "id": "0003344848-424ab-000001",
        "index": 14595,
        "lastChangeOn": 3344848
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003439195-e24f0-000001",
        "status": "REMOVED",
        "createdInId": "0003439195-e24f0-000001",
        "createdOn": 3439195,
        "expireOn": 3453595,
        "firstEligibleUd": null,
        "id": "0003439195-e24f0-000001",
        "index": 14596,
        "lastChangeOn": 3439195
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003541070-69697-000001",
        "status": "REMOVED",
        "createdInId": "0003541070-69697-000001",
        "createdOn": 3541070,
        "expireOn": 3555470,
        "firstEligibleUd": null,
        "id": "0003541070-69697-000001",
        "index": 14597,
        "lastChangeOn": 3541070
      },
      {
        "accountId": null,
        "account": null,
        "name": "0003739364-c18fb-000001",
        "status": "REMOVED",
        "createdInId": "0003739364-c18fb-000001",
        "createdOn": 3739364,
        "expireOn": 3753764,
        "firstEligibleUd": null,
        "id": "0003739364-c18fb-000001",
        "index": 14598,
        "lastChangeOn": 3739364
      },
      {
        "accountId": null,
        "account": null,
        "name": "0004143628-38ef7-000001",
        "status": "REMOVED",
        "createdInId": "0004143628-38ef7-000001",
        "createdOn": 4143628,
        "expireOn": 4158028,
        "firstEligibleUd": null,
        "id": "0004143628-38ef7-000001",
        "index": 14600,
        "lastChangeOn": 4143628
      },
      {
        "accountId": null,
        "account": null,
        "name": "SpiranneGecko",
        "status": "REMOVED",
        "createdInId": "0003207864-4e4ce-000002",
        "createdOn": 3207864,
        "expireOn": 4090070,
        "firstEligibleUd": null,
        "id": "0003207864-4e4ce-000002",
        "index": 14589,
        "lastChangeOn": 3213470
      }
    ]
  }
}

Est-ce normal d’avoir des identités sans comptes associés dans l’indexer ?

1 Like

Le nom est encore dans IdentitiesNames mais l’identité n’est pas dans Identity ni dans IdentityIndexOf, donc l’identité n’existe plus. Le nom est conservé pour éviter son réemploi à des fins de phishing.

Ok donc ça fait sens de garder les identities removed pour en garder une trace.

Contexte

Une des difficultés de l’indexeur est de garder un index complet incluant des données supprimées sur Duniter à des fins d’historique. Un exemple avec ce bug : Bug subsquid - #5 by HugoTrentesaux.

Tu noteras les champs account et accountRemoved dans le schéma schema.graphql · main · nodes / duniter-squid · GitLab :

"Identity"
type Identity @entity {
  "Identity index"
  index: Int! @index @unique
  "Current account"
  # should be null for a removed identity and only in this case
  account: Account @unique
  "Let track the account in case identity was removed"
  # should be non null for a removed identity and only in this case
  accountRemoved: Account
  "Name"
  name: String! @index

Le champ account porte la contrainte @unique mais Duniter ne force cette contrainte que pendant un certain temps. Quand l’identité est supprimée, une autre peut être créée en utilisant le même account. Que doit faire l’indexeur dans ce cas ?

C’est pour ça que dans account, identity est unique (Identity) alors que removedIdentities est multiple ([Identity]).

"Account table identified by its ss58 address"
type Account @entity {
  "current account for the identity"
  identity: Identity @derivedFrom(field: "account")
  "removed identities on this account"
  # they are handled apart to avoid dropping the @unique constraint of account
  removedIdentities: [Identity] @derivedFrom(field: "accountRemoved")

Il y aura le même problème quand on décidera de libérer des pseudos pour réutilisation. Pour l’instant, tous les outils partent du principe que [un pseudo = une identité]. Mais si Duniter libère le pseudo d’une identité supprimée il est possible qu’une autre identité l’utilise après. Dans ce cas l’indexeur devra faire la même chose : ajouter un champ nameRemoved pour garder une trace des anciennes identités qui ont utilisé ce pseudo.

Réponse

Oui, et uniquement pour les identités qui ont été supprimées de Duniter :

Tu peux donc réutiliser la même clé pour créer une autre identité sans faire crasher l’indexeur et en conservant la contrainte @unique qu’il serait très gênant d’abandonner.

1 Like

Tiens, cette remarque m’inspire une méthode de test : on devrait pouvoir créer des états (ex. : fiche de membre, comme cette page de Duniter Panel) qui soient à la fois générés par de la consultation d’un indexeur et par la consultation du Storage : le test consiste à vérifier qu’il n’existe aucune différence.

Cela permet autant de détecter des bugs côtés indexeur que côté Duniter.

Bien sûr la génération par consultation du Storage sera généralement beaucoup plus coûteuse (c’est bien pour ça qu’on crée des indexeurs), mais peu importe : il peut s’agir de tests sur demande. Des Golden Tests en quelque sorte.

J’ajoute ça à Have a testing strategy (#141) · Issues · nodes / rust / Duniter v2S · GitLab.

3 Likes