Author

Topic: Help with creating P2PK transaction (Read 149 times)

legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
May 02, 2024, 02:03:51 AM
#3
Edit: With a bit more experimentation, I am able to replicate your signatures if I hash one too many times. You are hashing the sighash preimage with SHA256 3 times, not 2 times, and that's why your signature is wrong. The way signing works is that the hash function is double SHA256, and the result is directly used in the z used in the s computation. You don't hash it again since it isn't the message.

Thank you for your response. My signatures were being generated by coincurve, a libesecp256k1 wrapper, and it turns out that it was hashing the message a third time before signing, which I wasn't aware of apparently: https://ofek.dev/coincurve/api/#coincurve.keys.PrivateKey.sign

There is an option to disable the hasher, but from my experience that seems to just make it complain about byte length. So I removed one of my own SHA256 calls and I made the library do the other hash itself.

Everything works properly now.

The code I'm using can be found on the master branch of ZPyWallet here: https://github.com/ZenulAbidin/zpywallet/tree/master if you want to take a look at it. Transaction creation stuff is in zpywallet/transactions/encode.py.
staff
Activity: 3458
Merit: 6793
Just writing some code
April 30, 2024, 11:44:04 AM
#2
Alternatively, if anyone has a another P2PK transaction that comes with the expected preimage for that transaction, I'd be happy to know about it.
Although they don't contain the preimage, there are a number sighash tests at https://github.com/bitcoin/bitcoin/blob/master/src/test/data/sighash.json. These are a bit more reliable than signature tests since signatures can vary due to nonces. It also better isolates what's going wrong since you take signatures completely out of the equation.

Or is the signature valid, but just signed with openssl random nonce values instead of with libsecp256k1? That might be plausible, since this BIP is from 2017 and libsecp256k1 was made in 2019 I think.
libsecp was created in 2013, and has been in use in Core since 2014



Without being able to see your code, it's hard to say what is wrong. I've tried the examples you've provided with the preimages you provided and I am getting the expected signatures with my own tooling. This suggests that your signing code is incorrect somewhere. But without being able to see your code, it's hard to say what is actually causing the discrepancy.



Edit: With a bit more experimentation, I am able to replicate your signatures if I hash one too many times. You are hashing the sighash preimage with SHA256 3 times, not 2 times, and that's why your signature is wrong. The way signing works is that the hash function is double SHA256, and the result is directly used in the z used in the s computation. You don't hash it again since it isn't the message.
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
April 30, 2024, 06:28:02 AM
#1
I am trying to test my code against the BIP143 reference transactions at: https://en.bitcoin.it/wiki/BIP_0143#Reference_Implementation . I am stuck at the very first one (that says Native P2WPKH).

I was intending to test my segwit input signing, but since that works, I need to figure out why the P2PK input is not calculating the correct preimage for signing. (My DER signing code works correctly as well as adding the required varints and stuff to the final scriptsig).

This is my preimage for the P2PK input

Code:
0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000232103c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432aceeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac1100000001000000

After removing the sighash at the end, I have:

Code:
0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000232103c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432aceeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000

which decodes to:

{
  "txid": "66bd3593b9cc26ecf428b436a4e2e873fc9545a06e58bf519609ebaf58693831",
  "hash": "66bd3593b9cc26ecf428b436a4e2e873fc9545a06e58bf519609ebaf58693831",
  "version": 1,
  "size": 195,
  "vsize": 195,
  "weight": 780,
  "locktime": 17,
  "vin": [
    {
      "txid": "9f96ade4b41d5433f4eda31e1738ec2b36f6e7d1420d94a6af99801a88f7f7ff",
      "vout": 0,
      "scriptSig": {
        "asm": "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432 OP_CHECKSIG",
        "hex": "2103c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432ac"
      },
      "sequence": 4294967278
    },
    {
      "txid": "8ac60eb9575db5b2d987e29f301b5b819ea83a5c6579d282d189cc04b8e151ef",
      "vout": 1,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 1.12340000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 8280b37df378db99f66f85c95a783a76ac7a6d59 OP_EQUALVERIFY OP_CHECKSIG",
        "desc": "addr(1Cu32FVupVCgHkMMRJdYJugxwo2Aprgk7H)#3p63gz2n",
        "hex": "76a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac",
        "address": "1Cu32FVupVCgHkMMRJdYJugxwo2Aprgk7H",
        "type": "pubkeyhash"
      }
    },
    {
      "value": 2.23450000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 3bde42dbee7e4dbe6a21b2d50ce2f0167faa8159 OP_EQUALVERIFY OP_CHECKSIG",
        "desc": "addr(16TZ8J6Q5iZKBWizWzFAYnrsaox5Z5aBRV)#n0m4rux2",
        "hex": "76a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac",
        "address": "16TZ8J6Q5iZKBWizWzFAYnrsaox5Z5aBRV",
        "type": "pubkeyhash"
      }
    }
  ]
}


