Tuesday, November 5, 2024

signature – manually signing bitcoin transaction

I am attempting to create a BTC transaction with one enter and two outputs, one for change and one OP_RETURN to anchor knowledge. And I am doing all of that on my regtest backend. The uncooked unsigned transaction is

01000000018be9d0e99e74d69d915e105db1328707f713d42a894909b18a78fe68e1d8290c0000000023210340165231215a98e7a32abce9d410ecd09ac505938b25f9451defa051d591ebf8acffffffff0218ee052a010000001976a9143eb52fb0be4be87edc74848b371547f663e26c7e88ac0000000000000000226a408973d6b447bdda5312b1ef1b5509668672296301dd328d4e55317def98f165d200000000

I can then use the bitcoin rpc to signal it and it really works, so I am fairly sure that this half is right. Once I nonetheless attempt to signal it manually I get the error

500: {"end result":null,"error":{"code":-26,"message":"16: mandatory-script-verify-flag-failed (Non-canonical DER signature)"},"id":2}

I’ve adopted the steps outlined in redeem a primary Tx? in addition to Signing a uncooked transaction with Python ECDSA (or OpenSSL) in addition to tried to make use of pybitcointools to signal the enter with out success.

The tackle and personal key I take advantage of are

addr: "mmEXEzUGcMmmiLsfxxM8gB8TQSTkuR1drf"
pk:  "cTyF9pebH3kwwzUt5gzaxSDQ1DbqYfx4P1i4d1TyjtSDEeUFgYsk"

and stragely, although the PK is the one given to me by ./bitcoin-cli -regtest dumpprivkey <addr> doesn’t appear to match the tackle and I am undecided why or what it’s I must do to it (it is in WIF format and compressed, i.e. 0x01 appended to the tip

The unique TX contains the scriptPubKey of the utxo. I then double sha256 the entire uncooked tx (proven above) and exchange the scriptPubKey half with the sigScript | pubkey utilizing the next code:

private_key, compressed_pk = wif_to_private_key(private_key_wif)
tx = bytearray.fromhex(raw_unsigned_transaction) + int(1).to_bytes(4, 'little')

double_sha256_tx = hashlib.sha256(hashlib.sha256(tx).digest()).digest()
signing_key = ecdsa.SigningKey.from_string(bytearray.fromhex(private_key), curve=ecdsa.SECP256k1)
public_key = bytearray.fromhex(privtopub(private_key_wif))
signature = signing_key.sign_digest(double_sha256_tx, sigencode=ecdsa.util.sigencode_der) + int(1).to_bytes(1, 'little')
scriptSig = to_varstr(signature) + to_varstr(public_key)

to_varstr merely prints [len]|[data] and privtopub is the perform from pybitcointools as I could not determine easy methods to go from the compressed non-public key to the tackle manually. It is value noting although that the public_key right here that privtoaddr from pybitcointools doesn’t return the proper tackle both which is perhaps the basis reason for the problem?

I might be glad about any pointers or issues to strive

cheers
Chris

PS:
one other attention-grabbing side is that the signed transaction I generate is loads longer than the one generated by the signtransaction rpc name:

rpc:    01000000018be9d0e99e74d69d915e105db1328707f713d42a894909b18a78fe68e1d8290c0000000023210340165231215a98e7a32abce9d410ecd09ac505938b25f9451defa051d591ebf8acffffffff0218ee052a010000001976a9143eb52fb0be4be87edc74848b371547f663e26c7e88ac0000000000000000226a40ac4f0818b683eeeaa1fbf2f508af2fc22cc814e69025152c70d7c414ebbfc30a00000000
handbook: 01000000018be9d0e99e74d69d915e105db1328707f713d42a894909b18a78fe68e1d8290c000000006b483045022100d6e538aa819f3162d5c6a0e4d9ee0323395df89e943c769d96ae939baec5c6920220083a311cb35df3c98d7a6bd0bc80d98a71fbdf8e325ba908ea4b721a4eac8bb301210343395a6e84c7f2b1d50c11f96783664a6f04d66b51befb3befcc57334e2a9abcffffffff0218ee052a010000001976a9143eb52fb0be4be87edc74848b371547f663e26c7e88ac0000000000000000226a40ac4f0818b683eeeaa1fbf2f508af2fc22cc814e69025152c70d7c414ebbfc30a00000000

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles