Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid Taproot signatures in transactions with non-standard sighash #65

Open
1ma opened this issue Nov 7, 2024 · 0 comments · May be fixed by #66
Open

Invalid Taproot signatures in transactions with non-standard sighash #65

1ma opened this issue Nov 7, 2024 · 0 comments · May be fixed by #66

Comments

@1ma
Copy link

1ma commented Nov 7, 2024

Apparently embit v0.8.0 produces incorrect signatures in Taproot transactions with a non-standard sighash.

The following script reproduces the issue. The unsigned PSBT has been prepared in Sparrow with SINGLE|ANYONECANPAY. We call sign_with() passing None as the sighash argument, so that the sighash defined in the psbt data is the one taken into account.

from base64 import b64decode
from embit.bip32 import HDKey
from embit.psbt import PSBT

# tprv of "aim" x12 in testnet/signet
master_private_key = 'tprv8ZgxMBicQKsPf7HFb4WqgmtZCLyuWp3qdDDMngGZUcVLK27uovLZmq87VQRzmRLNGGfuv9MmbrfDfFqYWN9UC4jU9yFPFBKznKtjJXAp6zB'
unsigned_psbt_base64 = 'cHNidP8BAF4CAAAAARfCyWIG/NiHOFrFkb34/tlVFc/N0wVIGQzWQrx0j2pLAAAAAAD9////AbBjzR0AAAAAIlEgl3d2EP+VhSPaLqFAcO3gOmaApwdP0ulTfjbhZnQkGpZNPgAATwEENYfPA6fJqKyAAAAANFK5sPQqTwnjADO2lv7oWYdTo0CWEwxtTtGDWvPUiMsD1hM7Pe2Gzg01QefANL7alLQYwxsmeyTFfH/TlstresUQnRILGVYAAIABAACAAAAAgAABAF4CAAAAARIkR5wC2SeGdLpgweIuxsxD3wICJsUWtJ3T1ZIrxsyjAAAAAAACAAAAASBkzR0AAAAAIlEg0vcpFkr36+uyRermS3owVW2WZAoX2RxiCnLL4jFfaCUAAAAAAQErIGTNHQAAAAAiUSDS9ykWSvfr67JF6uZLejBVbZZkChfZHGIKcsviMV9oJQEDBIMAAAAhFmNl9RJbp6Iz+FwX7WJG3TcKWmrvBr1tvpdVJ9n6XGUTGQCdEgsZVgAAgAEAAIAAAACAAAAAAAIAAAABFyBjZfUSW6eiM/hcF+1iRt03Clpq7wa9bb6XVSfZ+lxlEwAhByx1NQ1R+Sx4GcdHzkgnsRJh7SapmaqPBXiewFXgL3RdGQCdEgsZVgAAgAEAAIAAAACAAAAAAAMAAAABBSAsdTUNUfkseBnHR85IJ7ESYe0mqZmqjwV4nsBV4C90XQA='

xkey = HDKey.from_base58(master_private_key)

unsigned_psbt_raw = b64decode(unsigned_psbt_base64)

psbt = PSBT.parse(unsigned_psbt_raw)

sigs = psbt.sign_with(xkey, None)

print(sigs)
print(psbt.to_base64())

Output:

1
cHNidP8BAF4CAAAAARfCyWIG/NiHOFrFkb34/tlVFc/N0wVIGQzWQrx0j2pLAAAAAAD9////AbBjzR0AAAAAIlEgl3d2EP+VhSPaLqFAcO3gOmaApwdP0ulTfjbhZnQkGpZNPgAATwEENYfPA6fJqKyAAAAANFK5sPQqTwnjADO2lv7oWYdTo0CWEwxtTtGDWvPUiMsD1hM7Pe2Gzg01QefANL7alLQYwxsmeyTFfH/TlstresUQnRILGVYAAIABAACAAAAAgAABAF4CAAAAARIkR5wC2SeGdLpgweIuxsxD3wICJsUWtJ3T1ZIrxsyjAAAAAAACAAAAASBkzR0AAAAAIlEg0vcpFkr36+uyRermS3owVW2WZAoX2RxiCnLL4jFfaCUAAAAAAQErIGTNHQAAAAAiUSDS9ykWSvfr67JF6uZLejBVbZZkChfZHGIKcsviMV9oJQEDBIMAAAABCEMBQYSwoL7UpZlJvIsjQLxnFlxNdvxCFsxWQbWaKyfEgPCLZzzejYIl4gIo/LVYx+z48A0U3GxSO/5nth8ExBIJbUWDIRZjZfUSW6eiM/hcF+1iRt03Clpq7wa9bb6XVSfZ+lxlExkAnRILGVYAAIABAACAAAAAgAAAAAACAAAAARcgY2X1ElunojP4XBftYkbdNwpaau8GvW2+l1Un2fpcZRMAAQUgLHU1DVH5LHgZx0fOSCexEmHtJqmZqo8FeJ7AVeAvdF0hByx1NQ1R+Sx4GcdHzkgnsRJh7SapmaqPBXiewFXgL3RdGQCdEgsZVgAAgAEAAIAAAACAAAAAAAMAAAAA

Bitcoin Core is able to run finalizepsbt on that result, but attempting to broadcast the final transaction with sendrawtransaction results in this error:

error code: -26
error message:
mandatory-script-verify-flag-failed (Invalid Schnorr signature)

If the seed is loaded in a Sparrow wallet, Sparrow is able to sign that same PSBT and broadcast the final transaction. Comparing both final transactions can be seen that Sparrow and embit do not produce the same result byte per byte in the signature section of the transaction, and I believe these should be identical. In both cases the signature fields are 65 bytes long instead of the usual 64, and their last byte is the correct value 83 for SINGLE|ANYONECANPAY.

These are the two transactions side by side. The first one is Sparrow (broadcastable), the second one Embit's.

0200000000010117c2c96206fcd887385ac591bdf8fed95515cfcdd30548190cd642bc748f6a4b0000000000fdffffff01b063cd1d0000000022512097777610ff958523da2ea14070ede03a6680a7074fd2e9537e36e16674241a960141626d225da279392453086d8a2b79e2b9e3ea4afa0e4a4128d9311ea4cbf3b7a3adabf7c7ecdf810c506e40179934437f6e7236af211e71029e3c40d712eadd86834d3e0000
0200000000010117c2c96206fcd887385ac591bdf8fed95515cfcdd30548190cd642bc748f6a4b0000000000fdffffff01b063cd1d0000000022512097777610ff958523da2ea14070ede03a6680a7074fd2e9537e36e16674241a96014184b0a0bed4a59949bc8b2340bc67165c4d76fc4216cc5641b59a2b27c480f08b673cde8d8225e20228fcb558c7ecf8f00d14dc6c523bfe67b61f04c412096d45834d3e0000

The tests have been carried out in a custom signet network. If you want to run the exact same tests you need to connect Sparrow in signet mode to the ssl://electrum.bitcoinbarcelona.xyz:60602 electrum server. An explorer is available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant