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

Embit doesn't sign a PSBT input without fingerprint #41

Closed
tadeubas opened this issue Feb 16, 2023 · 4 comments
Closed

Embit doesn't sign a PSBT input without fingerprint #41

tadeubas opened this issue Feb 16, 2023 · 4 comments

Comments

@tadeubas
Copy link

tadeubas commented Feb 16, 2023

I've created a Sparrow Watch Only Wallet on the testnet with the default Master fingerprint = 00000000 (8 zeros)

tpubDCberYHnzBMaKUa34hXGTNXECt9bKprGKtqYt2Bm4qGFK3bqMkMA6KxRR1kPPSh73QoX6LtmsArgNYXRw8HnkWwc8ywf7Ru6XcxRnJo9HfW

Then created a simple transaction and copied the PSBT as Base64 (you can use https://bip174.org/ to see the Inputs, Outputs and values in a human readable way 😄) :

cHNidP8BAHECAAAAAZAnIjvbN8fqgDLA4n0UGRa8y9hixeRh0lyqqzD5xV4KAQAAAAD9////AkEHAAAAAAAAFgAU+P+L3Sh4fvIiFSg9ApKpmj0aRuroAwAAAAAAABYAFEwgsWYuLvNbH+CaJF4BkGacPs3p7uwkAE8BBDWHzwNOAaDGgAAAAA6sE2xHBRocbxB2m7sG3JvBy6PH2P+6FU8Xz26TLNf+Ax8/bmYn6gHZ6KY5opTh2Ajf+3sKBpZ40s59aYtcEnY+EAAAAABUAACAAQAAgAAAAIAAAQBxAgAAAAGeomnbab30E8l/NgBlX2NSEHnKRoS/JrHaHRmS3TaiBwAAAAAA/v///wJMyxMAAAAAABYAFAre1yrqM0lajsrS+XaPhFl3ySrkuAsAAAAAAAAWABRzQTmBnB9S0JrKpdz0MZIFJDr2eNDsJAABAR+4CwAAAAAAABYAFHNBOYGcH1LQmsql3PQxkgUkOvZ4AQMEAQAAACIGA2SK/HlpQsji9MlfrvLP/jBs5FFegxl1PoBlvFlo6mOkGAAAAABUAACAAQAAgAAAAIAAAAAAAgAAAAAiAgI681B3eYesw1GS6BWKm9qpAqWRSqkpWtc39XMEQSXt9xgAAAAAVAAAgAEAAIAAAACAAQAAAAAAAAAAIgIC7VCWFEldnuNNptwFF9p3PMnUfAxbtOCh5/Xnx2WKwBMYAAAAAFQAAIABAACAAAAAgAAAAAADAAAAAA==

Finally I tried to sign the PSBT input with the fingerprint 00000000, but because fingerprint doesn't match, Embit didn't try to sign, even if the key can sign. As seen on psbt.py: https://github.com/diybitcoinhardware/embit/blob/master/src/embit/psbt.py#L898

Then I place the Master fingerprint accordingly e0c595c5, and now Embit sign the PSBT:

cHNidP8BAHECAAAAAZAnIjvbN8fqgDLA4n0UGRa8y9hixeRh0lyqqzD5xV4KAQAAAAD9////AugDAAAAAAAAFgAUTCCxZi4u81sf4JokXgGQZpw+zelDBwAAAAAAABYAFPj/i90oeH7yIhUoPQKSqZo9Gkbq7uwkAE8BBDWHzwNOAaDGgAAAAA6sE2xHBRocbxB2m7sG3JvBy6PH2P+6FU8Xz26TLNf+Ax8/bmYn6gHZ6KY5opTh2Ajf+3sKBpZ40s59aYtcEnY+EODFlcVUAACAAQAAgAAAAIAAAQBxAgAAAAGeomnbab30E8l/NgBlX2NSEHnKRoS/JrHaHRmS3TaiBwAAAAAA/v///wJMyxMAAAAAABYAFAre1yrqM0lajsrS+XaPhFl3ySrkuAsAAAAAAAAWABRzQTmBnB9S0JrKpdz0MZIFJDr2eNDsJAABAR+4CwAAAAAAABYAFHNBOYGcH1LQmsql3PQxkgUkOvZ4AQMEAQAAACIGA2SK/HlpQsji9MlfrvLP/jBs5FFegxl1PoBlvFlo6mOkGODFlcVUAACAAQAAgAAAAIAAAAAAAgAAAAAiAgLtUJYUSV2e402m3AUX2nc8ydR8DFu04KHn9efHZYrAExjgxZXFVAAAgAEAAIAAAACAAAAAAAMAAAAAIgICOvNQd3mHrMNRkugVipvaqQKlkUqpKVrXN/VzBEEl7fcY4MWVxVQAAIABAACAAAAAgAEAAAAAAAAAAA==

Why this is bad? It is important because the Master fingerprint information is not relevant for the signing process, I know lots of tutorials that only teach to stores the XPUB and derivation path info for a Watch Only wallet. Electrum on Android doesn't even show to the user the Master fingerprint of the wallet.

BlueWallet also uses the 00000000 fingerprint as default to Watch Only wallets, and you only see this info if you enable the Advanced Mode in Settings > General (and you can't change the master fingerprint value, even if it is 00000000):

Here is what Sparrow says about the Master fingerprint The master fingerprint uniquely identifies this keystore using first 4 bytes of the master public key hash. It is safe to use any valid value (00000000) for Watch Only Wallets:
image

And here is the sequence that shows this bad behavior on Embit code:

from embit.networks import NETWORKS
from embit import bip32, bip39
from embit.psbt import PSBT

mnemonic = "action action action action action action action action action action action action"
seed = bip39.mnemonic_to_seed(mnemonic)
root = bip32.HDKey.from_seed(seed, version=NETWORKS["test"]["xprv"])

# PSBT as Base64 from Sparrow Watch Only Wallet
fingerprint_00000000 = "cHNidP8BAHECAAAAAZAnIjvbN8fqgDLA4n0UGRa8y9hixeRh0lyqqzD5xV4KAQAAAAD9////AkEHAAAAAAAAFgAU+P+L3Sh4fvIiFSg9ApKpmj0aRuroAwAAAAAAABYAFEwgsWYuLvNbH+CaJF4BkGacPs3p7uwkAE8BBDWHzwNOAaDGgAAAAA6sE2xHBRocbxB2m7sG3JvBy6PH2P+6FU8Xz26TLNf+Ax8/bmYn6gHZ6KY5opTh2Ajf+3sKBpZ40s59aYtcEnY+EAAAAABUAACAAQAAgAAAAIAAAQBxAgAAAAGeomnbab30E8l/NgBlX2NSEHnKRoS/JrHaHRmS3TaiBwAAAAAA/v///wJMyxMAAAAAABYAFAre1yrqM0lajsrS+XaPhFl3ySrkuAsAAAAAAAAWABRzQTmBnB9S0JrKpdz0MZIFJDr2eNDsJAABAR+4CwAAAAAAABYAFHNBOYGcH1LQmsql3PQxkgUkOvZ4AQMEAQAAACIGA2SK/HlpQsji9MlfrvLP/jBs5FFegxl1PoBlvFlo6mOkGAAAAABUAACAAQAAgAAAAIAAAAAAAgAAAAAiAgI681B3eYesw1GS6BWKm9qpAqWRSqkpWtc39XMEQSXt9xgAAAAAVAAAgAEAAIAAAACAAQAAAAAAAAAAIgIC7VCWFEldnuNNptwFF9p3PMnUfAxbtOCh5/Xnx2WKwBMYAAAAAFQAAIABAACAAAAAgAAAAAADAAAAAA=="
fingerprint_e0c595c5 = "cHNidP8BAHECAAAAAZAnIjvbN8fqgDLA4n0UGRa8y9hixeRh0lyqqzD5xV4KAQAAAAD9////AugDAAAAAAAAFgAUTCCxZi4u81sf4JokXgGQZpw+zelDBwAAAAAAABYAFPj/i90oeH7yIhUoPQKSqZo9Gkbq7uwkAE8BBDWHzwNOAaDGgAAAAA6sE2xHBRocbxB2m7sG3JvBy6PH2P+6FU8Xz26TLNf+Ax8/bmYn6gHZ6KY5opTh2Ajf+3sKBpZ40s59aYtcEnY+EODFlcVUAACAAQAAgAAAAIAAAQBxAgAAAAGeomnbab30E8l/NgBlX2NSEHnKRoS/JrHaHRmS3TaiBwAAAAAA/v///wJMyxMAAAAAABYAFAre1yrqM0lajsrS+XaPhFl3ySrkuAsAAAAAAAAWABRzQTmBnB9S0JrKpdz0MZIFJDr2eNDsJAABAR+4CwAAAAAAABYAFHNBOYGcH1LQmsql3PQxkgUkOvZ4AQMEAQAAACIGA2SK/HlpQsji9MlfrvLP/jBs5FFegxl1PoBlvFlo6mOkGODFlcVUAACAAQAAgAAAAIAAAAAAAgAAAAAiAgLtUJYUSV2e402m3AUX2nc8ydR8DFu04KHn9efHZYrAExjgxZXFVAAAgAEAAIAAAACAAAAAAAMAAAAAIgICOvNQd3mHrMNRkugVipvaqQKlkUqpKVrXN/VzBEEl7fcY4MWVxVQAAIABAACAAAAAgAEAAAAAAAAAAA=="

psbt = PSBT.from_string(fingerprint_00000000)
value = psbt.sign_with(root)

trimmed_psbt = PSBT(psbt.tx)
for i, inp in enumerate(psbt.inputs):
    trimmed_psbt.inputs[i].partial_sigs = inp.partial_sigs

print(value) # == 0
print(trimmed_psbt) # == cHNidP8BAHECAAAAAZAnIjvbN8fqgDLA4n0UGRa8y9hixeRh0lyqqzD5xV4KAQAAAAD9////AkEHAAAAAAAAFgAU+P+L3Sh4fvIiFSg9ApKpmj0aRuroAwAAAAAAABYAFEwgsWYuLvNbH+CaJF4BkGacPs3p7uwkAAAAAAA=

psbt = PSBT.from_string(fingerprint_e0c595c5)
value = psbt.sign_with(root)

trimmed_psbt = PSBT(psbt.tx)
for i, inp in enumerate(psbt.inputs):
    trimmed_psbt.inputs[i].partial_sigs = inp.partial_sigs

print(value) # == 1
print(trimmed_psbt) # == cHNidP8BAHECAAAAAZAnIjvbN8fqgDLA4n0UGRa8y9hixeRh0lyqqzD5xV4KAQAAAAD9////AugDAAAAAAAAFgAUTCCxZi4u81sf4JokXgGQZpw+zelDBwAAAAAAABYAFPj/i90oeH7yIhUoPQKSqZo9Gkbq7uwkAAAiAgNkivx5aULI4vTJX67yz/4wbORRXoMZdT6AZbxZaOpjpEcwRAIgI+SNJrEAVfkb4wlhlj+eEISmo4Mnj1z7AXLrZEQA3CgCICrjsVdmaeGMMStHF+aEpNHKHpFyAMdmj3SI9SZlyrP4AQAAAA==
@tadeubas tadeubas changed the title Error when signing a transaction from Sparrow Watch Only Wallet Error when trying to sign a PSBT without input fingerprint Aug 19, 2023
@tadeubas tadeubas changed the title Error when trying to sign a PSBT without input fingerprint Embit doesn't sign a PSBT input without fingerprint Aug 19, 2023
@tadeubas
Copy link
Author

@stepansnigirev what is your opinion on this? There is any workaround to sign a PSBT input without fingerprint?

@stepansnigirev
Copy link
Contributor

One option would be to go through all bip32 derivations in psbt and replace 00000000 fingerprint with the root fingerprint you want to sign with. Then it should sign.

But generally I think it's better if you set master fingerprint to sparrow.

@stepansnigirev
Copy link
Contributor

And this is not a "bad behavior of embit code". It is invalid use of psbt fields.

@tadeubas
Copy link
Author

Thx for the response! I will investigate further, but I don't think that going to all bip32 derivations is really necessary, I don't know how Sparrow and BlueWallet does this, but both can sign a PSBT that has input(s) without a fingerprint. If this is what is expected from Embit code I will close the issue.

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

No branches or pull requests

2 participants