analizando direcciones de entrada y salida de bitcoin desde scripts

alguien puede guiarme a través del proceso de combinación de entradas y salidas de secuencias de comandos para revelar las direcciones de entrada y salida codificadas en base58. Tomemos, por ejemplo, el bloque 728 . esto tiene dos entradas de script sin procesar:

493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01

and

493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01

el primer byte de cada uno (49 hex = 73 dec) es la instrucción para insertar 73 bytes en la pila. según la wiki , cada uno de estos scripts de entrada consta de una firma y una clave pública.

el script de salida sin procesar es

76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac

que se traduce en las instrucciones

OP_DUP OP_HASH160 OP_PUSHDATA0(20 bytes) 12ab8dc588ca9d5787dde7eb29569da63c3a238c OP_EQUALVERIFY OP_CHECKSIG

Entonces, dada esta información, ¿cómo puedo extraer las direcciones de entrada (como se muestra en blockexplorer.com)? ¿Es esto posible?

1Miuw7ifaTYY5qrzKYFcTDiojSFxRfAqwP and 18KrJNtPVu6LWRNPQReqF29iFm7vDhirMk

y dirección de salida

12higDjoCCNXSA95xZMWUdPvXNmkAduhWv

Respuestas (3)

la dirección de salida se deriva únicamente del script de salida a partir del paso 4 en la wiki de la siguiente manera:

primero agregue ceros a la izquierda:

0012ab8dc588ca9d5787dde7eb29569da63c3a238c

luego hash con sha256 ( si miras en la wiki , esto es en realidad parte de la operación OP_HASH160) para dar:

e158c4be10913422dadcf1c36843020ebb3ffe9d0cb13fb9e8c0a564a53c7832

luego hash con sha256 nuevamente (el wiki está mal aquí, dice que se use ripemd160, pero en realidad se requiere sha256 nuevamente) para dar:

96bf1d277213bbcd91145138e4c7ad8dcd6e1de1c39884fcbc1f5a6d4d7aee93

luego tome los primeros 4 bytes de este resultado ( 96bf1d27) y péguelos al final de la clave pública hash160 original con ceros a la izquierda:

0012ab8dc588ca9d5787dde7eb29569da63c3a238c96bf1d27

convertir a decimal:

457790304922245030616719694560989441716273193824169172263

codificación base58 para dar:

2higDjoCCNXSA95xZMWUdPvXNmkAduhWv

y pegue un 1 delante de todo para obtener la dirección de salida de bitcoin:

12higDjoCCNXSA95xZMWUdPvXNmkAduhWv

ahora para averiguar cómo obtener las direcciones de entrada...

gracias a esta respuesta , podemos ver que ambas firmas están codificadas en el siguiente formato:

  • 0x30: un byte de encabezado que indica una estructura compuesta
  • un descriptor de longitud de 1 byte para todo lo que sigue
  • 0x02: un byte de encabezado que indica un número entero
  • un descriptor de longitud de 1 byte para el valor r
  • la coordenada r, como un entero big-endian
  • 0x02: un byte de encabezado que indica un número entero
  • un descriptor de longitud de 1 byte para el valor s
  • la coordenada s, como un entero big-endian
  • un byte de tipo hash

entonces, decodificando las firmas de script sin procesar:

493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01
  • 0x49 = OP_PUSHDATA0: inserte 73 bytes en la pila (el comando de script no forma parte del valor de la firma)
  • 0x30 = byte de encabezado
  • 0x46 = descriptor de longitud (70 bytes)
  • 0x02 = byte de encabezado
  • 0x21 = descriptor de longitud del valor r (33 bytes)
  • 00e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006bla coordenada r como un entero big endian
  • 0x02 = byte de encabezado
  • 0x21 = descriptor de longitud de valor s (33 bytes)
  • 00b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5dla coordenada s como un entero big endian
  • 0x01 = byte de tipo hash

y la segunda firma sin procesar también tiene el mismo formato:

493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01
  • 0x49 = OP_PUSHDATA0: inserte 73 bytes en la pila (el comando de script no forma parte del valor de la firma)
  • 0x30 = byte de encabezado
  • 0x46 = descriptor de longitud (70 bytes)
  • 0x02 = byte de encabezado
  • 0x21 = descriptor de longitud del valor r (33 bytes)
  • 00a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3la coordenada r como un entero big endian
  • 0x02 = byte de encabezado
  • 0x21 = descriptor de longitud de valor s (33 bytes)
  • 00911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bfla coordenada s como un entero big endian
  • 0x01 = byte de tipo hash

por lo que esto confirma que los valores de firma en las entradas de transacciones en realidad no contienen claves públicas en absoluto. las direcciones de entrada en realidad provienen de las salidas de transacciones anteriores que se pueden identificar a través del hash de entrada y el índice de entrada en el tx actual.

esto puede proporcionar un método para obtener la clave pública solo de la firma github.com/nanotube/supybot-bitcoin-marketmonitor/blob/master/…
también, esto muestra cómo se crea la firma bitcoin.stackexchange.com/a/5241/2116
Gran respuesta. Ojalá pudiera votar más.

mi solución fue que pasé la cadena hexadecimal a:

    def publicKeyDecode(pub):
            hash1 = hashlib.sha256(binascii.unhexlify(pub))
            hash2 = hashlib.new('ripemd160', hash1.digest())
            padded = (b'\x00') + hash2.digest()
            hash3 = hashlib.sha256(padded)
            hash4 = hashlib.sha256(hash3.digest())
            padded += hash4.digest()[:4]
            return base58.b58encode(padded)
tuvo que usar sha256en lugar de ripemd160para obtener la dirección correcta
Tuve que comentar la primera línea (pub = pub[2:-2]) para trabajar con la clave pública (0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352) en la wiki ( en.bitcoin.it/wiki/… )
Todo depende del propio guión. porque es un programa. así que tienes que interpretarlo por tu cuenta. La solución anterior fue una decodificación de script estándar. Alguien lo editó, por lo que no es correcto para todos los scripts.

Aquí hay una implementación de python3+ para la respuesta de @mulllhausen sobre el análisis de la dirección de Bitcoin del script P2PKH:

import binascii
import hashlib
import base58

def P2PKHToAddress(pkscript, istestnet=False):
    pub = pkscript[6:-4] # get pkhash, inbetween first 3 bytes and last 2 bytes
    p = '00' + pub # prefix with 00 if it's mainnet
    if istestnet:
        p = '6F' + pub # prefix with 0F if it's testnet
    h1 = hashlib.sha256(binascii.unhexlify(p))
    h2 = hashlib.new('sha256', h1.digest())
    h3 = h2.hexdigest()
    a = h3[0:8] # first 4 bytes
    c = p + a # add first 4 bytes to beginning of pkhash
    d = int(c, 16) # string to decimal
    b = d.to_bytes((d.bit_length() + 7) // 8, 'big') # decimal to bytes
    address = base58.b58encode(b) # bytes to base58
    if not istestnet:
        address = '1' + address # prefix with 1 if it's mainnet
    return address

print(P2PKHToAddress("76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac")) # 12higDjoCCNXSA95xZMWUdPvXNmkAduhWv