Migrate identity (identity.changeOwnerKey())

bonbonbon j’y suis presque, on avance!

Y a il un moyen pour moi de vérifier la signature via polkadot js ?

Cela fonctionne pour un message de type String signé par mon code, mais pas pour un Uint8List.
Est-ce que c’est censé fonctionner pour un Uint8List graphiquement ici ?

Non, polkadot js ne peut vérifier que les signatures émises via la lib polkadot/api, car ça ajoute des wrapping bytes, je suis d’ailleurs persuadé que c’est la cause de ton problème.

Pour ne pas avoir les wraping bytes, il te faut descendre plus bas niveau en js, et utiliser directement la fonction sr25519Sign du paquet npm @polkadot/util-crypto.

Pour vérifier, tu peux check la signature avec un bout de code python, je peux aussi le faire avec un bout de code rust, si tu me fournis pubkey et sig.

1 Like

Je vais tenter une question bête, mais ne serait-il pas possible de changer côté duniter la vérification de la signature du message en hexa plutôt que Uint8Array pour cet extrinsic ?

En hexa ce même message donne

0x69636f6b07c112ff6ab9d7d0d531ebe59f98b35318b2813b1655577380819d38d6182d9915000000b552b263c6049cbe4e236689ff07a21f104fff8482ede6deb058f5d9ed4ec4ef

Non pas possible, le runtime wasm doit être léger et rapide, il contient les SCALE codec nais c’est tout, il ne contient rien pour gérer ou parser les chaînes de caractères, et ne le peut pas, car c’est du no_std.

En plus ça ne résoudrait en rien ton problème, puisque c’est un souci de signature, pas de génération du message.

Faut pas te décourager @poka, tu as déjà énormément avancé, c’est normal que tu galères surtout que tu dois composer avec une couche javascript que tu ne maîtrises pas bien.

Fais une pause :slight_smile:

3 Likes

Après quelques précieuses indications d’elois et une bonne nuit de sommeil, j’ai pu mettre à jours mon fork de polkawallet_sdk pour permettre la signature unwrap du message Uint8List:

Et cela a fonctionné ! L’identité zombie (initialement sur l’adresse corresponsant à Cesium(test,test)) a été migré vers mon adresse 5D2HHRj6zCEL9iY3CBpKy1mBMtpXUJCFDNvevBqVQAWdzqSS (dérivation de mon coffre gecko) !! :slight_smile:

Par contre l’indexer de @cgeek n’a pas compris ce qu’il s’est passé lol, c’est normal ce cas d’usage n’était pas encore prévue.

4 Likes

@ManUtopiK @cgeek , il faut que l’indexeur écoute l’event Identity.IdtyChangedOwnerKey, cet event contient 2 paramètres: le IdtyIndex et la nouvelle adresse.

Je vous ai créé une issue:

https://git.duniter.org/manutopik/duniter-indexer/-/issues/12

4 Likes

Tiens, en regardant ton code qui fait le unwrap() je vois que juste avant tu fais :

if (!keyPair.isLocked) {
        keyPair.lock();
      }

Pourquoi as tu besoin de Locker, juste avant le sign() ?
C’est plutôt le contraire ?

Ce n’est pas mon code, c’est le package polkawallet_sdk, je n’ai fait que changer wrap to unwrap pour régler le problème de signature que j’avais.

Je ne sais pas à quoi correspond keyPair.lock(), je ne m’en sert nul part dans mon code.
C’est une interface JS, je n’ai pas été voir à quoi ça correspond. Je suis d’accords que c’est étrange de voir lock et non unlock ici, mais bon ça fonctionne j’en demande pas plus pour cette partie pour le moment ^^

Je n’arrive plus à migrer d’identité sur le nouveau runtime 700. Je test uniquement sur mon noeud de dev local, car tester la gdev aujourd’hui à m’a permis de me rendre compte que je n’étais plus membre de la Ğ1 au moment du lancement pour non renouvellement de mon adhésion …

