0

I'm looking to get "hands on" with signing, however when I adapt Runeks' thorough answer at https://bitcoin.stackexchange.com/a/5241/89798 my code invariably fails reporting that I've used the wrong private key. Am I sourcing the private key wrongly, or mishandling it in some way? Where in my process below am I getting it wrong?

I'll start by noting Runeks' code as it stands executes correctly, that I'm using v0.13.2 bitcoind and bitcoin-cli in order to get the legacy transactions used in his answer, and I'm using regtest rather than mainnet.

My process:

  1. I use a script to reset the regtest network and generate 101 blocks so I've a single coinbase I can use:
CURDIR=`pwd`
cd /home/bitcoin14/.bitcoin
/usr/local/bin/bitcoin-cli -conf=/home/bitcoin14/.bitcoin/regtest.conf -regtest stop
sleep 1
rm -rf /home/bitcoin14/.bitcoin/regtest && /usr/local/bin/bitcoind -conf=/home/bitcoin14/.bitcoin/regtest.conf -regtest -daemon
sleep 2
/usr/local/bin/bitcoin-cli -conf=/home/bitcoin14/.bitcoin/regtest.conf -regtest generate 101 >/dev/null
cd $CURDIR
  1. I send the coins to a new address in order not to use that coinbase transaction
$ /usr/local/bin/bitcoin-cli -conf=/home/bitcoin14/.bitcoin/regtest.conf getnewaddress
mk5U6xEDnTmfNrHcCXkdKrXziYH1YMygVw
$ /usr/local/bin/bitcoin-cli -conf=/home/bitcoin14/.bitcoin/regtest.conf sendtoaddress mk5U6xEDnTmfNrHcCXkdKrXziYH1YMygVw 49.99
675eac8d9aebe4f84aa2bb18a9f02304d11cb8937ca103b6ccf00fdf0de69727
  1. I obtain the hex and vout of the above transaction as containing the coins whose move I wish to sign
$ /usr/local/bin/bitcoin-cli -conf=/home/bitcoin14/.bitcoin/regtest.conf gettransaction 675eac8d9aebe4f84aa2bb18a9f02304d11cb8937ca103b6ccf00fdf0de69727 | egrep 'vout|hex'
      "vout": 1,
      "vout": 1
  "hex": "0100000001fe37d2309bb4b4f4de102ff08f08e049acaecd4c1ee195328404c02406e596c6000000004847304402206eef31e0114c8e31180da39c644fc518624e9c5f354f6c375bfffba8a3c0dc6d022021056d74ea16155036663b7aaab1e297715231747718e48ab94aefd05cded83d01feffffff0254330f00000000001976a91486d1e65bc7f89b24724f50fa5db3a7f102d9644d88acc0aff629010000001976a9143206b266d2998b1092fcd1737165c363c0e31b6c88ac65000000"
  1. I obtain a new address to which the coins will be redeemed
$ /usr/local/bin/bitcoin-cli -conf=/home/bitcoin14/.bitcoin/regtest.conf getnewaddress
n42ui4Tbd2mVPiRtAUr4RYW7KC7qUmXDTt
  1. I obtain the private key generated at "2" above
$ /usr/local/bin/bitcoin-cli -conf=/home/bitcoin14/.bitcoin/regtest.conf dumpprivkey mk5U6xEDnTmfNrHcCXkdKrXziYH1YMygVw
cPMjUqc3d4WhDG8Evn2G3RrVWMyetHtwiTZhpKW1T1QUrBhYGVnG
  1. I convert the private key into the hex equivalent as per https://bitcoin.stackexchange.com/a/52954/89798 (This on a different machine)
$ ./bitcoin-tool --input-type private-key-wif --input-format base58check --output-type private-key --output-format hex --network bitcoin --input cPMjUqc3d4WhDG8Evn2G3RrVWMyetHtwiTZhpKW1T1QUrBhYGVnG
3500dba7a3363e7127cd72273b0e475c5dbb1d378496b803edaf06f8eb3ee160
  1. I take the above and edit them into place in Runeks' code
HEX_TRANSACTION="0100000001fe37d2309bb4b4f4de102ff08f08e049acaecd4c1ee195328404c02406e596c6000000004847304402206eef31e0114c8e31180da39c644fc518624e9c5f354f6c375bfffba8a3c0dc6d022021056d74ea16155036663b7aaab1e297715231747718e48ab94aefd05cded83d01feffffff0254330f00000000001976a91486d1e65bc7f89b24724f50fa5db3a7f102d9644d88acc0aff629010000001976a9143206b266d2998b1092fcd1737165c363c0e31b6c88ac65000000"
...
OUTPUT_INDEX=1
...
SEND_TO_ADDRESS="n42ui4Tbd2mVPiRtAUr4RYW7KC7qUmXDTt"
...
PRIVATE_KEY=0x3500dba7a3363e7127cd72273b0e475c5dbb1d378496b803edaf06f8eb3ee160
  1. I run the code (again different machine to the above)
$ python2 sign3.py 
Traceback (most recent call last):
  File "sign3.py", line 144, in <module>
    (OUTPUT_INDEX, hash_160_to_bc_address(tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2], bytes[0]))
RuntimeError: The supplied private key cannot be used to redeem output index 1
You need to supply the private key for address mk5U6xEDnTmfNrHcCXkdKrXziYH1YMygVw

The error is clear: I have not supplied the correct private key. Where is my mistake? Thanks all!

Edit

It appears that bitcoind-0.13 provides a pubkeyhash based on a compressed public key, and that the code beneath acts on the uncompressed public key that the private key reveals. The two hashes being different, the later conditional fails.

k = ecdsa_ssl.KEY()
k.generate(('%064x' % PRIVATE_KEY).decode('hex'))

#here we retrieve the public key data generated from the supplied private key                                                                                                                                                                                                  
pubkey_data = k.get_pubkey()

Investigations continue...

1

The issue is public key compression, as noted in your edit. The original code does not handle compressed public keys.

Try adding

k.set_compressed(True)

before

#here we retrieve the public key data generated from the supplied private key                                                                                                                                                                                                  
pubkey_data = k.get_pubkey()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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