2

Based on the script from github. I tried to construct a valid testnet transaction. I had to do some modifications to the script so here is the current 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")    )

the script is using the address and transaction found here https://live.blockcypher.com/btc-testnet/address/mwRhL3S4NATBKDJkgbaa1PXGFUB9Qi1uuj/ . When I try to broadcast the transaction using https://live.blockcypher.com/btc-testnet/pushtx/ . I get an error message saying it´s something wrong regarding the script in input transaction has a script based on pay-to-pubkey-hash and that´s how I try to decode it. Any tips?

The tx generated by the script

0100000001387205fa23c962e6951a66387cbd9ab8bbca5167f98a651a657457c6a8e81083010000009e5948314d3064512b6d6668436f4849693154514f79795975646b306f57786263586c4245582f5968636954386d567943375a717a41616d454570577530435950456f72656e644f44467a4f6e5146776b69595737354b67633d014304303364393466316464383732383862613163306666656665636161373161633733393733323132303662666137326631313563313761323639316331633866336539ffffffff02a0860100000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac50c30000000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac00000000

The error message is

Error validating transaction: Error running script for input 0 referencing 8310e8a8c65774651a658af96751cabbb89abd7c38661a95e662c923fa057238 at 1: Script was NOT verified successfully..

5
  • Add the exact error message, please.
    – Hannah Vernon
    Nov 20, 2017 at 18:16
  • The error message is "Error validating transaction: Error running script for input 0 referencing 8310e8a8c65774651a658af96751cabbb89abd7c38661a95e662c923fa057238 at 1: Script was NOT verified successfully..". I will update the post with the raw tx. Nov 20, 2017 at 19:13
  • Your input script is completely invalid and nothing like what your python script suggests you want to do. What seems to have happened here is that you have encoded a string into the transaction, not the bytes that are required.
    – Andrew Chow
    Nov 20, 2017 at 20:10
  • How did you find that out? is there a way to decode the tx to analyze the part that went wrong? Nov 20, 2017 at 20:56
  • You can use the decoderawtransaction call it bitcoin core to decode a raw transaction. From looking at the "asm" field of the scriptSig from the transaction's input, you can see clearly that it is a jumble of rubbish data, not at all a valid script Jan 5, 2018 at 3:16

1 Answer 1

1

As MeshCollider pointed out, scriptSig is wrong, but it does seem to have structure to it. Specifically it looks like OP is doing operations on ascii text instead of the actual bytes :

scriptSig is :

48314D3064512B6D6668436F4849693154514F79795975646B306F57786263586C4245582F5968636954386D567943375A717A41616D454570577530435950456F72656E644F44467A4F6E5146776B69595737354B67633D
01
43
04
303364393466316464383732383862613163306666656665636161373161633733393733323132303662666137326631313563313761323639316331633866336539

Which is actually (hex2bin some of the data) :

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

Also seems that OP's signature on the transaction is invalid, so I guess that the data hashed itself was malformed. The correct data for sighash would be :

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

And the signature would be :

30440220586E47980A1329CE23A55E318772935056972FCD7F702D39594A2F0A786657E40220234CCC55AE41DED90A09D3F86F52BD0FD1B881000EDB1734FD0ACE6AFBFB7E4D01

Then the final transaction is :

0100000001387205FA23C962E6951A66387CBD9AB8BBCA5167F98A651A657457C6A8E81083010000006A4730440220586E47980A1329CE23A55E318772935056972FCD7F702D39594A2F0A786657E40220234CCC55AE41DED90A09D3F86F52BD0FD1B881000EDB1734FD0ACE6AFBFB7E4D012103D94F1DD87288BA1C0FFEFECAA71AC7397321206BFA72F115C17A2691C1C8F3E9FFFFFFFF02a0860100000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac50c30000000000001976a914ae8370a2d4634b2b6f29b938a996f961f73ded4888ac00000000

I'll let OP decide if they want to redeem it or not. It's practically paying everything to fees :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.