Voici l’erreur que j’obtiens:

Uncaught Error: createType(Call):: Call: failed decoding identity.changeOwnerKey:: Struct: failed on args: {"new_key":"AccountId32","new_key_sig":"{\"_enum\":{\"Ed25519\":\"SpCoreEd25519Signature\",\"Sr25519\":\"SpCoreSr25519Signature\",\"Ecdsa\":\"SpCoreEcdsaSignature\"}}"}:: Struct: failed on new_key_sig: {"_enum":{"Ed25519":"SpCoreEd25519Signature","Sr25519":"SpCoreSr25519Signature","Ecdsa":"SpCoreEcdsaSignature"}}:: Unable to create Enum via index 212, in Ed25519, Sr25519, Ecdsa

Est-ce que vous pouvez me confirmer qu’il s’agit bien d’une erreur de signature (new_key_sig) invalide ?
Si c’est le cas, le message d’erreur a été modifié depuis la dernière fois (et tant mieux).

Vous n’avez pas changer quoi que ce soit à ce niveau ? Toujours le même préfix icok par exemple (je n’ai pas encore été vérifier dans le code) ?

Arrivez-vous à effectuer une migration d’identité avec d’autres clients avec d’autres clients que Gecko ? Ou arrivez-vous à le faire avec Gecko sur la gdev (ou terminez-vous en timeout) ?


edit: Je viens de tester sur l’image du runtime 300 (debug-sha-4d5e08be), et je confirme que la migration d’identité fonctionne avec gecko sur ce runtime, il a donc eu un changement depuis côté Duniter.

1 Like

Oui, j’ai changé le nom de la struct “payload”, mais ça devrait pas avoir changé le message à soumettre :thinking:

Il faut que j’implémente la migration d’identité dans Ğcli, je vais essayer de le faire vite avant de devenir forgeron et je te dis ce que je vois.

2 Likes

Pour info, en python, on passe de ça :

params = {"new_key": new_keypair.ss58_address, "new_key_sig": signature_bytes}

à ça :

# newKey: AccountId32, newKeySig: SpRuntimeMultiSignature
params = {"new_key": new_keypair.ss58_address, "new_key_sig": {"Sr25519": signature_bytes}}
2 Likes

Ah zut, j’avais oublié de tenir au courant. Je l’ai bien implémenté dans Ğcli en permettant aussi les clés ed25519 générées “méthode Cesium” (c’est comme ça que j’ai fait pour migrer mon identité forgeron) et ça ressemble à ça :

/// change owner key
pub async fn change_owner_key(
	data: &Data,
	address: AccountId,
	keypair: KeyPair,
) -> Result<(), subxt::Error> {
	let (_payload, signature) = generate_chok_payload(data, address.clone(), keypair);

	// this is a hack, see
	// https://substrate.stackexchange.com/questions/10309/how-to-use-core-crypto-types-instead-of-runtime-types
	let signature = match signature {
		Signature::Sr25519(signature) => MultiSignature::Sr25519(
			runtime::runtime_types::sp_core::sr25519::Signature(signature.0),
		),
		Signature::Nacl(signature) => MultiSignature::Ed25519(
			runtime::runtime_types::sp_core::ed25519::Signature(signature.try_into().unwrap()),
		),
	};

	submit_call_and_look_event::<
		runtime::identity::events::IdtyChangedOwnerKey,
		Payload<runtime::identity::calls::types::ChangeOwnerKey>,
	>(
		data,
		&runtime::tx()
			.identity()
			.change_owner_key(address, signature),
	)
	.await
}

Merci @vit pour le ping ^^

Lorsque je migre une identité une première fois (changeOwnerKey), ça fonctionne.
Lorsque je tente de la migrer une seconde fois juste après, j’ai l’erreur:

