Mint: When proofs are used, store whether they were fees or not
Fixes #725
Summary
This PR introduces a new fee tracking infrastructure for Lightning melts in the Cashu mint. It enables the system to record proofs used for fee payments, classify fee types, and store the actual fee amounts. This feature improves accounting transparency and auditability without changing existing mint or melt behavior.
Changes
-
Added new
migration m028_add_fee_tracking_to_proofs_used: • Adds is_fee, fee_type, and fee_amount columns to proofs_used table. • Creates index on (is_fee, fee_type) for efficient querying. -
Extended invalidate_proof() in
crud.pyto record optional fee-related metadata (is_fee, fee_type, fee_amount). -
Updated
ledger._invalidate_proofs()to propagates fee parameters and logs fee-related proof invalidation events.
Local Testing
- I added for local testing purposes but removed an experimental internal fee computation logic in
melt_mint_settle_internally()before creating this PR, with it's exclusion, mint–mint melts remain fee-free. - I also modified
fakewallet.pyto simulate Lightning routing fees and verify that: •fee_paidvalues are correctly recorded inmelt_quotes. • proofs used for fees are stored withis_fee = 1and correspondingfee_amount.
Tested with local DB Queries
SELECT 'TOTAL_PAYMENT_PROOFS' AS category, COUNT(*) AS count, SUM(amount) AS total_amount FROM proofs_used WHERE melt_quote IS NOT NULL UNION ALL SELECT 'FEE_PROOFS_ONLY', COUNT(*), SUM(amount) FROM proofs_used WHERE is_fee = 1 AND melt_quote IS NOT NULL;
Result
TOTAL_PAYMENT_PROOFS|90|9050 FEE_PROOFS_ONLY|2|264
hey, thank you for your PR.
I'm not sure if this would work. If someone swaps a single proof, say 1024 sats, and we return 1023 sats, and keep 1 sat fee, how would that be accounted for?
hey, thank you for your PR.
I'm not sure if this would work. If someone swaps a single proof, say 1024 sats, and we return 1023 sats, and keep 1 sat fee, how would that be accounted for?
this is a great catch, i'll fix this.
thanks once again @callebtc for catching this, i've now made the swap() method detect implicit fees when the sum of input proofs exceeds the sum of output amounts, and passes that fee_amount into _invalidate_proofs() and also updated the _invalidate_proofs function.