nutshell icon indicating copy to clipboard operation
nutshell copied to clipboard

Mint: When proofs are used, store whether they were fees or not

Open KvngMikey opened this issue 3 months ago • 3 comments

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.py to 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.py to simulate Lightning routing fees and verify that: • fee_paid values are correctly recorded in melt_quotes. • proofs used for fees are stored with is_fee = 1 and corresponding fee_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

image

KvngMikey avatar Oct 10 '25 20:10 KvngMikey

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?

callebtc avatar Oct 19 '25 17:10 callebtc

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.

KvngMikey avatar Oct 25 '25 21:10 KvngMikey

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.

KvngMikey avatar Oct 27 '25 00:10 KvngMikey