Does `blinded_payinfo` refer to the recipient or the intro node
Its not specified, and it turns out we were inconsistent between what we generated and what our pathfinder used (yay fuzzing!).
I'm not sure what you mean by "refer to"? Do you mean in which node's payload this is included? Or which node_id it points to?
Ha, sorry, this was indeed unclear. I meant "which node in the path has to meet the provided htlc_min/htlc_max/cltv_expiry". The spec doesn't specify.
For path-finding, a blinded path is equivalent to a single channel. And just like a channel, it has fees, minimum and maximum amounts, and CLTV expiry delta, that's blinded_payinfo.
A HTLC that arrives at the first node of the blinded path must satisfy the requirements of blinded_payinfo or it will be rejected.
Gotcha, that's clearer! Indeed, we should clarify that this applies to the whole blinded path: the htlc_min and htlc_max apply to every channel in that blinded path, and the cltv_expiry as well (every node in the blinded path must ensure that the HTLC's expiry is lower than the cltv_expiry).
Wait, the two of you just said different things, though - @thomash-acinq said that the HTLC that arrives at the first node must satisfy the requirements but then @t-bast said that the values apply to "every channel in the blinded path". Those are different.
The specific case where it came up for us may be illustrative - we are treating the blinded path as a single hop for pathfinding purposes, but our fuzzer decided that this was an invalid path. Specifically, the fuzzer was looking at the total in-flight over the blinded path (including the fee, since the fee could be taken by a later hop) and making sure it doesn't exceed the blinded path's htlc-max. But, for a normal hop, we wouldn't do that - the fee is always taken directly by the node in question, so we wouldn't include the fee in the in-flight amount over the outbound edge.
In your specific case, the total in-flight should not include the fee. It is the responsibility of the creator of the blinded route to make sure that it behaves exactly like a single channel would.
For instance if you want to blind the route A -> B -> C where A -> B has htlc-max=100 and fee-base=2, and B -> C has htlc-max=1000 and fee-base=5 (we assume no proportional fee for simplicity), then blinded_payinfo for the whole route would be htlc-max=95 and fee-base=7. In practice, to preserve privacy, you would set htlc-max a bit lower (let's say 90) and hide the true fee-base too (in eclair we can set it to 0 and pay the fees ourselves).
Sure, that was my understanding as well, but I was noting that the BOLTs are unclear and wanted to make sure people were doing the same thing (and it sounds like @t-bast at least was on a different page!).
Either way, point is the BOLTs need to be clarified.
it sounds like @t-bast at least was on a different page!
Unless I'm missing something, we are on the same page, I discussed that with Thomas offline and we agree on the behavior, I just probably poorly explained it in english, code (or spec) is easier to express that!