Analysieren von Bitcoin-Eingabe- und Ausgabeadressen aus Skripten

kann mich jemand durch den Prozess des Kombinierens von Skripteingaben und -ausgaben führen, um die base58-codierten Eingabe- und Ausgabeadressen anzuzeigen. nehmen Sie zum Beispiel Block 728 . Dies hat zwei rohe Skripteingaben:

493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01

and

493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01

das jeweils erste Byte (49 hex = 73 dec) ist die Anweisung, 73 Bytes auf den Stack zu schieben. Laut Wiki besteht jedes dieser Eingabeskripte aus einer Signatur und einem öffentlichen Schlüssel.

das Rohausgabeskript ist

76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac

was sich in die Anleitung übersetzt

OP_DUP OP_HASH160 OP_PUSHDATA0(20 bytes) 12ab8dc588ca9d5787dde7eb29569da63c3a238c OP_EQUALVERIFY OP_CHECKSIG

Wie kann ich angesichts dieser Informationen Eingabeadressen extrahieren (wie in blockexplorer.com gezeigt)? ist das überhaupt möglich?

1Miuw7ifaTYY5qrzKYFcTDiojSFxRfAqwP and 18KrJNtPVu6LWRNPQReqF29iFm7vDhirMk

und Ausgangsadresse

12higDjoCCNXSA95xZMWUdPvXNmkAduhWv

Antworten (3)

Die Ausgabeadresse wird ausschließlich aus dem Ausgabeskript ab Schritt 4 im Wiki wie folgt abgeleitet:

Zuerst führende Nullen hinzufügen:

0012ab8dc588ca9d5787dde7eb29569da63c3a238c

dann Hash mit sha256 ( wenn man im Wiki nachschaut ist das eigentlich Teil der Operation OP_HASH160) zu geben:

e158c4be10913422dadcf1c36843020ebb3ffe9d0cb13fb9e8c0a564a53c7832

dann wieder mit sha256 gehasht (das Wiki ist hier falsch - es sagt, dass reifemd160 verwendet werden soll, aber tatsächlich wird wieder sha256 benötigt), um Folgendes zu geben:

96bf1d277213bbcd91145138e4c7ad8dcd6e1de1c39884fcbc1f5a6d4d7aee93

Nehmen Sie dann die ersten 4 Bytes dieses Ergebnisses ( 96bf1d27) und kleben Sie sie mit führenden Nullen an das Ende des ursprünglichen öffentlichen Hash160-Schlüssels:

0012ab8dc588ca9d5787dde7eb29569da63c3a238c96bf1d27

in dezimal umwandeln:

457790304922245030616719694560989441716273193824169172263

base58-Kodierung zu geben:

2higDjoCCNXSA95xZMWUdPvXNmkAduhWv

und kleben Sie eine 1 davor, um die Bitcoin-Ausgabeadresse zu erhalten:

12higDjoCCNXSA95xZMWUdPvXNmkAduhWv

jetzt um herauszufinden, wie man die Eingabeadressen bekommt ...

Dank dieser Antwort können wir sehen, dass beide Signaturen im folgenden Format codiert sind:

  • 0x30: ein Header-Byte, das eine zusammengesetzte Struktur anzeigt
  • ein 1-Byte-Längendeskriptor für alles, was folgt
  • 0x02: ein Header-Byte, das eine ganze Zahl angibt
  • ein 1-Byte-Längendeskriptor für den r-Wert
  • die r-Koordinate als Big-Endian-Ganzzahl
  • 0x02: ein Header-Byte, das eine ganze Zahl angibt
  • ein 1-Byte-Längendeskriptor für den s-Wert
  • die s-Koordinate als Big-Endian-Ganzzahl
  • ein Hashtyp-Byte

Entschlüsseln Sie also die Rohskriptsignaturen:

493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01
  • 0x49 = OP_PUSHDATA0 - schiebe 73 Bytes auf den Stapel (Skriptbefehl nicht Teil des Signaturwerts)
  • 0x30 = Kopfbyte
  • 0x46 = Längendeskriptor (70 Byte)
  • 0x02 = Kopfbyte
  • 0x21 = r-Wert-Längendeskriptor (33 Bytes)
  • 00e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006bdie r-Koordinate als Big-Endian-Ganzzahl
  • 0x02 = Kopfbyte
  • 0x21 = Längendeskriptor für s-Wert (33 Bytes)
  • 00b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5ddie s-Koordinate als Big-Endian-Ganzzahl
  • 0x01 = Hashtyp-Byte

und die zweite Rohsignatur hat auch das gleiche Format:

493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01
  • 0x49 = OP_PUSHDATA0 - schiebe 73 Bytes auf den Stapel (Skriptbefehl nicht Teil des Signaturwerts)
  • 0x30 = Kopfbyte
  • 0x46 = Längendeskriptor (70 Byte)
  • 0x02 = Kopfbyte
  • 0x21 = r-Wert-Längendeskriptor (33 Bytes)
  • 00a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3die r-Koordinate als Big-Endian-Ganzzahl
  • 0x02 = Kopfbyte
  • 0x21 = Längendeskriptor für s-Wert (33 Bytes)
  • 00911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bfdie s-Koordinate als Big-Endian-Ganzzahl
  • 0x01 = Hashtyp-Byte

dies bestätigt also, dass die Signaturwerte in den Transaktionseingaben tatsächlich überhaupt keine öffentlichen Schlüssel enthalten. Die Eingabeadressen stammen tatsächlich aus den vorherigen Transaktionsausgaben, die durch den Eingabe-Hash und den Eingabeindex im aktuellen TX identifiziert werden können.

Dies kann eine Methode bieten, um den öffentlichen Schlüssel allein aus der Signatur zu erhalten github.com/nanotube/supybot-bitcoin-marketmonitor/blob/master/…
Außerdem zeigt dies, wie die Signatur erstellt wird bitcoin.stackexchange.com/a/5241/2116
Gute Antwort. Ich wünschte, ich könnte mehr abstimmen.

Meine Lösung war, dass ich den Hex-String übergeben habe an:

    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)
musste sha256statt verwenden ripemd160, um die richtige Adresse zu erhalten
Musste die erste Zeile (pub = pub[2:-2]) auskommentieren, um mit dem öffentlichen Schlüssel (0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352) im Wiki ( en.bitcoin.it/wiki/… ) zu arbeiten.
Alles hängt vom Skript selbst ab. weil es ein Programm ist. also musst du es selbst interpretieren. Die obige Lösung war eine Standardskriptdecodierung. Jemand hat es bearbeitet, also ist es nicht für alle Skripte korrekt.

Hier ist eine Python3+-Implementierung für die Antwort von @mulllhausen zum Parsen der Bitcoin-Adresse aus dem P2PKH-Skript:

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