Module error: pallet 41 -> identity.IssuerNotMember

  1. Je ne comprends pas l’erreur, elle est fausse, l’identité en question est bien membre
  2. Est-ce une comportement normal ?
  3. Comment prédire côté apps que l’identité ne peut pas migrer ?

Tu as bien signé l’extrinsic avec le bon compte (celui qui a reçu l’identité lors du premier changement) ?

Oui à priori, j’ai fais la même action dans un sens, puis dans l’autre. Si ça ne vous parait pas normal je vais investigué plus côté client, mais je ne vois pas pourquoi il signerait bien le premier coup, puis mal le second coup, avec exactement la même procédure inverse.

1 Like

Il y a un truc qui empêche de réutiliser l’ancien compte pour une identité, ou de re-changer de clé avant un certain délai. Mais en effet si c’est ça l’erreur n’est pas la bonne.

1 Like

Normalement c’est le seul endroit où on jette l’erreur IssuerNotMember : pallets/identity/src/lib.rs · master · nodes / rust / Duniter v2S · GitLab (dans check_create_identity).

Donc je suis vraiment curieux de voir quel est ton call. J’ai regardé les derniers ExtrinsicFailed, mais à part au bloc 234716, je vois pas beaucoup de change owner key, et jamais avec l’erreur IssuerNotMember.

query Qerr {
  event(limit: 100, where: {name: {_eq: "ExtrinsicFailed"}}, orderBy: {block: {height: DESC}}) {
    pallet
    name
    block{height,calls{name}}
  }
}

Tu peux montrer à quel bloc tu as l’erreur ?

C’est également uniquement sur une chains de test local gdev que je fais ça.
C’est probable que comme pour l’autre erreur, ce soit dû au fait que j’utilise le runtime gtest au lieu de celui gdev.

Je rédige des tests end2end sur une gdev locale pour Tikka et j’ai des soucis avec la migration d’un compte V1 vers V2 :

  • Il reste 100 centimes sur le compte source malgré l’appel à l’extrinsic transferAll(keep_alive=false)
  • L’identité a bien été migrée, mais si j’interroge l’api RPC, le storage dit que le compte source est toujours lié à l’identité.

Dépôt d’existence non transféré

Après un extrinsic transferAll(keep_alive=false) de Bob (je triche dans mes tests car ce n’est pas un compte V1) à un nouveau compte V2 :

Bob :

{
  nonce: 2
  consumers: 1
  providers: 1
  sufficients: 1
  data: {
    free: 100
    reserved: 0
    feeFrozen: 0
    linkedIdty: 2
  }
}
5DnWJYCLXYWTXqMhXhJ8oi2oQQikHnSBUQBq5NmyD46VZAHG : 
{
  nonce: 0
  consumers: 0
  providers: 2
  sufficients: 1
  data: {
    free: 900
    reserved: 0
    feeFrozen: 0
    linkedIdty: 2
  }
}

Le dépôt d’existence n’a pas été transféré…
Si je tente un second transferAll(keep_alive=false) avec polkadot.js cette fois :

Je ne peux pas complètement vider le compte source !

[EDIT]
Ticket créé sur le Gitlab

Identité transférée mais le compte source reste lié

L’identité a bien le nouveau compte V2 en propriétaire et Bob en ancien propriétaire.

{
  data: {
    firstEligibleUd: 1
  }
  nextCreatableIdentityOn: 0
  oldOwnerKey: [
    5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty
    5
  ]
  ownerKey: 5DnWJYCLXYWTXqMhXhJ8oi2oQQikHnSBUQBq5NmyD46VZAHG
  nextScheduled: 0
  status: Member
}

Mais Bob est toujours lié à l’identité !!?? :

{
  nonce: 2
  consumers: 1
  providers: 1
  sufficients: 1
  data: {
    free: 100
    reserved: 0
    feeFrozen: 0
    linkedIdty: 2
  }
}

[EDIT]

1 Like

Je crois que c’est prévu dans le protocole de garder une trace des oldOwnerKey après migration non ?