pay: domain-separate tip and make legacy signature acceptance one switch #193
Loading…
Reference in a new issue
No description provided.
Delete branch "onionwire/t_438331aa-close-the-legacy-signature-surface-and-d"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
tipwas the one payment frame with no domain tag. This PR gives it one, and turns the scattered v1 fallbacks into a single switch.Code
tipv2.sign_tipnow signs"onionwire-tip-v1" || 0x00 || txid || 0x00 || amount_atomic || 0x00 || address || 0x00 || memo || 0x00 || ascii(ts), mirroringinv/rcp(the tag keeps the historical-v1suffix; the function follows the existing*_v2naming).verify_tiptries v2, then the LF layout.encode_tip/decode_tipare unchanged — only the signed bytes move.pay::LEGACY_SIGS: bool = truepluspay::legacy_sigs(). Every listed fallback reads it: theonionwire:v1invite string (both historical forms),loc,inv,rcp, andtip. With it off, only the tagged form verifies. It is not a wire field and is not negotiable.prfis not gated here.src/profile.rsis outside this card's file scope, so its legacy fallback stays unconditional; both the code doc and the spec say so explicitly rather than implying the switch is total.Tests
Legacy on (default):
legacy_untagged_loc_still_verifies,legacy_untagged_prf_still_verifies,legacy_untagged_inv_still_verifies,legacy_untagged_rcp_still_verifies, newlegacy_untagged_tip_still_verifies; invite side keepswell_formed_v1_concat_still_decodes(insrc/qr.rs) andinvite_v1_still_decodes_to_a_classical_friend_rowgreen.Legacy off (
pay::with_legacy_sigs(false, ...), a scoped thread-local test hook — restored by RAII, no cross-test state):legacy_off_rejects_untagged_loclegacy_off_rejects_untagged_invlegacy_off_rejects_untagged_rcplegacy_off_rejects_untagged_tiplegacy_off_rejects_v1_invite_but_v2_still_decodesEach asserts both halves: the untagged form is rejected and the tagged form still verifies; the
loc/inv/rcp/tiptests also assert acceptance returns after the scope exits.Tip round-trip:
tip_frame_roundtrip_and_wrong_key(emit → encode → decode → verify) stays green, and newtip_emits_tagged_form_onlypins thatsign_tip's signature does not verify over the LF-joined layout (so encode is v2-only) and that the memo is covered.Verification (this worktree, host target)
One earlier run failed
wallet_child::tests::a_start_that_fails_after_the_daemon_came_up_leaves_nothing_runningwithAddress already in use (os error 98): another kanban worker's suite held 18080 at the same time. On a re-run with the port free it passes; it is fixed-port test contention, not this diff.Spec
docs/PROTOCOL.md: the intro now namestipamong tagged frames, adds theLEGACY_SIGSparagraph, the per-frame emitted / accepted inbound table, and the mixed-fleet consequence (an old peer cannot verify a new taggedtipuntil it updates; the reverse direction works while the switch is on; turning it off is a fleet-wide cutover). The per-frameLegacy accept:sentences and thetipsignature block are updated in the same diff — leaving them would contradict the table. No other doc sections touched;docs/THREAT_MODEL.mduntouched.Notes
assert_eq!on wire strings was weakened; thetipprefix and LF frame layout are unchanged, only the signed preimage.src/pay.rs,src/loc.rs,src/qr.rs,tests/app_sig.rs,tests/qr.rs,docs/PROTOCOL.md.