Open moneymanolis opened 1 year ago
For a strange reason, this is only a problem until specter is rebooted. Then it disappears. At least i know roughly what's the case here: the taproot transaction is not be considered as ismine
. This is implemented like this:
@property
def ismine(self) -> bool:
if self.get("ismine"):
return self["ismine"]
inputs = self.psbt.inputs
outputs = self.psbt.outputs
any_inputs_mine = any([inp.is_mine for inp in inputs])
any_outputs_mine = any([out.is_mine for out in outputs])
self["ismine"] = any_inputs_mine or any_outputs_mine
return self["ismine"]
The psbt is created like this:
@property
def psbt(self) -> SpecterPSBT:
"""This tx but as a psbt. Need rpc-calls"""
if hasattr(self, "_psbt"):
return self._psbt
self._psbt: SpecterPSBT = self.PSBTCls.from_transaction(
self.tx, self.descriptor, self.network
)
# fill derivation paths etc
updated = self.rpc.walletprocesspsbt(str(self._psbt), False).get("psbt", None)
if updated:
self._psbt.update(updated)
return self._psbt
As this needs to be an issue for the output as the output needs to be ismine
, the SpecterOutputScope.ismine implementation:
@property
def is_mine(self) -> bool:
return self.descriptor.owns(self.scope)
@stepansnigirev can you see any reason why taproot transactions have trouble here?
I've figured out that the cache has the right values but the implementations which are SUPPOSE to calculate the cached value does not:
So there is somewhere some taproot magic which i'm not aware of.
If Bitcoin Core does not add taproot fields into PSBT, the descriptor can't verify that the output belongs to the descriptor. What version of Core do you use?
Oh wait... Specter is creating psbt from transaction itself, then probably the problem is with taproot fields that we don't add in the code.
I'm using:
"version": 220000,
"subversion": "/Satoshi:22.0.0/",
Here is the psbt from that tx.
Yes, as you see, inputs and outputs don't contain derivation information, so descriptor.owns()
always returns False
.
With non-taproot wallets walletprocesspsbt
rpc call populates PSBT with derivation information, but not for taproot:
https://github.com/cryptoadvance/specter-desktop/blob/fa9605d6c955f46bce441c759f6bf799a8c74ab3/src/cryptoadvance/specter/txlist.py#L321
It could be that Bitcoin Core 23 does it, but I didn't check
But then, how does the right information gets into the cache? My gues is that the super-confusing fetch_transaction-method does that in this section:
Update: That assumption was wrong.
Maybe wallet.fill_psbt
can help to get full information.
https://github.com/cryptoadvance/specter-desktop/blob/ff94b0651123426843786d2a3f07bcc2392673a0/src/cryptoadvance/specter/wallet.py#L1943
Yes, another way is to check if addresses used in inputs and outputs belong to the wallet.
It's an amazing feature. I'll call that from now on an Heisenberg Feature.
Update:Ok, i have the "feature". The value in the csv was "false". And we have a type_converter
which is bool, but:
>>> bool("False")
True
>>>
The result of fill_psbt
would look like this:
So this looks like exactly the original psbt.
Update: Bitcoin core can't see this fields as that is the point of the fill_psbt method. So decoding it with the help of Core is useless.
Output contains "unknown" fields that are actually taproot derivations. Bitcoin Core doesn't know what they mean but embit descriptor should be able to detect owned outputs
A sideeffect of the mitigation of this issue is that the amounts are broken on taproot because is_mine
doesn't work properly on the in-/outputs but that's essential to calculate the amounts.
(Screenshot from revamp branch but same on master)
Steps to reproduce
Create a Taproot wallet, send regtest funds to it from a Segwit wallet to produce an UTXO for the Taproot wallet.
Stacktrace