Unable to sign transaction (testnet)

Hey,

I have been playing with Blockcerts for a couple of weeks now and I would like to issue sample certificates on the testnet. However, cert-issuer tells me it is unable to sign the transaction (trace below). I’ve seen this thread but unfortunately, it did not help much.

  • My public key exists on the testnet. For further verification, I was able to make a regular transaction to an electrum wallet using bitcoin-cli without a problem.
  • Certificates have been instantiated with cert-tools, this conf.ini file, and this issuer Id.
  • I wanted to issue two sample certificates for these students which also have valid testnet addresses. Here are the unsigned certificates.
  • When I run cert-tool -c conf.ini, the correct public key is referenced in the issung_address field and so is the link to the private key.
  • I am running a node. bitcoind is started and I have a copy of the testnet blockchain downloaded.

The same error arises when I issue this command instead:

cert-issuer --issuing_address 2MwBERpNv7JJaW4nVUbQncXjFjG1nFKLYEp --usb_name /etc/cert-issuer/ --key_file pk_issuer.txt --unsigned_certificates_dir /etc/cert-issuer/data/unsigned_certificates --signed_certificates_dir /etc/cert-issuer/data/signed_certificates --blockchain_certificates_dir /etc/cert-issuer/data/blockchain_certificates --work_dir /etc/cert-issuer/data/work --chain bitcoin_testnet --no_safe_mode

I am not able to issue certificates on the testnet, even when starting from sctratch with fresh addresses and using the commands provided in the readme.

  • I see on the readme that web images are lauched with sudo. Could that be related? I am using windows and gitbash so it is not something I can try.
  • Could it be a dependency error or a problem in cert-issuer? Note that the work directory stays empty.
  • Could that be related to my bitcoin configuration? Is there anything special to consider?

If you have any input/insight, that would be very helpful!
Thank you :wink:

Here is the trace:

Traceback (most recent call last):
  File "/usr/local/bin/cert-issuer", line 11, in <module>
    sys.exit(cert_issuer_main())
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/__main__.py", line 17, in cert_issuer_main
    issue_certificates.main(parsed_config)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/issue_certificates.py", line 36, in main
    return issue(app_config, certificate_batch_handler, transaction_handler)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/issue_certificates.py", line 22, in issue
    tx_id = issuer.issue(app_config.chain)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/issuer.py", line 27, in issue
    txid = self.transaction_handler.issue_transaction(blockchain_bytes)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/blockchain_handlers/bitcoin/transaction_handlers.py", line 56, in issue_transaction
    signed_tx = self.sign_transaction(prepared_tx)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/blockchain_handlers/bitcoin/transaction_handlers.py", line 92, in sign_transaction
    signed_tx = signer.sign_transaction(prepared_tx)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/models.py", line 84, in sign_transaction
    return self.signer.sign_transaction(self.wif, transaction_to_sign)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/blockchain_handlers/bitcoin/signer.py", line 35, in sign_transaction
    raise UnableToSignTxError('Unable to sign transaction')
cert_issuer.errors.UnableToSignTxError: Unable to sign transaction

If you have the full logs, that may help. One common error people have that cause the signing error is that the private key they use don’t match up with the public key.

Thanks for your quick answer :wink:

Yup, I verified the private key. I use bitcoin-cli to directly dump it into the file. For my public key it is:

~# bitcoin-cli dumpprivkey "2MwBERpNv7JJaW4nVUbQncXjFjG1nFKLYEp" > /etc/cert-issuer/pk_issuer.txt

As a result, pk_issuer.txt is created and contains a 52 characters string (I double checked it and it is conform to what comes out the standard output. Also, no space is hidden at the end of the line). I also created other adresses, sent funds, updated the private key accordingly but still the same exception is raised. There is something I’m missing…

The only condition for it to work is that the private key matches the public key? Doesn’t the public key have to match something else? Or doesn’t some parameter have to be set to something special?

Here is the log that appears with the trace:

WARNING - Your app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
INFO - This run will try to issue on the bitcoin_testnet chain
INFO - Set cost constants to recommended_tx_fee=0.000600,min_per_output=0.000028,satoshi_per_byte=250
INFO - Set cost constants to recommended_tx_fee=0.000600,min_per_output=0.000028,satoshi_per_byte=250
INFO - Processing 2 certificates
INFO - Processing 2 certificates
INFO - Processing 2 certificates under work path=/etc/cert-issuer/data/work
INFO - Processing 2 certificates under work path=/etc/cert-issuer/data/work
INFO - Total cost will be 133500 satoshis
INFO - Total cost will be 133500 satoshis
INFO - Starting finalizable signer
INFO - Starting finalizable signer
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
INFO - Stopping finalizable signer
INFO - Stopping finalizable signer
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
INFO - here is the op_return_code data: 96b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec34
INFO - here is the op_return_code data: 96b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec34
INFO - Unsigned hextx=0100000001fea7ff632a1f4fbaa69ffde7e94351ded43256a43f0a946bfb42946210ac85d70200000000ffffffff02e0604b000000000017a9142b1f34ef778f4e9efa9e36204592c6d029901116870000000000000000226a2096b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec3400000000
INFO - Unsigned hextx=0100000001fea7ff632a1f4fbaa69ffde7e94351ded43256a43f0a946bfb42946210ac85d70200000000ffffffff02e0604b000000000017a9142b1f34ef778f4e9efa9e36204592c6d029901116870000000000000000226a2096b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec3400000000
INFO - Preparing tx for signing
INFO - Preparing tx for signing
INFO - Starting finalizable signer
INFO - Starting finalizable signer
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
ERROR - Unable to sign transaction. hextx=0100000001fea7ff632a1f4fbaa69ffde7e94351ded43256a43f0a946bfb42946210ac85d70200000000ffffffff02e0604b000000000017a9142b1f34ef778f4e9efa9e36204592c6d029901116870000000000000000226a2096b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec3400000000
ERROR - Unable to sign transaction. hextx=0100000001fea7ff632a1f4fbaa69ffde7e94351ded43256a43f0a946bfb42946210ac85d70200000000ffffffff02e0604b000000000017a9142b1f34ef778f4e9efa9e36204592c6d029901116870000000000000000226a2096b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec3400000000
INFO - Stopping finalizable signer
INFO - Stopping finalizable signer
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
WARNING - app is configured to skip the wifi check when the USB is plugged in. Read the documentation to ensure this is what you want, since this is less secure
Traceback (most recent call last):
  File "/usr/local/bin/cert-issuer", line 11, in <module>
    sys.exit(cert_issuer_main())
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/__main__.py", line 17, in cert_issuer_main
    issue_certificates.main(parsed_config)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/issue_certificates.py", line 36, in main
    return issue(app_config, certificate_batch_handler, transaction_handler)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/issue_certificates.py", line 22, in issue
    tx_id = issuer.issue(app_config.chain)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/issuer.py", line 27, in issue
    txid = self.transaction_handler.issue_transaction(blockchain_bytes)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/blockchain_handlers/bitcoin/transaction_handlers.py", line 56, in issue_transaction
    signed_tx = self.sign_transaction(prepared_tx)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/blockchain_handlers/bitcoin/transaction_handlers.py", line 92, in sign_transaction
    signed_tx = signer.sign_transaction(prepared_tx)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/models.py", line 84, in sign_transaction
    return self.signer.sign_transaction(self.wif, transaction_to_sign)
  File "/usr/local/lib/python3.6/dist-packages/cert_issuer/blockchain_handlers/bitcoin/signer.py", line 35, in sign_transaction
    raise UnableToSignTxError('Unable to sign transaction')
cert_issuer.errors.UnableToSignTxError: Unable to sign transaction

and here is the transaction decoded with blockcypher

{
    "addresses": [
        "35d2N5StVqoEJH9woTnuzajzWuocS3Wrfy"
    ], 
    "block_height": -1, 
    "block_index": -1, 
    "confirmations": 0, 
    "data_protocol": "unknown", 
    "double_spend": false, 
    "fees": 0, 
    "hash": "73f405b87f40aa43c7a588f1b64d7f23e8289e9e5994e7895d881f3d7f3f3b0a", 
    "inputs": [
        {
            "age": 0, 
            "output_index": 2, 
            "prev_hash": "d785ac10629442fb6b940a3fa45632d4de5143e9e7fd9fa6ba4f1f2a63ffa7fe", 
            "script_type": "empty", 
            "sequence": 4294967295
        }
    ], 
    "outputs": [
        {
            "addresses": [
                "35d2N5StVqoEJH9woTnuzajzWuocS3Wrfy"
            ], 
            "script": "a9142b1f34ef778f4e9efa9e36204592c6d02990111687", 
            "script_type": "pay-to-script-hash", 
            "value": 4940000
        }, 
        {
            "addresses": null, 
            "data_hex": "96b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec34", 
            "script": "6a2096b798b6be8af088b4194af4f7fdc3f880f4f1cfe6a04f482465d8f5f675ec34", 
            "script_type": "null-data", 
            "value": 0
        }
    ], 
    "preference": "low", 
    "received": "2019-03-14T13:12:07.850995292Z", 
    "relayed_by": "54.227.204.11", 
    "size": 126, 
    "total": 4940000, 
    "ver": 1, 
    "vin_sz": 1, 
    "vout_sz": 2
}

