Bei einem rohen Standard-Tx ( Wiki ):
01000000
01
26c07ece0bce7cda0ccd14d99e205f118cde27e83dd75da7b141fe487b5528fb
00000000
8b
48304502202b7e37831273d74c8b5b1956c23e79acd660635a8d1063d413c50b218eb6bc8a022100a10a3a7b5aaa0f07827207daf81f718f51eeac96695cf1ef9f2020f21a0de02f01410452684bce6797a0a50d028e9632be0c2a7e5031b710972c2a3285520fb29fcd4ecfb5fc2bf86a1e7578e4f8a305eeb341d1c6fc0173e5837e2d3c7b178aade078
ffffffff
02
b06c191e01000000
19
76a9143564a74f9ddb4372301c49154605573d7d1a88fe88ac
00e1f50500000000
19
76a914010966776006953d5567439e5e39f86a0d273bee88ac
00000000
und ein privater Schlüssel:
18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
Wie konstruiert man eine neue Transaktion, um die Münze aus der zweiten Ausgabe einzulösen? Ich habe lange versucht, dies anhand des Diagramms von etotheipi herauszufinden , kann aber anscheinend nicht verstehen, wie eine ordnungsgemäße Transaktion erstellt werden soll. Eine Schritt-für-Schritt-Anleitung wäre wünschenswert.
In dieser Antwort werde ich die Schritte durchgehen, die zum Einlösen der zweiten Ausgabe der oben aufgeführten Transaktion erforderlich sind. Die Antwort beschränkt sich auf das Einlösen einer Ausgabe des bestimmten Typs, der in dieser Transaktion vorhanden ist (eine Ausgabe, die die Bereitstellung einer neuen Transaktion erfordert, die mit einem privaten Schlüssel signiert ist, dessen entsprechender öffentlicher Schlüssel mit dem Hash im Skript der betreffenden Ausgabe gehasht wird). Diese Antwort ist schon ziemlich lang, auch ohne Berücksichtigung anderer Ausgabetypen.
Kurze Zusammenfassung: Wir beginnen mit dem Aufbau einer neuen Transaktion mit einer scriptSig, die den scriptPubKey der Ausgabe enthält, die wir einlösen möchten. Der scriptPubKey dieser Transaktion enthält ein Skript, das an einen Hash eines öffentlichen Schlüssels (Bitcoin-Adresse) zahlt. Wir führen für diese Transaktion einen doppelten SHA256-Hash durch, wobei am Ende der 4-Byte-Hashcodetyp SIGHASH_ALL angehängt wird. Wir signieren diesen Hash mit dem oben angegebenen privaten Schlüssel. Die scriptSig dieser neuen Transaktion wird dann durch ein Skript ersetzt, das zuerst die DER-codierte Signatur plus den Ein-Byte-Hashcodetyp SIGHASH_ALL auf den Stack schiebt, gefolgt von dem entsprechenden öffentlichen Schlüssel des DER-codierten privaten Schlüssels.
Schritt-für-Schritt-Beschreibung:
Wir beginnen mit der Erstellung einer neuen Rohtransaktion, die wir hashen und signieren.
01000000
01
eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2
01000000
19
76a914010966776006953d5567439e5e39f86a0d273bee88ac
ffffffff
01
605af40500000000
19
76a914097072524438d003d23a2f23edb65aae1bb3e46988ac
00000000
Und zum Schluss schreiben wir einen vier Byte langen „Hash-Code-Typ“ (in unserem Fall 1):01000000
Wir haben jetzt die folgenden rohen Transaktionsdaten:
01000000
01
eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2
01000000
19
76a914010966776006953d5567439e5e39f86a0d273bee88ac
ffffffff
01
605af40500000000
19
76a914097072524438d003d23a2f23edb65aae1bb3e46988ac
00000000
01000000
(Signierungsphase) Jetzt hashen wir diese gesamte Struktur doppelt mit SHA256, was den Hash ergibt9302bda273a887cb40c13e02a50b4071a31fd3aae3ae04021b0b843dd61ad18e
30460221009e0339f72c793a89e664a8a932df073962a3f84eda0bd9e02084a6a9567f75aa022100bd9cbaca2e5ec195751efdfac164b76250b1e21302e51ca86dd7ebd7020cdc06
An diese Signatur hängen wir den Ein-Byte-Hash-Codetyp an: 01
. Der öffentliche Schlüssel lautet:0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6
Wir konstruieren das endgültige scriptSig durch Verketten:
Wir ersetzen dann das Ein-Byte-Variant-Längenfeld aus Schritt 5 durch die Länge der Daten aus Schritt 16. Die Länge beträgt 140 Bytes oder 0x8C-Bytes:8c
4930460221009e0339f72c793a89e664a8a932df073962a3f84eda0bd9e02084a6a9567f75aa022100bd9cbaca2e5ec195751efdfac164b76250b1e21302e51ca86dd7ebd7020cdc0601410450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6
Zum Schluss entfernen wir den 4-Byte-Hashcodetyp, den wir in Schritt 13 hinzugefügt haben, und erhalten am Ende den folgenden Bytestrom, der die letzte Transaktion darstellt:
01000000
01
eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2
01000000
8c
4930460221009e0339f72c793a89e664a8a932df073962a3f84eda0bd9e02084a6a9567f75aa022100bd9cbaca2e5ec195751efdfac164b76250b1e21302e51ca86dd7ebd7020cdc0601410450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6
ffffffff
01
605af40500000000
19
76a914097072524438d003d23a2f23edb65aae1bb3e46988ac
00000000
Python-Beispielcode:
Ich habe ein Beispiel-Python-Skript erstellt, das alle oben genannten Aufgaben erfüllt. Es ist absichtlich so ausführlich wie möglich und stark kommentiert, mit so wenigen Funktionen wie möglich, um der obigen Schritt-für-Schritt-Anleitung zu ähneln. Die Anzahl der Codezeilen kann leicht auf die Hälfte reduziert werden, aber ich entscheide mich dafür, es in diesem ausführlichen Format zu posten, da ich beurteile, dass es am einfachsten zu befolgen ist (dh kein Hin- und Herspringen durch Funktionen). Das Skript enthält 76 nicht leere Zeilen ohne Kommentar. Das Skript hängt von bitcointools (zum Serialisieren und Deserialisieren von Transaktionen und base58-Codierung/Decodierung) und ecdsa_ssl.py abaus meinem Fork von Jorics Brutus-Repository (zum Erstellen öffentlicher/privater EC-Schlüsselpaare und ECDSA-Signierung). Der einfachste Weg, das Skript zum Ausführen zu bringen, besteht darin, bitcointools in einen Ordner zu klonen und ecdsa_ssl.py von der obigen URL zusammen mit diesem Skript in denselben Ordner zu legen und das Skript von dort aus auszuführen. Sie sollten die Adresse in der SEND_TO_ADDRESS
Variablen in diesem Skript durch die Adresse ersetzen, an die die Münzen gesendet werden sollen, es sei denn, Sie fühlen sich großzügig :).
#bitcointools von deserialisieren import parse_Transaction, opcodes aus BCDataStream importieren BCDataStream aus base58 import bc_address_to_hash_160, b58decode, public_key_to_bc_address, hash_160_to_bc_address ecdsa_ssl importieren Importieren Sie Crypto.Hash.SHA256 als sha256 Importieren Sie Crypto.Random #transaktion, von der wir eine Ausgabe einlösen wollen HEX_TRANSACTION="010000000126c07ece0bce7cda0ccd14d99e205f118cde27e83dd75da7b141fe487b5528fb000000008b48304502202b7e37831273d74c8b5b1956c23e79acd660635a8d1063d413c50b218eb6bc8a022100a10a3a7b5aaa0f07827207daf81f718f51eeac96695cf1ef9f2020f21a0de02f01410452684bce6797a0a50d028e9632be0c2a7e5031b710972c2a3285520fb29fcd4ecfb5fc2bf86a1e7578e4f8a305eeb341d1c6fc0173e5837e2d3c7b178aade078ffffffff02b06c191e010000001976a9143564a74f9ddb4372301c49154605573d7d1a88fe88ac00e1f505000000001976a914010966776006953d5567439e5e39f86a0d273bee88ac00000000" #Ausgabe zum Einlösen. muss in HEX_TRANSACTION vorhanden sein AUSGABE_INDEX=1 #Adresse an die wir die eingelösten Coins senden wollen. #ERSETZEN SIE DURCH IHRE EIGENE ADRESSE, es sei denn, Sie sind großzügig SEND_TO_ADDRESS="1L4xtXCdJNiYnyqE6UsB8KSJvqEuXjz6aK" #Gebühr, die wir zahlen möchten (in BTC) TX_GEBÜHR=0,001 #Konstante, die die Anzahl der Satoshis pro BTC definiert MÜNZE = 100000000 #constant wird verwendet, um zu bestimmen, welcher Teil der Transaktion gehasht wird. SIGHASH_ALL=1 #Privater Schlüssel, dessen öffentlicher Schlüssel mit dem Hash gehasht wird, der in scriptPubKey der Ausgabenummer *OUTPUT_INDEX* in der in HEX_TRANSACTION beschriebenen Transaktion enthalten ist PRIVATE_KEY=0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 def dsha256 (Daten): Rückgabe sha256.new(sha256.new(data).digest()).digest() tx_data=HEX_TRANSACTION.decode('hex_codec') tx_hash=dsha256(tx_data) #hier verwenden wir bitcointools, um eine Transaktion zu parsen. Dies ermöglicht einen einfachen Zugriff auf die verschiedenen Felder der Transaktion, aus der wir eine Ausgabe einlösen möchten stream = BCDataStream() stream.write(tx_data) tx_info = parse_Transaction(stream) if len(tx_info['txOut']) < (OUTPUT_INDEX+1): heben Sie RuntimeError auf, "es gibt nur %d Ausgabe(n) in der Transaktion, von der Sie versuchen einzulösen. Sie möchten den Ausgabeindex %d einlösen" % (len(tx_info['txOut']), OUTPUT_INDEX) #dieses Wörterbuch wird verwendet, um die Werte der verschiedenen Transaktionsfelder zu speichern # Dies ist nützlich, da wir eine Transaktion zum Hashen und Signieren erstellen müssen # und eine weitere, die die letzte Transaktion sein wird tx_fields = {} ##Hier beginnen wir mit der Erstellung der Transaktion, die wir hashen und signieren sign_tx = BCDataStream() ##Zuerst schreiben wir die Versionsnummer, die 1 ist tx_fields['Version'] = 1 sign_tx.write_int32(tx_fields['Version']) ## dann schreiben wir die Anzahl der Transaktionseingaben, die eins ist tx_fields['num_txin'] = 1 sign_tx.write_compact_size(tx_fields['num_txin']) ##dann schreiben wir die eigentlichen Transaktionsdaten #'prevout_hash' tx_fields['prevout_hash'] = tx_hash sign_tx.write(tx_fields['prevout_hash']) #Hash der Transaktion, von der wir eine Ausgabe einlösen möchten #'prevout_n' tx_fields['output_index'] = OUTPUT_INDEX sign_tx.write_uint32(tx_fields['output_index']) #welche Ausgabe der Transaktion mit der TX-ID 'prevout_hash' wollen wir einlösen? ##Als nächstes kommt der Teil der Transaktionseingabe. Hier platzieren wir das Skript der *Ausgabe*, die wir einlösen möchten tx_fields['scriptSigHash'] = tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'] #schreibe zuerst die Größe sign_tx.write_compact_size(len(tx_fields['scriptSigHash'])) #dann die Daten sign_tx.write(tx_fields['scriptSigHash']) #'Reihenfolge' tx_fields['sequenz'] = 0xffffffff sign_tx.write_uint32(tx_fields['sequenz']) ##dann schreiben wir die Anzahl der Transaktionsausgaben. In diesem Beispiel verwenden wir nur eine einzige Ausgabe tx_fields['num_txout'] = 1 sign_tx.write_compact_size(tx_fields['num_txout']) ##dann schreiben wir die eigentlichen Transaktionsausgabedaten #wir lösen alles von der ursprünglichen Ausgabe abzüglich TX_FEE ein tx_fields['value'] = tx_info['txOut'][OUTPUT_INDEX]['value']-(TX_FEE*COIN) sign_tx.write_int64(tx_fields['Wert']) ##Hier geht unser scriptPubKey hin (ein Skript, das an eine Adresse auszahlt) #Wir wollen das folgende Skript: #"OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG" address_hash = bc_address_to_hash_160(SEND_TO_ADDRESS) #chr(20) ist die Länge des address_hash (20 Byte oder 160 Bit) scriptPubKey = chr(opcodes.OP_DUP) + chr(opcodes.OP_HASH160) + \ chr(20) + address_hash + chr(opcodes.OP_EQUALVERIFY) + chr(opcodes.OP_CHECKSIG) #schreiben Sie zuerst die Länge dieses Datenpakets tx_fields['scriptPubKey'] = scriptPubKey sign_tx.write_compact_size(len(tx_fields['scriptPubKey'])) #dann die Daten sign_tx.write(tx_fields['scriptPubKey']) #Sperrzeit schreiben (0) tx_fields['Sperrzeit'] = 0 sign_tx.write_uint32(tx_fields['locktime']) #und Hashcodetyp (1) tx_fields['hash_type'] = SIGHASH_ALL sign_tx.write_int32(tx_fields['hash_type']) #dann erhalten wir den Hash der signaturlosen Transaktion (den Hash, den wir mit unserem privaten Schlüssel signieren) hash_scriptless = dsha256(sign_tx.input) ## Jetzt beginnen wir mit dem ECDSA-Zeug. ## Wir erstellen einen privaten Schlüssel aus den bereitgestellten privaten Schlüsseldaten und signieren hash_scriptless damit ## prüfen wir auch, ob der entsprechende öffentliche Schlüssel des privaten Schlüssels die angegebene Ausgabe tatsächlich einlösen kann k = ecdsa_ssl.KEY() k.generate(('%064x' % PRIVATE_KEY).decode('hex')) #hier rufen wir die öffentlichen Schlüsseldaten ab, die aus dem bereitgestellten privaten Schlüssel generiert wurden pubkey_data = k.get_pubkey() #dann erstellen wir eine Signatur über den Hash der signaturlosen Transaktion sig_data=k.sign(hash_scriptless) #ein Ein-Byte-Hash-Typ wird an das Ende der Signatur angehängt (https://en.bitcoin.it/wiki/OP_CHECKSIG) sig_data = sig_data + chr(SIGHASH_ALL) #Überprüfen wir, ob der bereitgestellte private Schlüssel die betreffende Ausgabe tatsächlich einlösen kann if (bc_address_to_hash_160(public_key_to_bc_address(pubkey_data)) != tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2]): Bytes = b58decode (SEND_TO_ADDRESS, 25) raise RuntimeError, "Der bereitgestellte private Schlüssel kann nicht verwendet werden, um den Ausgabeindex %d einzulösen\nSie müssen den privaten Schlüssel für die Adresse %s angeben" % \ (OUTPUT_INDEX, hash_160_to_bc_address(tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2], bytes[0])) ## Jetzt beginnen wir mit der Erstellung der endgültigen Transaktion. dies ist ein Duplikat der signaturlosen Transaktion, ## mit dem scriptSig, das mit einem Skript ausgefüllt ist, das die Signatur plus den Ein-Byte-Hashcodetyp und den öffentlichen Schlüssel von oben auf den Stack überträgt final_tx = BCDataStream() final_tx.write_int32(tx_fields['Version']) final_tx.write_compact_size(tx_fields['num_txin']) final_tx.write(tx_fields['prevout_hash']) final_tx.write_uint32(tx_fields['output_index']) ##Jetzt müssen wir die eigentliche scriptSig schreiben. ## dieser besteht aus den DER-codierten Werten r und s aus der Signatur, einem Ein-Byte-Hashcodetyp und dem öffentlichen Schlüssel in unkomprimierter Form ## müssen wir auch die Länge dieser beiden Datenstücke voranstellen (codiert als ein einzelnes Byte ## mit der Länge), vor jedem Datenstück. Diese Länge ist ein Skript-Opcode, der dies mitteilt ## Bitcoin-Skriptinterpreter, um die x folgenden Bytes auf den Stack zu schieben scriptSig = chr(len(sig_data)) + sig_data + chr(len(pubkey_data)) + pubkey_data #schreiben Sie zuerst die Länge dieser Daten final_tx.write_compact_size(len(scriptSig)) #dann die Daten final_tx.write(scriptSig) ##und dann schreiben wir einfach dieselben Daten nach der scriptSig, die in der signaturlosen Transaktion enthalten ist, # Weglassen des Vier-Byte-Hash-Code-Typs (da dieser in dem einzelnen Byte nach den Signaturdaten codiert ist) final_tx.write_uint32(tx_fields['sequenz']) final_tx.write_compact_size(tx_fields['num_txout']) final_tx.write_int64(tx_fields['Wert']) final_tx.write_compact_size(len(tx_fields['scriptPubKey'])) final_tx.write(tx_fields['scriptPubKey']) final_tx.write_uint32(tx_fields['locktime']) # gibt die letzte Transaktion im Hex-Format aus (kann als Argument für senddrawtransaction von bitcoind verwendet werden) print final_tx.input.encode('hex')
k.generate(('%064x' % PRIVATE_KEY).decode('hex'))
tut? Soll ich etwas aus dem privaten Schlüssel generieren und damit signieren, oder signiere ich einfach mit dem privaten Schlüssel?Dieser Kern , der teilweise auf der Antwort von Runeks basiert, zeigt, wie man 0,01 Bitcoins in Ruby überträgt. Es ruft Informationen aus der vorherigen Transaktion von Blockchain.info ab, sodass Sie ihm nur Ihren privaten Schlüssel und Ihre Adresse zuführen müssen (letzteres ist redundant, aber nützlich für die Demonstration). Ich habe viele Kommentare hinzugefügt, um die Schritte zu erklären.
Sobald Sie die Transaktions-ID, den vout, den scriptPubKey dieser Transaktion und den WIF-codierten privaten Schlüssel kennen, der dem gehashten öffentlichen Schlüssel entspricht, um die Adresse zu erhalten, können Sie eine Rohtransaktion erstellen und signieren, ohne online zu sein.
Ich habe eine PHP-Bibliothek geschrieben, um mit Rohtransaktionen umzugehen (neben anderen Bitcoin-Funktionen). So würden Sie eine reguläre Transaktion einlösen: https://github.com/Bit-Wasp/bitcoin-lib-php Es ist ein Update erforderlich, um P2SH-Signaturen zu unterstützen, aber eine reguläre Transaktion wird problemlos eingelöst.
Benutzer7295
Müllhausen
f2b3eb2deb76566e7324307cd47c35eeb88413f971d88519859b1834307ecfec
, von dem blockexplorer.com sagt, dass er nicht existiertZauberer von Ozzie