Ich versuche, einen TX mit 4 Eingängen zu erstellen und ihn über cmdline und openssl auf einem Cold-Storage-Computer zu signieren. Dann möchte ich es über Bitcoin qt (oder blockchain.info) senden. Das Signieren mit einer einzigen Eingabe und einer einzigen Ausgabe funktioniert bei mir bereits (über Unix-cmd-Zeile und OpenSSL). Jetzt möchte ich mit mehreren Eingaben arbeiten, mit ein wenig Hilfe von Stackexchange hier: Wie signiere ich eine Transaktion mit mehreren Eingaben?
Ich habe eine Transaktion mit 4 Eingaben erstellt und kann sie nicht zum Laufen bringen. Die Transaktion sieht so aus und wird korrekt in bitcoin qt (decoderawtransaction) oder mit https://blockchain.info/de/decode-tx dekodiert :
0100000004b0772e6ef46c2d3c60418bb7d5c2c015d6b943e5fca07570eb82c26dc7c9d248010000006B483045022100D675D9F98E5B1F01BDB05E5389ACB453EFA14EF399361099736376611D9BF88E02206B8FEF37F2C2316D3629D6C43945AFA23B0EB0CA2C1163E33B28066B01A4E241012103cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0ffffffff74fb6858c31a292d20c9744187032bddb7ddea02a3aa3ef523c8524a21481881010000006A47304402200F921996446FBAD78ECB6C95303ECD13145CA7E13E769B44742FA499325B347402202F8378D7D154F4F8D345525696F8E31DF8A96C05AA58B2F53012E3550CC90AE7012103cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0ffffffffcc21e36eedb509c660681c1e949dd294bd4c11692439221004c2235d565b74bb000000006A47304402206B7C2D73EC787ADD99740DAB78F7252ED49A1BA42BA358A667BF118B8740BB0C0220366EF47DE6339C261946513C939A301ECF940A294036ED72A5FD893C5CAFEED8012103cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0ffffffffea919487e04ed509d6cb9c7297c277b9be3a68f3836c7d86df378714a75949e8000000006A47304402205B595472AA821D96DBFB6E531A663571A9DB14DDFCF8AC0B4330B6264955C15F02203FDF004B19996654490F00FA9BDFC175265CF95BA6DC86943B4B7C50EAF23616012103cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0ffffffff0120830c00000000001976a91418ec49b27624086a2b6f35f263d951d25dbe24b688ac00000000
Das Hochladen mit Bitcoin qt (sendrawtransaction) gibt diesen Fehler:
16: Mandatory-Script-Verify-Flag-Failed (Signatur muss Null sein für fehlgeschlagene CHECK(MULTI)SIG-Operation) (Code -26)
Welche Möglichkeiten habe ich, um die nächsten Schritte herauszufinden, wenn es schief geht?
Dies hat mir geholfen, es für eine einzelne Eingabetransaktion zum Laufen zu bringen: Verifizieren eines Bitcoin-Trx auf der Unix-cmd-Zeile mit OpenSSL?
Jetzt habe ich vier Eingänge und komprimierte Pubkeys. Ich habe den obigen TX genau wieder in Electrum erstellt (gleiche 4 Eingänge, gleicher Einzelausgang), signiert. Habe es aber nicht verschickt. Dann habe ich Electrum generiert und meinen generierten tx dekodiert und Zeile für Zeile überprüft, dass es keine Unterschiede in den Werten gibt (außer den Signaturzeilen unterscheiden sie sich natürlich). Danach habe ich eine Textdatei mit Befehlen erstellt, die für jede Eingabe den Pubkey, den Hash (double sha256) und die Signatur ausspuckt. Auf diese Weise könnte ich Signaturen mit openssl auf diese Weise überprüfen:
openssl pkeyutl <tx_hash.hex -verify -pubin -inkey pubkey.pem -sigfile tx_sig.hex
Wenn ich jede Signatur in der Transaktion prüfe, bekomme ich immer eine Erfolgsmeldung von OpenSSL (die komplette Datei ist am Ende unten angehängt). Wenn ich es jedoch per Bitcoin qt sende, bekomme ich die oben genannte Fehlermeldung. Die Fehlermeldung kommt von "the bitcoin network"... Wie kann ich es emulieren?
Um eine tx zu bestätigen, wird eine Prüfung von dem tx-Eingabe-SigScript und dem vorherigen tx-Ausgabe-PKScript ausgeführt. Also habe ich das Ausgabeskript der vorherigen Transaktion (für jede Eingabe) doppelt überprüft. Sie sind alle gleich:
OP_DUP OP_HASH160 c2df275d78e506e17691fd6f0c63c43d15c897fc OP_EQUALVERIFY OP_CHECKSIG
Meine Prüfaktivitäten würden wie folgt aussehen: Ich lege SIG und PUBKEY aus dem tx-Eingabe-SigScript auf einen virtuellen Stack und lasse dann das PKScript Schritt für Schritt für alle Eingaben dagegen laufen. Hier ein Beispiel für die erste Eingabe (mehr oder weniger die Stack-Emulationsschritte):
step action result
1 SIGSCRIPT SIGNATURE 3045022100D675D9F98E5B1F . . . B28066B01A4E241
2 SIGSCRIPT PUBKEY 03cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0
3 OP_DUP PUBKEY 03cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0
4 OP_HASH160 xxd -r -p <PUBKEY.txt >pubkey.hex
openssl dgst -binary -sha256 <pubkey.hex >pk_sha256.hex
openssl dgst -binary -ripemd160 <pk_sha256.hex >pkhash.hex
xxd -ps pkhash.hex
c2df275d78e506e17691fd6f0c63c43d15c897fc
5 PKSCRIPT PKH c2df275d78e506e17691fd6f0c63c43d15c897fc
6 OP_EQUALVERIFY YES !
Hier habe ich für alle 4 Inputs den gleichen PUBKEY_HASH generiert, damit OP_Equalverify korrekt laufen sollte. Auf dem Stack verbleibt:
1 Input SIGNATURE 3045022100D675D9F98E5B1F . . . B28066B01A4E241
2 Input PUBKEY 03cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0
3 OP_CHECKSIG
Ich weiß nicht, was hier im Netzwerk passiert, ich würde gerne glauben, dass es die Transaktion in ihre Elemente (pro Eingabe) dekodiert, einen Hash darüber erstellt und etwas Ähnliches tut wie ich (natürlich mit anderen Bibliotheken). ): UNTERSCHRIFT ÜBERPRÜFEN. Ich habe es so gemacht:
openssl pkeyutl <tx_hash.hex -verify -pubin -inkey pubkey.pem -sigfile tx_sig.hex
Gibt es eine Möglichkeit, eine spezifischere Fehlermeldung zu erhalten, wenn eine "falsche" Transaktion gesendet wird? "mandatory-script-verify-flag-failed" und "(code -26)" helfen mir nicht weiter zu debuggen ...
Hier ist die Datei, die aus dem Transaktionsprozess generiert wurde und hilft, die Signatur für jede Eingabe zu überprüfen:
##############################################
### Bitcoin prep file to verify signatures ###
##############################################
# Bitcoin (and here with openssl) works only on binary files. For each input, convert to binary.
# the pubkey for above example:
echo 3036301006072a8648ce3d020106052b8104000a032200 > pubkey.txt
echo 03cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0 >> pubkey.txt
xxd -r -p <pubkey.txt | openssl pkey -pubin -inform der >pubkey.pem
# TX_IN[0], double sha256 and signature:
echo afc7f91ceb9754ebb644d058334817babf8414d1ce75fd0683ad172e950348c9 > tx_hash.txt
echo 3045022100d675d9f98e5b1f01bdb05e5389acb453efa14ef399361099736376611d9bf88e02206b8fef37f2c2316d3629d6c43945afa23b0eb0ca2c1163e33b28066b01a4e241 > tx_sig.txt
xxd -r -p <tx_hash.txt >tx_hash.hex
xxd -r -p <tx_sig.txt >tx_sig.hex
openssl pkeyutl <tx_hash.hex -verify -pubin -inkey pubkey.pem -sigfile tx_sig.hex
# TX_IN[1], double sha256 and signature:
echo 11ded58d693d72a23b6191c20222b20ee4947bac63c34d1ccdac07461486a3b0 > tx_hash.txt
echo 304402200f921996446fbad78ecb6c95303ecd13145ca7e13e769b44742fa499325b347402202f8378d7d154f4f8d345525696f8e31df8a96c05aa58b2f53012e3550cc90ae7 > tx_sig.txt
xxd -r -p <tx_hash.txt >tx_hash.hex
xxd -r -p <tx_sig.txt >tx_sig.hex
openssl pkeyutl <tx_hash.hex -verify -pubin -inkey pubkey.pem -sigfile tx_sig.hex
# TX_IN[2], double sha256 and signature:
echo 12f904b9d0b37c368d24d132aaff2d2fe47fd9a5e3083a501e63410c6d4671ea > tx_hash.txt
echo 304402206b7c2d73ec787add99740dab78f7252ed49a1ba42ba358a667bf118b8740bb0c0220366ef47de6339c261946513c939a301ecf940a294036ed72a5fd893c5cafeed8 > tx_sig.txt
xxd -r -p <tx_hash.txt >tx_hash.hex
xxd -r -p <tx_sig.txt >tx_sig.hex
openssl pkeyutl <tx_hash.hex -verify -pubin -inkey pubkey.pem -sigfile tx_sig.hex
# TX_IN[3], double sha256 and signature:
echo 183b7652c2785d57483c5f70575e027f513743aad01100828d9eb4aeb48ea4ed > tx_hash.txt
echo 304402205b595472aa821d96dbfb6e531a663571a9db14ddfcf8ac0b4330b6264955c15f02203fdf004b19996654490f00fa9bdfc175265cf95ba6dc86943b4b7c50eaf23616 > tx_sig.txt
xxd -r -p <tx_hash.txt >tx_hash.hex
xxd -r -p <tx_sig.txt >tx_sig.hex
openssl pkeyutl <tx_hash.hex -verify -pubin -inkey pubkey.pem -sigfile tx_sig.hex
Der gesamte Code für dieses Beispiel zum Erstellen/Signieren ist hier: https://github.com/pebwindkraft/trx_cl_suite Die drei Befehle zum Erstellen, Signieren und Decodieren eines Trx sind:
./tcls_create.sh -v -f svn_4inputs.txt 820000 13GnHB51piDBf1avocPL7tSKLugK4F7U2B 33
./tcls_sign.sh -v -f tmp_c_urtx.txt -w Kxyz...your_priv_key_in_WIF_format...abc -p 03cc5debc62369bd861900b167bc6add5f1a6249bdab4146d5ce698879988dced0
./tcls_tx2txt.sh -vv -r 0100000004b0772e6ef46c2d3c60...b6f35f263d951d25dbe24b688ac00000000
Ich habe einen Fehler in diesen Shell-Skripten gefunden, obwohl ich nicht sicher bin, ob es der einzige ist. Einmal behoben, generiert es jetzt die gleichen Sha256ds der unsignierten TXs wie ein anderes Tool, das ich ausprobiert habe (vorher nicht).
Wenn Sie hier nachsehen , werden Sie sehen, dass die scriptSig des txin richtig auf den scriptPubKey des zu signierenden UTXO gesetzt wird, aber für die scriptPubKeys, die ausgeblendet werden sollten, gibt das Skript nichts aus – es sollte ein leeres Zeichen ausgeben string wie diese else-Klausel:
if [ $i -eq $j ] ; then
printf ${TX_IN_ScriptBytes_hex[$i]} >> $utxhex_tmp_fn
printf ${TX_IN_Sig_Script[$i]} >> $utxhex_tmp_fn
else
printf 00 >> $utxhex_tmp_fn
fi
Wie gesagt, ich habe den Rest der Skripte nicht überprüft, aber hoffentlich bringt Sie das einen Schritt näher.
Jonas Schnelli
pebwindkraft
pebwindkraft