Fehler bei der Erstellung von Rohtransaktionen im Python-Testnet

Basierend auf dem Skript von github . Ich habe versucht, eine gültige Testnet-Transaktion zu erstellen. Ich musste einige Änderungen am Skript vornehmen, also hier ist der aktuelle Code.

import struct
import base58
import hashlib
import ecdsa

import struct
import base58
import hashlib
import ecdsa


Bob_addr = "mwRhL3S4NATBKDJkgbaa1PXGFUB9Qi1uuj"
bob_hashed_pubkey = base58.b58decode_check(Bob_addr)[1:].encode("hex")
print(bob_hashed_pubkey)
print(base58.b58decode_check(Bob_addr)[1:])

Bob_private_key = "cQFXsyWHnz1CcxgDb1E4q7zLoB6jVzhCCGMyXSJaj74YGUik2N45"
prv_txid = "8310e8a8c65774651a658af96751cabbb89abd7c38661a95e662c923fa057238"


Charlie_adr = "mwRhL3S4NATBKDJkgbaa1PXGFUB9Qi1uuj"
charlie_hashed_pubkey = base58.b58decode_check(Charlie_adr)[1:].encode("hex")

class raw_tx:
    version         = struct.pack("<L", 1)
    tx_in_count     = struct.pack("<B", 1)
    tx_in           = {} #TEMP
    tx_out_count    = struct.pack("<B", 2)
    tx_out1         = {} #TEMP
    tx_out2         = {} #TEMP
    lock_time       = struct.pack("<L", 0)

def flip_byte_order(string):
    flipped = "".join(reversed([string[i:i+2] for i in range(0, len(string), 2)]))
    return flipped


rtx = raw_tx()

rtx.tx_in["txouthash"]      = flip_byte_order(prv_txid).decode("hex")
rtx.tx_in["tx_out_index"]   = struct.pack("<L", 1)
rtx.tx_in["script"]         = ("76a914%s88ac" % charlie_hashed_pubkey).decode("hex")
rtx.tx_in["scrip_bytes"]    = struct.pack("<B", len(rtx.tx_in["script"]))
rtx.tx_in["sequence"]       = "ffffffff".decode("hex")

rtx.tx_out1["value"]        = struct.pack("<Q", 100000)
rtx.tx_out1["pk_script"]    = ("76a914%s88ac" % bob_hashed_pubkey).decode("hex")
rtx.tx_out1["pk_script_bytes"] = struct.pack("<B", len(rtx.tx_out1["pk_script"]))

rtx.tx_out2["value"]        = struct.pack("<Q", 50000)
rtx.tx_out2["pk_script"]    = ("76a914%s88ac" % bob_hashed_pubkey).decode("hex")
rtx.tx_out2["pk_script_bytes"] = struct.pack("<B", len(rtx.tx_out2["pk_script"]))

raw_tx_string = (

    rtx.version
    + rtx.tx_in_count
    + rtx.tx_in["txouthash"]
    + rtx.tx_in["tx_out_index"]
    + rtx.tx_in["scrip_bytes"]
    + rtx.tx_in["script"]
    + rtx.tx_in["sequence"]
    + rtx.tx_out_count

    + rtx.tx_out1["value"]
    + rtx.tx_out1["pk_script_bytes"]
    + rtx.tx_out1["pk_script"]
    + rtx.tx_out2["value"]
    + rtx.tx_out2["pk_script_bytes"]
    + rtx.tx_out2["pk_script"]
    + rtx.lock_time
    + struct.pack("<L", 1)

    )

hashed_tx_to_sign = hashlib.sha256(hashlib.sha256(raw_tx_string).digest()).digest()
print(hashed_tx_to_sign)

#sk = ecdsa.SigningKey.from_string(Bob_private_key.decode("hex"), curve = ecdsa.SECP256k1)
#vk = sk.verifying_key
print(bitcoin.privkey_to_pubkey(Bob_private_key))

vk = bitcoin.privkey_to_pubkey(Bob_private_key)
public_key = ('\04' + vk).encode("hex")

#signature = sk.sign_digest(hashed_tx_to_sign, sigencode = ecdsa.util.sigencode_der_canonize)
signature = (bitcoin.ecdsa_sign(hashed_tx_to_sign, Bob_private_key))



sigscript = (

    signature
    + "\01"
    + struct.pack("<B", len(public_key.decode("hex")))
    + public_key.decode("hex")

    )

real_tx = (
    rtx.version
    + rtx.tx_in_count
    + rtx.tx_in["txouthash"]
    + rtx.tx_in["tx_out_index"]
    + struct.pack("<B", len(sigscript) + 1)
    + struct.pack("<B", len(signature) + 1)
    + sigscript
    + rtx.tx_in["sequence"]
    + rtx.tx_out_count
    + rtx.tx_out1["value"]
    + rtx.tx_out1["pk_script_bytes"]
    + rtx.tx_out1["pk_script"]
    + rtx.tx_out2["value"]
    + rtx.tx_out2["pk_script_bytes"]
    + rtx.tx_out2["pk_script"]
    + rtx.lock_time

    )

print(real_tx.encode("hex")    )

Das Skript verwendet die hier gefundene Adresse und Transaktion https://live.blockcypher.com/btc-testnet/address/mwRhL3S4NATBKDJkgbaa1PXGFUB9Qi1uuj/ . Wenn ich versuche, die Transaktion mit https://live.blockcypher.com/btc-testnet/pushtx/ zu übertragen . Ich erhalte eine Fehlermeldung, die besagt, dass etwas mit dem Skript in der Eingabetransaktion nicht stimmt. Es hat ein Skript, das auf Pay-to-Pubkey-Hash basiert, und so versuche ich, es zu entschlüsseln. Irgendwelche Tipps?

