1

As the title states, I'm trying to send a Litecoin transaction using the Blockcypher API Python SDK, and using Bitcoinlib for key management. I have extensively reviewed the documentation and source code for the tools I'm working with, and I have tried researching this specific error but still have yet to get past this roadblock.

I've gotten to a point where the transaction is built and and signatures are created, but when I try broadcasting it, the API returns this error to my console:

{'errors': [{'error': 'Error validating generated transaction: 
Error running script for input 0 referencing 79d841bf41ead0e4ecbb58197c289ec9cc087e85cf1a98196e2e415b8990357a at 0:
Script was NOT verified successfully.'}], 

'tx': {'block_height': -1, 'block_index': -1, 
'hash': 'f2ae95498b3b209ee077ad8a32292a0461ab2d37b807a647520aee31e9c62d29', 
'addresses': ['ltc1q7nyvlc6jkznpemw3g0n8f3z5z4eatfhevy07au', 'ltc1qxdvtqt9tm7rwplk8upezujtjsh6k3l85tw39ue'], 
'total': 98100, 
'fees': 1900, 
'size': 221, 
'vsize': 140, 
'preference': 'low', 
'relayed_by': '35.226.89.167', 
'received': '2023-07-05T08:53:48.287727164Z', 
'ver': 1, 
'double_spend': False,
'vin_sz': 1, 
'vout_sz': 2, 
'confirmations': 0, 
'inputs': [
    {'prev_hash': '79d841bf41ead0e4ecbb58197c289ec9cc087e85cf1a98196e2e415b8990357a',
     'output_index': 0, 
     'output_value': 100000,
     'sequence': 4294967295,
     'addresses': ['ltc1q7nyvlc6jkznpemw3g0n8f3z5z4eatfhevy07au'], 
     'script_type': 'pay-to-witness-pubkey-hash', 
     'age': 2502561,
     'witness': 
['3044022077515b45f26a56b0dfff42eb94b69d98dbf8fb896fda079ea7e99a17a768fd6f022008b3c435ee0816801e1eea22871cb935a7eaaa8df6ad472eab19b096fb62cd82'
, '034b3110d0be2b52a14c4bbccef285396c67c29586463f278a8d1efacb3c33f439']}], 
'outputs': [{
     'value': 10000, 
     'script': '00143358b02cabdf86e0fec7e0722e497285f568fcf4',
     'addresses': ['ltc1qxdvtqt9tm7rwplk8upezujtjsh6k3l85tw39ue'], 
     'script_type': 'pay-to-witness-pubkey-hash'}, 
     {'value': 88100, 
     'script': '0014f4c8cfe352b0a61cedd143e674c4541573d5a6f9', 
     'addresses': ['ltc1q7nyvlc6jkznpemw3g0n8f3z5z4eatfhevy07au'], 
     'script_type': 'pay-to-witness-pubkey-hash'}]},
'tosign': ['']}

First, I tried using the simple_spend method as shown below...

from blockcypher import simple_spend
simple_tx = simple_spend(api_key = API_KEY, from_privkey=priv_key_hex,
to_address='ltc1qxdvtqt9tm7rwplk8upezujtjsh6k3l85tw39ue', to_satoshis=10000, coin_symbol='ltc')
print('tx:', simple_tx)

... and this error was produced:

TX Error(s): Tx NOT Signed or Broadcast
Unable to find a transaction to spend for address LhYFhgm6iai5da8ADeoUjs2BnAPoPm74cm.
Not enough funds in 0 inputs to pay for 1 outputs, missing -10000.
Not enough funds after fees in 0 inputs to pay for 1 outputs, missing -11400.
Error validating generated transaction: Transaction missing input or output.
Traceback (most recent call last):
  File "main.py", line 33, in <module>
    simple_tx = simple_spend(api_key = API_KEY, from_privkey=priv_key_hex, to_address='ltc1qxdvtqt9tm7rwplk8upezujtjsh6k3l85tw39ue', to_satoshis=10000, coin_symbol='ltc')
  File "/home/runner/sendltc/venv/lib/python3.10/site-packages/blockcypher/api.py", line 1684, in simple_spend
    raise Exception('Build Unsigned TX Error')
Exception: Build Unsigned TX Error

This indicates that the private key I provided is automatically being formatted as a legacy address, where no funds for the input transaction exist because I funded the segwit derivative of the private key. I have since verified that this code will properly execute transactions when I fund the legacy derivative of the private key. But it does not work when I attempt to involve a segwit addresses as the sender or receiver.

Since I am unsure of how to ensure that the simple_spend method attempts a segwit transaction, I tried constructing it piece-by-piece.

Here's the code for that:

from bitcoinlib.keys import Key
from blockcypher import create_unsigned_tx, make_tx_signatures, broadcast_signed_transaction

API_KEY = '<api_key>'

wif = '<compressed_wif>'


priv_key_hex = Key(wif, network = 'litecoin').private_hex
pub_key_hex = Key(wif, network = 'litecoin').public_hex

sender = Key(priv_key_hex, network = 'litecoin').address(prefix='ltc', script_type='p2wpkh', encoding='bech32')
inputs = [{'address': f"{sender}"}]
outputs = [{'address': 'ltc1qxdvtqt9tm7rwplk8upezujtjsh6k3l85tw39ue', 'value': 10000}]

unsigned_tx = create_unsigned_tx(inputs=inputs, outputs=outputs, include_tosigntx=True, coin_symbol='ltc', api_key = API_KEY)
print(unsigned_tx)

privkey_list = [str(priv_key_hex)]
pubkey_list = [str(pub_key_hex)]

tx_signatures = make_tx_signatures(txs_to_sign=unsigned_tx['tosign'], privkey_list=privkey_list, pubkey_list=pubkey_list)
print('')
print(tx_signatures)

tx = broadcast_signed_transaction(unsigned_tx=unsigned_tx, signatures=tx_signatures, pubkeys=pubkey_list, coin_symbol='ltc', api_key = API_KEY)
print('')
print(tx)

So when I try to run this, the aforementioned error is returned, stating that the script could not be verified. My hunch is that it has something to do with attempting to broadcast a legacy transaction while I provided a segwit address. Upon viewing similar threads on here, it would seem that the signature is being malformed either because there is a problem with how I'm deriving my keys, or somehow I need to set a flag indicating a segwit transaction. This could lead to the root of the problem, but I could also be overlooking other issues.

Any advice, pointers, or answers would be greatly appreciated. Thank you for your time.

1 Answer 1

0

It looks like the function make_tx_signatures does not include the sighash byte at the end of the signature. This causes the signature to be invalid as the sighash byte is required so that the node knows what to include in the message hash when verifying.

Presumably the transaction is being signed with SIGHASH_ALL, so you simply need to append a 01 byte to the end of the signature.

Your Answer

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

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