2017-09-20 18 views
1

tl; dr Comment doit-on effectuer Hash160, en utilisant la plupart des outils python de base?Obtenir l'adresse Hash160 bitcoin en python

============================================== ======

Salut,

J'essaie de comprendre, comment les transactions fonctionnent en Bitcoin. Lorsque je choisis des entrées pour un nouveau tx, je veux m'assurer qu'elles appartiennent à une adresse spécifique. Cependant, les tx existants ne spécifient pas les adresses des sorties précédentes, mais plutôt le hash de l'adresse.

par exemple:

>> bx fetch-tx 11a1b7ac0a65bd50b7094c720aecd77cfd83d84b1707960fd00dd82a888aab5c --config /home/theo/Desktop/bx-testnet.cfg 

{ 
    hash 11a1b7ac0a65bd50b7094c720aecd77cfd83d84b1707960fd00dd82a888aab5c 
    inputs 
    { 
     input 
     { 
      address_hash f3b7278583827a049d6be894bf7f516178a0c8e6 
      previous_output 
      { 
       hash 4a3532061d43086299ae9b2409a456bb9638dff32e0858c4ccda27203fb2e4f6 
       index 1 
      } 
      script "[30440220146b8b5b014245a9e27e21122d4dded04c3f39c3a49ac2494743d6f6ae8efff602206d417a4be9c7431ea69699132438510ade1cf8d746607f77d114907762ed1eb301] [023dd2e892290e41bb78efce6ea30a97015ef13eaaa9ebb7b0514485fc365cc391]" 
      sequence 4294967295 
     } 
    } 
    lock_time 0 
    outputs 
    { 
     output 
     { 
      address_hash a73706385fffbf18855f2aee2a6168f29dbb597e 
      script "dup hash160 [a73706385fffbf18855f2aee2a6168f29dbb597e] equalverify checksig" 
      value 130000000 
     } 
     output 
     { 
      address_hash ad6e80394af99ece5d7701bf2f457480b93965b7 
      script "dup hash160 [ad6e80394af99ece5d7701bf2f457480b93965b7] equalverify checksig" 
      value 49525957813 
     } 
    } 
    version 1 
} 

Dites, je veux vérifier que des sorties peuvent être envoyées à partir de l'adresse mvm74FACaagz94rjWbNmW2EmhJdmEGcxpa donc je prends son Hash160 en Python:

>> hashlib.new('ripemd160', hashlib.sha256("mvm74FACaagz94rjWbNmW2EmhJdmEGcxpa".encode('utf-8')).digest()).hexdigest() 
'748598cd9b004aecf8a2d97464fb1f2a90562ffe' 

Ce n'est pas le résultat Je m'attendais: a73706385fffbf18855f2aee2a6168f29dbb597e

Pendant ce temps, le service en ligne this calcule correctement le hachage.

Comment hacher160 une adresse bitcoin en Python?

Répondre

2

Enfin, je l'ai fait. Certaines révélations dans ma réponse peuvent sembler évidentes et fondamentales pour vous, mais j'espère qu'elles seront utiles au ppl qui sont complètement nouvelles pour bitcoin (comme moi).

========

Wiki dit que je peux obtenir Hash160 en inversant la dernière étape de production d'adresse

enter image description here (Hash160 est mise en surbrillance)

Cette étape est codant pour une chaîne d'octets avec alphabet base58

b58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' 

Ce manque alphabet 0, I, l, s, étant donné que ces s les ymbols sont faciles à mélanger. Et c'est la dernière chose que vous voulez faire quand un mauvais symbole peut conduire à perdre une grosse somme d'argent.

Ainsi, nous devons transformer mvm74FACaagz94rjWbNmW2EmhJdmEGcxpa en une chaîne d'octets. Les octets vont au format hexadécimal et peuvent aller de 0x00 (0 décimal) à 0xff (255 décimal). Et n'oublions pas que nous avons un alphabet b58 spécial à traiter: le décodage de l'adresse avec utf-8 ou d'autres standards d'encodage donnera des absurdités.

Au début, je pensais que je peux facilement décoder l'adresse avec cette fonction:

def decode(addr): 
    b58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' 
    decoded = '' 
    for i in addr: 
     temp = hex(b58.index(i)) 
     if len(temp) == 3: 
      temp = '0' + temp[-1] 
     else: 
      temp = temp[2:] 
     decoded += (temp) 
    return (decoded) 

decode('mvm74FACaagz94rjWbNmW2EmhJdmEGcxpa') 

>> '2c352c06030e090b212127390803312a1d22152c1d010d2c2811242c0d0f23372f21' 

Mais le résultat est rien comme le hachage j'ai regardé dans la transaction (a73706385fffbf18855f2aee2a6168f29dbb597e). De cette façon, j'ai appris que je n'avais aucune idée de la façon dont le décodage est fait. Que se passe-t-il si Hash160 a 0xff? Il n'y a pas un tel symbole dans b58, comme 58 dans hex est juste 0x3a. Lors du décodage de b58, nous ne pouvons pas traiter chaque symbole indépendamment.L'adresse complète constitue un chiffre géant écrit en base58 (son premier chiffre correspond à 58 ** 34).

Pour obtenir la chaîne d'octets, j'ai d'abord transformé ce nombre en nombre décimal et seulement ensuite en octet.

Si vous savez comment éviter ce détour et obtenir octets directement - s'il vous plaît commentaire

def decode(addr): 

    b58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' 

    def base58_to_dec(addr): 
     dec = 0 
     for i in range(len(addr)): 
      dec = int(dec * 58 + b58.index(addr[i])) 
     print('Decimal representation') 
     print(dec) 
     return(dec) 

    def dec_to_byte(dec): 
     out = '' 
     while dec != 0: 
      print(dec) 
      remn = dec % 256 
      dec = int((dec - remn)/256) 
      temp = hex(remn) 
      if len(temp) == 3: 
       temp = '0' + temp[-1] 
      else: 
       temp = temp[2:] 
      out = temp + out 
     return(out) 

    dec = base58_to_dec(addr) 
    out = dec_to_byte(dec) 
    return (out) 

decode("mvm74FACaagz94rjWbNmW2EmhJdmEGcxpa") 
>> Decimal representation 
>> 700858390993795610399098743129153130886272689085970101576715 
>> '6fa7370638600000000000000000000000000000000000000b' 

Cette sortie ressemble un peu ce que je dois (a7370638...), mais a beaucoup trop de zéros. Ne regardez pas que le premier octet (6f) ne correspond pas: il n'a rien à voir avec Hash160 dont nous avons besoin, juste la version du protocole.

Il s'agit probablement d'une erreur de précision. Pour y faire face, j'ai utilisé mpmath qui vous permet de travailler avec des nombres entiers avec précision.

from mpmath import * 
mp.dps = 1000 

def decode(addr): 

    b58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' 

    def base58_to_dec(addr): 
     dec = 0 
     for i in range(len(addr)): 
      dec = int(dec * 58 + b58.index(addr[i])) 
     return(dec) 

    def dec_to_byte(dec): 
     out = '' 
     while dec != 0: 
      remn = mpf(dec % 256) 
      dec = mpf((dec - remn)/256) 
      temp = hex(int(remn)) 
      if len(temp) == 3: 
       temp = '0' + temp[-1] 
      else: 
       temp = temp[2:] 
      out = temp + out 

     return (out) 

    dec = base58_to_dec(addr) 
    out = dec_to_byte(dec) 
    return (out) 

Appliquez le fonctionnement modulo précis et nous pouvons enfin obtenir le Hash160. Assurez-vous de couper les 4 premiers et derniers octets qui portent la vérification des doigts gras.

x = decode('mvm74FACaagz94rjWbNmW2EmhJdmEGcxpa') 
print(x) 
>> 6fa73706385fffbf18855f2aee2a6168f29dbb597ef59c240b 

print(x[2:-8]) 
>> a73706385fffbf18855f2aee2a6168f29dbb597e 

Yay! Tout comme dans la transaction!

+0

Bon travail! Merci d'avoir posté votre solution! – viraptor