p2sh : Ma transaction brute a détruit 0,0284377 BTC. Qu'ai-je fait de mal ?


Il y a des années. Il crée une représentation binaire de la transaction souhaitée basée sur le matériel présenté ici et ici  :

La représentation binaire est ensuite convertie en hexadécimal et diffusée via divers services gratuits tels que BlockExplorer, BlockCypher, etc.

Le système fonctionne parfaitement depuis des années. Jusqu’à hier. Un client a demandé que 0,0284377 BTC être envoyé à. Il ne l’a jamais reçu. Effectivement, il avait raison. Il n’a jamais été envoyé.

p2sh : Ma transaction brute a détruit 0,0284377 BTC. Qu'ai-je fait de mal ?

J’ai parcouru tous mes journaux et j’ai vu que mon logiciel avait en fait soumis une transaction avec les entrées et les sorties suivantes  :

  • entrée  :
  • sortie #1  : (mon client)
  • sortie #2  : (mon adresse de changement)

Tout semblait bien de mon côté, mais bien sûr, quand j’ai regardé l’explorateur de blocs, ce que j’ai vu m’a choqué. Considérez la transaction et regardez les entrées et les sorties  :

Comme vous pouvez le voir, ma saisie est correcte. Mon adresse de changement XU7 est également correcte. Mais regardez maintenant l’adresse de mon client. Ça dit (que j’appellerai JCA) au lieu de l’attendu (que j’appellerai 18v). Que diable? L’adresse JCA n’est connue ni de moi ni de mon client. C’est une adresse complètement inconnue.

De toute évidence, le problème se trouve quelque part dans mon code, j’ai donc creusé plus profondément pour découvrir ce qui rendait cette transaction particulière unique. J’ai identifié que son adresse souhaitée (18v) commence par un « 3 » alors que toutes les autres transactions sortantes que j’ai effectuées tout au long de l’historique de mon application ont des adresses ciblées commençant par « 1 ».

Ma mesure provisoire consistait à obliger les utilisateurs à ne spécifier que des adresses commençant par 1. Mais c’est une solution temporaire. Je dois découvrir ce que je fais mal.

Je me suis tourné vers Google. Les recherches ont indiqué que les adresses commençant par « 3 » sont généralement des adresses SegWit, tandis que celles commençant par « 1 » sont des adresses traditionnelles de la vieille école. Je me souviens de toutes les discussions sur SegWit il y a quelques mois, mais je pensais que cela ne m’affecterait pas et que mes anciennes transactions seraient toujours correctement effacées. De toute évidence, c’était un mauvais jugement de ma part, alors maintenant je dois comprendre ce que j’ai fait de manière incorrecte et d’où vient la fausse adresse JCA.

C’est là que je suis coincé. Je pense que mon problème pourrait avoir à voir avec les clés publiques non compressées ou compressées sur la base des discussions ici et ici :

Voici ce que je sais : Quand vient le temps de créer les sorties pour ma transaction, mon code fait ce qui suit (l’explication suit) :

Base58Decode(btcAddrHex).Take(addrBytes.Length-4).Skip(1).ToArray().Write((byte)0x76); //.Write((byte)0xa9); //.Write((octet)20); //taille de la clé publique bw.Write(pubKeyBytes); //clé publique bw.Write((byte)0x88); //.Write((byte)0xac); //.Flush(); return ms.ToArray();;

Ce que je fais ici, c’est : convertir l’adresse de sortie en octets en la décodant en Base58. Je supprime les quatre derniers octets, qui sont la somme de contrôle, et le premier octet, qui est toujours 0x00 (apparemment un indicateur de réseau quelconque). Cela me laisse avec la clé publique brute. En fait, en regardant mes notes internes, ce n’est pas vraiment la clé publique mais plutôt 0x04 ajouté à la clé publique et ensuite passé par SHA256 puis RIPEMD160. Mais je ferai référence à ce blob comme la clé publique. À partir de là, la séquence d’octets est 0x76, 0xa9, 20 (la taille du blob de clé publique), le blob de clé publique lui-même, 0x88 et 0xac.

Je ne prétends pas comprendre ce que signifient toutes ces entrées à un octet, mais les articles de blog ci-dessus disaient de les inclure, c’est donc ce que j’ai fait, et jusqu’à présent, cela a très bien fonctionné.

La question est la suivante  : comment diable l’adresse 18v a-t-elle été transformée en adresse JCA lorsqu’elle a été soumise au réseau ? Ma valeur de « taille de clé publique » (20) est-elle incorrecte, peut-être ? Au niveau de l’intestin, il semble étrange qu’une clé publique compressée (18v) et non compressée (JCA) ait toutes deux une taille constante de 20. Mais peut-être que je suis entièrement sur la mauvaise voie et que la compression n’a rien à voir avec ça.

Je n’ai pas à vous dire à quel point ce serait horrible si cette transaction était de 100 BTC au lieu de 0,0284377. J’ai eu de la chance que mon bogue ait été déclenché sur une transaction de faible valeur. Mais je veux vraiment résoudre ce problème. Pouvez-vous m’indiquer le bon chemin?