Repository navigation
Conversation
The mock LSPS2 service needs the opening fee to check `lsps2.buy` requests and to deduct it when forwarding. Write it from the bLIP-52 text, with every operation checked against the unsigned 64-bit range as the spec requires, instead of reusing the client's code: a bug shared by client and mock would go unnoticed by the tests. The spec's pseudocode divides by 10000000 and its prose mentions `+ 9999999`; both contradict the definition of `proportional` in parts per million and the spec's own C and Rust versions, which this follows.
Until now the mock deducted a fixed `htlc.fee_msat` (default 0) and did none of the fee checks bLIP-52 asks of an LSP. Compute the fee instead: - `lsps2.buy` with a `payment_size_msat` fails with 202 if the fee is not below the payment size and with 203 if computing it overflows. - In no-MPP+var-invoice mode the fee comes from the first HTLC, which is failed with unknown_next_peer if it is outside the payment size limits, if the fee overflows or if nothing would be left to forward. - The honest deduction is the computed fee; `htlc.fee_msat` still overrides it. Failed HTLCs now record why they were failed.
bLIP-52 lets the LSP open the JIT channel only while the current time is before the params' valid_until. The mock checked valid_until at lsps2.buy only, so it still opened channels for expired params. Fail parts that arrive once the params expired with unknown_next_peer. htlc.clock_offset_seconds moves the clock of that check, so a test can expire a session without waiting.
Held parts were failed only when another part arrived after valid_until. bLIP-52 asks for a separate timeout at valid_until for all pending parts, so arm a timer when a session starts holding parts. Moving the mock's clock past valid_until fails them as well, so tests do not wait in real time.
Every LSPS2 client test should end by checking the same invariants on what the client did, whatever the mock service misbehaved in. Add tests/lsps2_oracles.py with the first two: - Amount: a paid invoice received at least its amount minus the opening fee it owes (none for payments after the session), and the client holds no more in channels its peers opened than its paid invoices received. - Identity: invoices route only through known channels or through the LSP on a jit_channel_scid it issued to this client, and the only channel used before its funding confirms is the session's. The checks work on an Observation snapshot of plain data, gathered from the client and the mock's state, so they are unit tested on hand- written runs. For that the mock now timestamps its events, reports the params it issued and remembers which payment opened each session. The honest JIT tests now run the oracles.
Expired, contradictory or modified params must never lead to a payment. Two checks: - Every lsps2.buy the client sent uses params exactly as the LSP issued them, before valid_until, with usable payment size limits, a payment size the fee does not eat up, and a promise of at most 512 bytes of printable ASCII without '"' or '\'. - Every LSPS2 invoice follows the buy result the client was sent: the lsp_cltv_expiry_delta in a route hint without fees, an expiry no later than valid_until and the payment size as amount.
The last oracle for the LSPS2 client tests: the LSPS client plugin is still running and never crashed, no HTLC is left pending in the client's channels, and the client sent no more than 20 LSPS requests. check_oracles first waits for the client's HTLCs to settle, so that a check does not race a payment still in flight.
A client that accepts a part whose extra_fee does not match what was deducted from it breaks bLIP-52 even when the total deducted happens to be the right fee, and the amount oracle did not see that. Check that each part of a paid invoice arrived short by exactly its extra_fee and that the extra_fees add up to at most what the payment owes.
The LSPS2 service is to leave Core Lightning, so the client tests need a counterpart that does not depend on it. Run each client test that uses the in-tree service against both it and the mock service, which serves the same opening fee menu as the policy plugin. Nothing in the tests changes for the in-tree service; dropping it later only drops its parameter. With the mock, the JIT channel tests also check the oracles. The non-approved zero-conf test makes its invoice itself, so the checks on how the client makes invoices do not apply there.
The MPP+fixed-invoice test ran the in-tree service with an earlier Python mock taking over its HTLC handling, because the service does not support MPP. Run it against the mock service instead, which collects the parts, opens the channel and spreads the opening fee over the parts itself, and remove the earlier mock. The fee stays at 1000000 msat, now computed from a proportional rate, and the test gains the checks of the mock's own MPP test, which it replaces: how the fee is spread over the parts, the invoice status and the oracles.
The tests of the LSPS2 client against a misbehaving LSP go into their own file and need the same helpers to set up nodes and talk to the mock service. Move them out of test_cln_lsps.py, unchanged.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
26.09 FREEZE August 5th: Non-bugfix PRs not ready by this date will wait for 26.12.
RC1 is scheduled on August 17th
The final release is scheduled for September 7th.
Checklist
Before submitting the PR, ensure the following tasks are completed. If an item is not applicable to your PR, please mark it as checked:
tools/lightning-downgradeBuilds on 9657, only the last 3 commits are new.
in-tree/mock). The in-tree variant is unchanged. With the mock, the JIT channel tests also run the invariant checks.tests/lsps2_mock_helpers.pyso that other test files can use them.Removing the in-tree service later only means dropping its parameter.
Changelog-None