Erstellen einer signierten Bitcoin-Transaktion in Java

Ich habe versucht, meinen eigenen Raw-Transaktionsgenerator in Java zu bauen, den ich dann im Testnet-Netzwerk übertragen kann. Das Problem ist, wenn ich versuche, die Transaktion zu übertragen, sagt es, dass es einen Fehler im Einlösungsskript gibt, den ich nicht verstehe.

Hier ist ein Beispiel für eine Testnet-Transaktion:

0100000001e468833270cf713f3bbccc62b7b5b0fc0b0a4570608718530816795a6589f322000000008a473044022051646b77924f6bb7c411c5aa890110ab55db8812b8998fe24c8bdce39795ebd602200bc4de18fd5524ad8b946ee57604424e2b943ef2a14fc7199a7853dda0743cbe014104b97c679207532e0f4ee2515aedaba5f87700bbe0138f7457baa58e89a53153823ab29632e6c3c804ecaab5913656512339792479a1b898b7e5dc31f075ff8660ffffffff0176df1710000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac00000000

Das Skript, das ich versuche zu entsperren:

76a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac

Mit dem Redemption-Skript:

473044022051646b77924f6bb7c411c5aa890110ab55db8812b8998fe24c8bdce39795ebd602200bc4de18fd5524ad8b946ee57604424e2b943ef2a14fc7199a7853dda0743cbe014104b97c679207532e0f4ee2515aedaba5f87700bbe0138f7457baa58e89a53153823ab29632e6c3c804ecaab5913656512339792479a1b898b7e5dc31f075ff8660

Dies ist der Java-Code zum Signieren des umgekehrten doppelten sha256-Hashs:

  public static byte[] sign(byte[] hash, BigInteger priv){

        ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
        signer.init(true, new ECPrivateKeyParameters(priv, domain));

        BigInteger[] signature = signer.generateSignature(hash);
        ByteArrayOutputStream s = new ByteArrayOutputStream();

        try {
            DERSequenceGenerator seq = new DERSequenceGenerator(s);
            seq.addObject(new ASN1Integer(signature[0]));
            seq.addObject(new ASN1Integer(signature[1]));
            seq.close();
            return s.toByteArray();
        }
        catch(IOException e){
            return null;
        }
    }

Was ist falsch?

Sowohl die Transaktionen als auch die Skripte scheinen in Ordnung zu sein. Können Sie den Fehler, den Sie erhalten, genauer beschreiben? Haben Sie versucht, die Transaktion über andere Quellen wie Online-APIs zu übertragen? Es kann an der Übertragung selbst statt an der Transaktionskorrektheit liegen.
Ich habe versucht, die Transaktion mit beiden Blockcypern zu übertragen , was mir den Fehler gibt: "Fehler beim Senden der Transaktion: Fehler beim Ausführen des Skripts für die Eingabe 0, auf 22f389655a7916085318876070450a0bfcb0b5b762ccbc3b3f71cf70328368e4 bei 0: Skript wurde NICHT erfolgreich verifiziert." Ich habe auch versucht, den Blockexplorer zu verwenden , der mir gibt der Fehler "16: Mandatory-Script-Verify-Flag-Failed (Skript ohne Fehler ausgewertet, aber mit einem falschen/leeren obersten Stack-Element beendet). Code:-26".
Okay, jetzt verstehe ich. Es scheint, dass die Validierung fehlschlägt, da die Signatur nicht korrekt ist. Die Skriptauswertung schlägt in OP_CHECKSIG fehl, kurz nachdem überprüft wurde, ob das im vorherigen tx scriptPubKey bereitgestellte ripmd160 mit dem in ScriptSig bereitgestellten ripemd160 des öffentlichen Schlüssels übereinstimmt.
Ich verstehe aber nicht, warum das so ist. Beim Signieren platziere ich das Entsperrskript aus der Transaktion, die ich ausgeben möchte, wo die Signatur platziert wird, und hänge auch einen Hashcode-Typ an. Schließlich hash ich die Transaktion zweimal, mache den Hash rückgängig, bevor ich ihn schließlich signiere. Ist das richtig?
Sie sollten die gesamte Transaktion zweimal sha256, signieren und dann den Hashtyp anhängen. Hier ist ziemlich gut erklärt (ab Schritt 13) bitcoin.stackexchange.com/questions/3374/…

Antworten (1)

Schnelles Entschlüsseln des TX:

 VERSION      01000000
 TX_IN COUNT  hex=01, decimal=1
 TX_IN[0]
  TX_IN[0]    OutPoint hash 22F389655A7916085318876070450A0BFCB0B5B762CCBC3B3F71CF70328368E4 
  TX_IN[0]    OutPoint index hex=00000000, reversed=00000000, decimal=0
  TX_IN[0]    Script Length hex=8A, decimal=138
  TX_IN[0]    Script Sig  473044022051646B77924F6BB7C411C5AA890110AB55DB8812B8998FE24C8BDCE39795EBD602200BC4DE18FD5524AD8B946EE57604424E2B943EF2A14FC7199A7853DDA0743CBE014104B97C679207532E0F4EE2515AEDABA5F87700BBE0138F7457BAA58E89A53153823AB29632E6C3C804ECAAB5913656512339792479A1B898B7E5DC31F075FF8660
        47: OP_DATA_0x47:     push hex 47 (decimal 71) bytes as data
        30: OP_SEQUENCE_0x30: type tag indicating SEQUENCE, begin sigscript
        44: OP_LENGTH_0x44:   length of R + S
        02: OP_INT_0x02:      type tag indicating INTEGER
        20: OP_LENGTH_0x20:   this is SIG R
            51646B77924F6BB7:C411C5AA890110AB:55DB8812B8998FE2:4C8BDCE39795EBD6
        02: OP_S_INT_0x02
        20: OP_LENGTH_0x20:   this is SIG S
            0BC4DE18FD5524AD:8B946EE57604424E:2B943EF2A14FC719:9A7853DDA0743CBE
        01: OP_SIGHASHALL:    this terminates the ECDSA signature (ASN1-DER structure)
        Minimum and maximum size constraints                        - ok
        scriptsig always starts with 0x30                           - ok
        length 136 chars is less than actual sig length (140 chars) - ok
               (hex 0x44, decimal 68, 136 chars)
        length of R coordinate (64) >= 0                            - ok
        length of S coordinate (64) >= 0                            - ok
        S-Value is within scriptsig boundaries                      - ok
        Make sure the R & S length covers the entire signature      - ok
        S-value must be smaller than N/2                            - ok
        strictly check DER-encoded signature                        - ok
        41: OP_DATA_0x41:     push hex 41 (decimal 65) bytes as data
        04: OP_LENGTH_0X04
            B97C679207532E0F:4EE2515AEDABA5F8:7700BBE0138F7457:BAA58E89A5315382
            3AB29632E6C3C804:ECAAB59136565123:39792479A1B898B7:E5DC31F075FF8660
        * This terminates the Public Key, corresponding bitcoin address is:    mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am 
 TX_IN[0] Sequence FFFFFFFF

TX_OUT COUNT, hex=01, decimal=1
 TX_OUT[0] Value hex=76DF171000000000, rev_hex=000000001017DF76, dec=269999990 
 TX_OUT[0] PK_Script Length hex=19, dec=25 
 TX_OUT[0] pk_script 76A91448DDFD3891F3F422D5C3C9C25E35B382667FC6E688AC
        76: OP_DUP
        A9: OP_HASH160
        14: OP_Data14 (= decimal 20)
            48DDFD3891F3F422:D5C3C9C25E35B382
            667FC6E6
        88: OP_EQUALVERIFY
        AC: OP_CHECKSIG   This is a P2PKH script and translates base58 encoded into this bitcoin address:    mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am 
 LOCK_TIME 00000000

Die Transaktion ist also korrekt und die Signatur ist korrekt zusammengesetzt. Es folgt auch den "strengen Sig-Check"-Regeln. Der TX versucht, von mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am zu mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am auszugeben. Also habe ich die Signatur gegen den doppelten Hash des tx geprüft (siehe den berühmten Pizza-Transaktionsdurchlauf: Wie funktioniert der ECDSA-Verifizierungsalgorithmus während der Transaktion? ):

Die raw_tx.txt ist:

0100000001e468833270cf713f3bbccc62b7b5b0fc0b0a4570608718530816795a6589f322000000008a473044022051646b77924f6bb7c411c5aa890110ab55db8812b8998fe24c8bdce39795ebd602200bc4de18fd5524ad8b946ee57604424e2b943ef2a14fc7199a7853dda0743cbe014104b97c679207532e0f4ee2515aedaba5f87700bbe0138f7457baa58e89a53153823ab29632e6c3c804ecaab5913656512339792479a1b898b7e5dc31f075ff8660ffffffff0176df1710000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac00000000

sig entfernt und Ihr Pubkey-Skript in raw_tx_SIGHASH_ALL.txt eingegeben:

0100000001e468833270cf713f3bbccc62b7b5b0fc0b0a4570608718530816795a6589f322000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688acffffffff0176df1710000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac0000000001000000

und doppelter Hash (die Binärwerte, daher zuerst eine Konvertierung!)

  result=$( cat raw_tx_SIGHASH_ALL.txt | sed 's/[[:xdigit:]]\{2\}/\\x&/g' )
  printf $result > raw_tx.hex
  hexdump -C raw_tx.hex 
  openssl dgst -binary -sha256 <raw_tx.hex >ssha256.hex
  openssl dgst -binary -sha256 <ssha256.hex >dsha256.hex
  hexdump -C dsha256.hex 

Der dsha256 ist also in lesbarer Form: 6b37475a5388fb52f227817a0ddec00e7b69495b492cd7cdc6aff2afc44810e4

Ich verwende openssl, um die Double-Hash-Hex-Datei (dsha256.hex) mit der Signatur und einem „pem“-Schlüssel zu überprüfen (muss Pubkey von Hex in Pem konvertieren), ich erhalte immer eine Fehlermeldung:

openssl pkeyutl -verify -pubin -inkey pubkey.pem -sigfile tmp_sig.hex -in dsha256.hex

Beim Durchlaufen des Pizza-Beispiels wird eine "Signatur erfolgreich verifiziert" zurückgegeben.

Es ist etwas verwirrend, dass Sie die Elemente der DER-codierten Signatur als "Opcodes" und auf derselben Ebene wie der Rest der scriptSig schreiben. Aus der Sicht von Bitcoin ist diese gesamte Signatur ein Black-Box-Array von Bytes, keine Folge von Opcodes (OP_SEQUENCE bis OP_SIGHASH).