lightninglabs / neutrino

Privacy-Preserving Bitcoin Light Client
MIT License
894 stars 182 forks source link

filter validation error: "pk script wasn't matched by filter" #257

Closed pinheadmz closed 1 year ago

pinheadmz commented 1 year ago

I got this error message when syncing LND with neutrino:

2022-08-30 07:35:47.700 [ERR] BTCN: filter for block
000000000000000000062a351fa538152b80fdbe3e46c14ea4f0e1c2b1ca1155
might be invalid, input 0 of tx
d111fd02dd27c528d358deb62b83823be6f06d00cd16a01bad1c570bd395b306
spends pk script
0020712cb69185e9467eff249d658ee376f1a5b3f7ef01695c372adccf6dc3df0389
which wasn't matched by filter.
The input likely spends a taproot output which is not yetsupported

I did indeed fund the wallet with a taproot address (cool!) but looking at https://github.com/lightninglabs/neutrino/pull/215 I think this might be a bug. I don't see in BIP158 spec nor in the bitcoin core implementation that redeem scripts (from the witness) are expected to be included in the filter. So without trying it, I expect that even witness v0 scripts will also throw this error. In a sense, if I'm correct, NO output type is supported in this way.

LND wallet did act correctly and I was able to fund a channel and send a LN payment using neutrino, because the actual output script (just the witness program, aka p2tr address) IS included in the filter as expected.

I also realize that the script in the log message 0020712cb69185e9467eff249d658ee376f1a5b3f7ef01695c372adccf6dc3df0389 IS the witness program, so I am really confused.

Also note the tiny nit in the log message, missing space, due to the code style here:

https://github.com/lightninglabs/neutrino/blob/0c79b771272b4d55527c8e2017963fec2cfb5bd4/verification.go#L144-L149

guggero commented 1 year ago

Yeah, the error is a bit misleading. What is committed to the filter are all pk scripts of all outputs as well as the pk scripts of the inputs being spent. For segwit v0 you can always calculate the pk script of an output that's being spent by looking at the witness of the input that's spending it. For p2wkh you have the pubkey in there that you can hash, for p2wsh you have the full script that you can hash.

Because we want to detect peers that don't create filters properly, we do try to verify each filter of each block from each peer.

With that being said, the challenge with Taproot is that for a key spend, we cannot re-calculate the pk script, since the witness only contains a signature and no public key. And that's when the error is being logged.

The script that's being logged is just the p2wsh script for the hash of the signature. Basically the default case here: https://github.com/btcsuite/btcd/blob/master/txscript/pkscript.go#L263

Perhaps we should just add an extra if for a witness that's exactly one element of 64 or 65 bytes and just ignore that in the validation (as we won't be able to re-calculate the pk script anyway).

pinheadmz commented 1 year ago

Ahhhh that makes sense thanks, and clever! I see the issue with the taproot spends and actually I should've realized that the pk script that LND is complaining about is actually a witness version 0 program, so it makes sense that it's not included in the filter because thats the wrong output script!