Der vom Skript generierte TX

0100000001387205fa23c962e6951a66387cbd9ab8bbca5167f98a651a657457c6a8e81083010000009e5948314d3064512b6d6668436f4849693154514f79795975646b306f57786263586c4245582f5968636954386d567943375a717a41616d454570577530435950456f72656e644f44467a4f6e5146776b69595737354b67633d014304303364393466316464383732383862613163306666656665636161373161633733393733323132303662666137326631313563313761323639316331633866336539ffffffff02a0860100000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac50c30000000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac00000000

Die Fehlermeldung ist

Fehler beim Validieren der Transaktion: Fehler beim Ausführen des Skripts für Eingabe 0 mit Verweis auf 8310e8a8c65774651a658af96751cabbb89abd7c38661a95e662c923fa057238 bei 1: Skript wurde NICHT erfolgreich verifiziert.

Fügen Sie bitte die genaue Fehlermeldung hinzu.
Die Fehlermeldung lautet „Fehler beim Validieren der Transaktion: Fehler beim Ausführen des Skripts für Eingabe 0 mit Verweis auf 8310e8a8c65774651a658af96751cabbb89abd7c38661a95e662c923fa057238 bei 1: Skript wurde NICHT erfolgreich überprüft.“ Ich werde den Beitrag mit dem Roh-TX aktualisieren.
Ihr Eingabeskript ist völlig ungültig und entspricht nicht dem, was Ihr Python-Skript vorschlägt. Was hier passiert zu sein scheint, ist, dass Sie eine Zeichenfolge in die Transaktion codiert haben, nicht die erforderlichen Bytes.
Wie hast du das herausgefunden? Gibt es eine Möglichkeit, den TX zu decodieren, um den Teil zu analysieren, der schief gelaufen ist?
Sie können den decoderawtransactionCall-it-Bitcoin-Kern verwenden, um eine Rohtransaktion zu dekodieren. Wenn Sie sich das "asm"Feld der scriptSigTransaktionseingabe ansehen, können Sie deutlich erkennen, dass es sich um ein Durcheinander von Mülldaten handelt, überhaupt nicht um ein gültiges Skript

Antworten (1)

Wie MeshCollider betonte, ist scriptSig falsch, aber es scheint eine Struktur zu haben. Insbesondere sieht es so aus, als ob OP Operationen mit ASCII-Text anstelle der tatsächlichen Bytes ausführt:

scriptSig ist:

48314D3064512B6D6668436F4849693154514F79795975646B306F57786263586C4245582F5968636954386D567943375A717A41616D454570577530435950456F72656E644F44467A4F6E5146776B69595737354B67633D
01
43
04
303364393466316464383732383862613163306666656665636161373161633733393733323132303662666137326631313563313761323639316331633866336539

Was eigentlich ist (hex2bin einige der Daten):

1. H1M0dQ+mfhCoHIi1TQOyyYudk0oWxbcXlBEX/YhciT8mVyC7ZqzAamEEpWu0CYPEorendODFzOnQFwkiYW75Kgc= <- recoverable signature over some data
2. 01                                                                                       <- probably appended to use as SIGHASH_ALL
3. 43                                                                                       <- size of the next two items concatenated
4. 04                                                                                       <- probably prepended by mistake, 
                                                                                               thinking that all pubkeys are prepended with 0x04 ?
5. 03d94f1dd87288ba1c0ffefecaa71ac7397321206bfa72f115c17a2691c1c8f3e9                       <- pubkey in lowercase hex characters

Es scheint auch, dass die OP-Signatur für die Transaktion ungültig ist, daher vermute ich, dass die gehashten Daten selbst fehlerhaft sind. Die korrekten Daten für sighash wären:

01000000
01
  387205FA23C962E6951A66387CBD9AB8BBCA5167F98A651A657457C6A8E81083
  01000000
  19
    76 A9 14 AE8370A2D4634B2B6F29B938A996F961F73DED48 88 AC
  FFFFFFFF
02
  a086010000000000
  19
    76 a9 14 ae8370a2d4634b2b6f29b938a996f961f73ded48 88 ac
  50c3000000000000
  19
    76 a9 14 ae8370a2d4634b2b6f29b938a996f961f73ded48 88 ac
00000000
01000000

Und die Signatur wäre:

30440220586E47980A1329CE23A55E318772935056972FCD7F702D39594A2F0A786657E40220234CCC55AE41DED90A09D3F86F52BD0FD1B881000EDB1734FD0ACE6AFBFB7E4D01

Dann ist die letzte Transaktion:

0100000001387205FA23C962E6951A66387CBD9AB8BBCA5167F98A651A657457C6A8E81083010000006A4730440220586E47980A1329CE23A55E318772935056972FCD7F702D39594A2F0A786657E40220234CCC55AE41DED90A09D3F86F52BD0FD1B881000EDB1734FD0ACE6AFBFB7E4D012103D94F1DD87288BA1C0FFEFECAA71AC7397321206BFA72F115C17A2691C1C8F3E9FFFFFFFF02a0860100000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac50c30000000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac00000000

Ich lasse OP entscheiden, ob sie es einlösen wollen oder nicht. Es zahlt praktisch alles an Gebühren :)