Oh,

It seems that the recipient address is 35d2N5StVqoEJH9woTnuzajzWuocS3Wrfy (see log in previous post of this thread). This address is on the mainnet. That could explain why the transaction can’t be signed. How possible is that?

I’ll try to take a look at this tomorrow. For your latest question, you have to specifically tell BlockCypher what chain you’re on (mainnet vs testnet). Things look okay when you select testnet from the dropdown.

Indeed!

That’s interesting, the address appears valid on BlockCypher when picking the mainnet (orange coin):

But it indicates that the address is invalid when picking the testnet (blue coin):

I had issues connecting to blockchain.com for the past few days and can not verify that… :thinking:

Addresses look different in bitcoin if it’s a mainnet vs testnet, even if it’s coming from the same public key. 3* often indicates a mainnet address, and 2* often indicates a testnet address.

You’re right.

Common prefixies for testnet addresses are m* and n*. The Electrum wallet actually generates such addresses.

However, my bitcoin core generates addresses with a 2* as a prefix which is also valid for the testnet. When I look at the difference between the two types it appears that they are not the same type of key:

I saw posts on this blog where people successfully issue certificates with a m* address but I didn’t see any documentation specifying that cert-issuer can/can’t handle Pay to script hash (P2SH) transactions.

Do you think that P2SH confuses cert-issuer? I’m stuck here, what do you suppose I try to finally issue on the testnet?

Thanks,
Florent.

Alright,

I finally issued certificates on the testnet. Turns out the solution was to delete everything and use the Dockerfile instead of Dockerfile.web.

Here is the bottom line, I don’t know how things are related:

  • Dockerfile: Generates m* public addresses, transaction is made to myself, issuing works.
  • Dockerfile.web: Generates 2* public addresses, transaction is made to a 3* address, issuing fails (unable to sign transaction).
  • Dockerfile.web.tls: Does not build:
Step 36/62 : COPY $CRT /etc/ssl/certs/$CRT
lstat cert.crt: no such file or directory

Each Dockerfile is built differently and does not use the same linux distribution (Alpine for Dockerfile / Ubuntu for Dockerfile.web) nor the same bitcoincore version (0.15.1 for Dockerfile / 0.16.3 for Dockerfile.web). There is something wrong with the .web image on my machine but I am not able to debug it.

Perhaps this answer will be useful to someone :slightly_smiling_face:

Hello F.Dufour,

I had the same problem related by you… and I solve it reading this documentation https://bitcoin.org/en/glossary/address, there are two types of the public address:

A 20-byte hash formatted using base58check to produce either a P2PKH or P2SH Bitcoin address. Currently the most common way users exchange payment information

When I tried to issue on address starting with 2*, I got the same error.

So I thought should exists a way to change the type of address, and I found this documentation explaining how to do this. https://bitcoincore.org/en/2018/02/26/release-0.16.0/

In my case, I created the whole environment (I’m not using docker) so, I just changed the start the bitcoreserver to bitcoind -addresstype = legacy -daemon (I also could put this parameter in bitcoin.conf).

And… all working

Thanks, your thread help me a lot.

/

000000

INFO - verifying op_return value for transaction

INFO - verified OP_RETURN

INFO - Broadcasting succeeded with method_provider=<bound method BitcoindConnector.broadcast_tx of <cert_issuer.blockchain_handlers.bitcoin.connectors.BitcoindConnector object at 0x1042d3128>>, txid=36f36a1e06128226d38a69ce887d423a02821987795c7edbc244cfbd1d5f4dc9

INFO - Broadcast transaction with txid 36f36a1e06128226d38a69ce887d423a02821987795c7edbc244cfbd1d5f4dc9

INFO - Your Blockchain Certificates are in /ufp/cert_data

Thanks for the reports guys, thinking about this again, a couple things are coming to mind.

  1. Dockerfile.web is using version 0.16.3 which uses P2SH by default, I believe. As Fernando mentioned, creating a “legacy” address resolves that. There’s a github issue to update the version of Dockerfile since it’s at an old 0.13, but might be good to hold off on that for now since there’s issues with new addresses.

  2. We have a PR that should support segwit addresses that @lparker created awhile back (https://github.com/blockchain-certificates/cert-issuer/pull/84/files) though it could use some more testing to verify that old addresses and new addresses work without any issue.

I’d say for now, use the legacy option for creating a new address when using Dockerfile.web: https://bitcoincore.org/en/doc/0.16.0/rpc/wallet/getnewaddress/

thanks. already come in handy!