Skip to content

Add FFI receiver checklists fuzz target - #2022

Open
caarloshenriq wants to merge 1 commit into
payjoin:masterfrom
caarloshenriq:fuzz/receiver_checklist
Open

caarloshenriq wants to merge 1 commit into
payjoin:masterfrom
caarloshenriq:fuzz/receiver_checklist

Conversation

@caarloshenriq

Copy link
Copy Markdown
Contributor

Adds ffi-receiver-checklists, a fuzz target for the receiver's first four checks through payjoin-ffi: broadcast suitability, inputs owned, inputs seen and outputs owned.

Each check is exposed to the host twice. One way is a callback (check_inputs_not_owned(Arc<dyn IsInputOwned>)). The other is a checklist the host fetches, marks and hands back (inputs_owned_checklist, mark, apply_inputs_owned_checklist). The checklist path is FFI surface the core targets don't reach, and nothing stops a host from returning it reordered, incomplete, or marked for a different session.

What the fuzzer controls

The input is decision bytes read through Unstructured, with no custom mutator. The target rebuilds the original PSBT from the RetrievedOriginalPayload seed in seeds/receiver.jsonl:

  • Inputs: 1 to 4, each with a mutated txid and vout, and occasionally a different prevout value, prevout script, or no final signatures, since the fee rate check predicts input weight from those.
  • Outputs: 1 to 4, with scripts from a small table (P2SH, P2WPKH, P2TR, OP_RETURN) or raw bytes.
  • Host answers: per item for each check, plus a min fee rate that is usually realistic and occasionally a raw u64 for the FFI range validation.
  • Tampering: the marked checklist can be reversed, have an item dropped, duplicated or swapped, be cleared, or get items from a second, foreign receiver built the same way.
  • Failures: a callback can fail at any item, and the host's storage can refuse a save.
  • Persistence: each save goes through either the sync or the async persister adapter.

Choices that end the session early are decoded as rare ones (one in eight). An empty input passes all four checks.

Fuzzing results

From an empty corpus on aarch64 macOS, 600 seconds, one job:

Metric Value
Executions 569,493
Coverage counters reached 5490
Feature edges 18758
Corpus size 792 inputs
Crashes / OOM / Timeouts 0 / 0 / 0

A follow up run with 6 forks for 790 seconds reached 5501 counters with 0 / 0 / 0, so coverage of the four checks is saturated. Throughput is about 950 exec/s on one job, since every save is followed by a replay.

Addresses part of #1267.

Assigning @benalleng to review.

Disclosure: co-authored by Claude

Pull Request Checklist

Please confirm the following before requesting review:

Each of the receiver's first four checks (broadcast suitability,
inputs owned, inputs seen, outputs owned) is exposed through the FFI
twice: as a host callback, and as a checklist the host marks and
hands back. The checklist path is new FFI surface, and a host can
return it reordered, incomplete or marked for another session.

Fuzz both paths from fuzzer-shaped original PSBTs and assert that
for the same answers they persist the same events, that a checklist
not matching this receiver's own values is rejected without
persisting anything, that a failing callback or failing storage
never advances the session, and that the log plus what was persisted
replays to the state the transition reported. Saves alternate
between the sync and async persister adapters, so every comparison
also checks that the two agree.
@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 40973224615

Coverage remained the same at 87.547%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 17947
Covered Lines: 15712
Line Coverage: 87.55%
Coverage Strength: 320.75 hits per line

💛 - Coveralls

This branch has not been deployed

No deployments
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

Successfully merging this pull request may close these issues.

2 participants