I'm testing my code with the BIP143 reference transactions found at this link. I've hit a snag on the first one that deals with Native P2WPKH.
I thought my segwit input signing was working fine, but now I'm trying to sort out why the P2PK input isn't generating the right preimage for signing. My DER signing code is solid and I’m managing to add all the necessary varints and such to the final scriptsig.
Here's my preimage for the P2PK input:
Once I stripped out the sighash at the end, I have:
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"
Need help with P2PK transaction
2 replies 395 views
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.
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.
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.