Skip to content

Feat/silent payments#870

Draft
odudex wants to merge 21 commits into
developfrom
feat/silent-payments
Draft

Feat/silent payments#870
odudex wants to merge 21 commits into
developfrom
feat/silent-payments

Conversation

@odudex

@odudex odudex commented Jun 5, 2026

Copy link
Copy Markdown
Member

What is this PR for?

Implement full Silent Payments support.

It covers the extensive work done being done by @notTanveer on Silent Payments implementation on Embit and consumer projects like Krux

Changes made to:

  • Code
  • Tests
  • Docs
  • CHANGELOG

Did you build the code and tested on device?

  • Yes, build and tested on Amigo

What is the purpose of this pull request?

  • Bug fix
  • New feature
  • Docs update
  • Other

@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.20113% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.20%. Comparing base (a0924c7) to head (2b6b5d0).
⚠️ Report is 2 commits behind head on develop.

Files with missing lines Patch % Lines
src/krux/psbt.py 89.15% 18 Missing ⚠️
src/krux/pages/home_pages/home.py 55.55% 4 Missing ⚠️
src/krux/silent_payments.py 95.34% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #870      +/-   ##
===========================================
- Coverage    97.34%   97.20%   -0.14%     
===========================================
  Files           83       84       +1     
  Lines        10814    11145     +331     
===========================================
+ Hits         10527    10834     +307     
- Misses         287      311      +24     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@qlrd

qlrd commented Jun 8, 2026

Copy link
Copy Markdown
Member

4d4d797 is unrelated. Is for local tests?

@odudex

odudex commented Jun 8, 2026

Copy link
Copy Markdown
Member Author

4d4d797 is unrelated. Is for local tests?

Cherry-picked docs' hotfix from main. Should have rebased. Will do it later.
Silent payments will need to be added do docs too.

@odudex odudex marked this pull request as draft June 8, 2026 17:07
@odudex odudex force-pushed the feat/silent-payments branch 3 times, most recently from 5066b7b to d077619 Compare June 13, 2026 13:31
@odudex odudex force-pushed the feat/silent-payments branch from ef29e64 to a97118f Compare June 15, 2026 19:22
notTanveer and others added 21 commits June 17, 2026 10:52
Cover the new SP code paths added with the BIP-352 single-sig policy:
scan-key view (pub_key_view), SP address display (addresses), wallet
info (utils), derivation/policy selection (wallet_settings), the SP
login flow, and Wallet/Key SP helpers. Adds a SILENT_PAYMENT_KEY
fixture to the shared home_pages test data.
The SP scan key view exported the bare scan key expression to SD/Text
while the QR path exported the full sp(...) descriptor. Unify both on
the importable descriptor string so all export paths emit identical. Add a regression test asserting Text/SD and QR exports carry the same sp(...) descriptor.
Present the Silent Payment address as separate Text and QR menu entries,
since it is too long to fit alongside its QR code on most screens. Text
view shows 4 char blocks with alternating highlight and SD save; QR view
quick exits. Add optional bg_color to display_addr_highlighted so blocks
blend with the info box background.
Sparrow expects the bare scan key plus its [origin], not the full
sp(...) descriptor. Reverts the descriptor unification for both paths.
create_outputs assigns the BIP-352 counter k in recipient-list order,
which must match the output-index order the BIP-375 validator re-derives
in. Sorting recipients by spend key assigned mismatched k to outputs
sharing a scan key (e.g. labeled addresses of one recipient), so the
validator rejected the PSBT. Strengthen the regression test to assert
per-output scripts.
It was scanning every output and lazily importing the SP module three
times per sign; cache the result in a local.
Allow P2TR inputs (BIP-86 and BIP-376 spend-from) to fund SP outputs:
delegate input key resolution to embit so every consumer sums the same
even-Y key, gate signing on a resolvable key, and accept P2TR in
eligibility. Bumps embit to pick up P2TR resolution and the MicroPython
COutPoint fix.
…ns in SP sign

Compute wallet_nonce (PSBT serialization + SHA256) once and reuse for
both _sp_aux_rand calls, saving ~10-50KB allocation + hash per sign.

Compute _eligible_input_privkeys() once in sign() and pass to both
_populate_silent_payment_outputs and _derive_sp_output_scripts,
halving the EC scalar multiplications on K210.

Also: reuse bech32-encoded recipients list in cursor loop,
unify scan_keys_bytes/scan_key_objects into one pass
_validate_sp_signing_inputs now returns eligible indices, reused by
_eligible_input_privkeys and the post-sign assertion — eliminates 3
redundant get_eligible_inputs iterations over all inputs.

Cache has_sp_outputs result from validate() as _has_sp so sign()
skips the re-scan of every output.
chore: update Embit to latest and version
…ctors

- Add own_sp_output_type() to silent_payments.py: detects when an SP
  output pays the wallet's own BIP-352 address (label-0 → CHANGE, other
  labels/unlabeled → SELF_TRANSFER) by verifying both scan and
  label-tweaked spend keys; foreign spend key paired with our scan key
  still shows as SPEND to prevent coordinator spoofing
- Wire own_sp_output_type into _classify_output so SP change is not
  incorrectly counted as spend in the outputs() summary
- Merge _eligible_input_privkeys into _validate_sp_signing_inputs:
  returns (eligible, input_privkeys) to avoid double BIP-32 derivation
- Pass with_sp_shares=False to psbt.sign_with to skip redundant DLEQ
  re-verification of shares already populated by Krux with its own entropy
- Trim: only copy per-input sp_ecdh_shares/sp_dleq_proofs when no global
  share is present; the global fields cover non-taproot inputs without
  PSBT_IN_BIP32_DERIVATION, and dropping the duplicates shrinks the QR
- Add tests: k-ordering regression (interleaved outputs, same scan key),
  own_sp_output_type classification matrix, SP change label integration
Revert a stray keystroke in .gitignore and restore two comments
documenting why psbt.serialize() is used over psbt.tx.serialize() and
why coordinator-supplied SP fields are cleared.
Derive BIP-352 scan/spend keys from the seed when sp_keys is absent, so
own SP change/self-transfer outputs are recognized on the review screen
even when the wallet was loaded as plain single-sig instead of Silent
Payments. The cryptographic scan+spend check still gates ownership, so a
non-default SP account fails safely and the output stays a spend.
The per-instance cache pushed Key over pylint's R0902 limit (12/11).
Derive on demand instead; it is only called per SP output during review.

Also bump version to 26.06.beta1 and reformat the SP test.
Updated embit raises Bech32DecodeError instead of returning a sentinel,
so detect_encodings crashed on non-bech32 data. Guard both probe calls,
matching the other encoding detectors in the function.
@odudex odudex force-pushed the feat/silent-payments branch from a97118f to 2b6b5d0 Compare June 17, 2026 13:58
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.

3 participants