The signature DER is supposed to be:

Code:
494830450221008b9d1dc26ba6a9cb62127b02742fa9d754cd3bebf337f7a55d114c8e5cdd30be022040529b194ba3f9281a99f2b1c0a19c0489bc22ede944ccf4ecbab4cc618ef3ed01

which is on the Bitcoin Wiki page I linked, where the 01 at the end is the sighash, but this is what I get instead after double hashing the preimage:

Code:
48473044022004e3662fb98d9637af12ef69be116af28b0990319f1e883b9afade4827bcf9c702207d592e343146158d34bfa2e464e5adca67e1adde691ea1226fc5fe53ce16276a01

Since they do not provide the expected preimage value for P2PK, how am I supposed to figure out what is wrong with my transaction to sign?

Alternatively, if anyone has a another P2PK transaction that comes with the expected preimage for that transaction, I'd be happy to know about it.

Or is the signature valid, but just signed with openssl random nonce values instead of with libsecp256k1? That might be plausible, since this BIP is from 2017 and libsecp256k1 was made in 2019 I think.



here is another transaction, P2PKH this time: https://medium.com/@bitaps.com/exploring-bitcoin-signing-the-p2pkh-input-b8b4d5c4809c

Their preimage is:

Code:
0100000001449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e010000001976a914a235bdde3bb2c326f291d9c281fdc3fe1e956fe088acffffffff014062b007000000001976a914f86f0bc0a2232970ccdf4569815db500f126836188ac0000000001000000

Same as my preimage

But their signed transaction is

Code:
0100000001449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e010000006b483045022100e15a8ead9013d1de55e71f195c9dc613483f07c8a0692a2144ffa90506436822022062bc9466b9e1941037fc23e1cfadf24c8833f96942beb8f4340df60d506f784b012103969a4ac9b1521cfae44a929a614193b0467a20e0a15973cae9ba1efb9627d830ffffffff014062b007000000001976a914f86f0bc0a2232970ccdf4569815db500f126836188ac00000000

Mine is

Code:
0100000001449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e010000006b483045022100cbad2d3ab1e3fa1e485f22631024fa5f1803402e1e89a45920285a5951b9e3dc0220370e6f91dc2028bfce643d662f4e9d58fd7c797dafb7fcd466447a2a4af6fbd7012103969a4ac9b1521cfae44a929a614193b0467a20e0a15973cae9ba1efb9627d830ffffffff014062b007000000001976a914f86f0bc0a2232970ccdf4569815db500f126836188ac00000000

Different DER signatures but otherwise everything is the same.

I know that the link is using pybtc to sign its transaction which is using a custom ECDSA signer: https://github.com/bitaps-com/pybtc/blob/3d8a4962a83f07df411210bb8f7ef61ba9f9d42c/pybtc/_secp256k1/module_secp256k1.c#L145 and it also seems to be using RFC6979 r-value.

But libsecp256k1 is also using RFC6979! https://github.com/bitcoin-core/secp256k1/blob/da515074e3ebc8abc85a4fff3a31d7694ecf897b/src/secp256k1.c#L489

This explains the fact that my generated signatures are deterministic, but does this simply mean that two different valid signatures were generated? I don't think my DER itself is invalid....

TL;DR - if my preimage is identical and the rest of the transaction except for the DER is identical to a known valid transaction then can I be sure the transaction is valid? Since there is no balance I can't broadcast it.
Jump to: