Implement fee savings and privacy metrics for payjoin outcomes#2
Implement fee savings and privacy metrics for payjoin outcomes#20xZaddyy wants to merge 1 commit intopayjoin:masterfrom
Conversation
Mshehu5
left a comment
There was a problem hiding this comment.
Nice to see you contributing to this !
just have a couple of niits and questions
| let base_savings_sats = 150.0; | ||
|
|
||
| // Larger amounts might justify slightly higher fee savings due to more inputs | ||
| // Cap at 2x for very large amounts | ||
| let amount_factor = (amount / 100000.0).min(2.0); | ||
| let total_savings = (base_savings_sats * (1.0 + amount_factor * 0.2)) as u64; | ||
|
|
||
| Amount::from_sat(total_savings) | ||
| } | ||
|
|
||
| /// Calculate privacy score for a payjoin | ||
| /// Higher scores indicate better privacy benefits | ||
| fn calculate_payjoin_privacy_score(amount: f64) -> f64 { | ||
| // Base privacy benefit from transaction structure obfuscation | ||
| let base_privacy = 10.0; | ||
|
|
||
| // Larger amounts get slightly higher privacy scores as they're more valuable to hide | ||
| // Log scaling, capped at 1.0 | ||
| let amount_factor = (amount / 100000.0).ln_1p().min(1.0); | ||
|
|
||
| // Random timing component (simplified - in reality depends on network timing) | ||
| let timing_privacy = 2.0; | ||
|
|
||
| base_privacy + (amount_factor * 5.0) + timing_privacy |
There was a problem hiding this comment.
niit : Since some of these are hardcode maybe const world be better
e.g
+const BASE_PRIVACY_SCORE: f64 = 10.0;
+const TIMING_PRIVACY_BONUS: f64 = 2.0;
also the numbers being multiplied and divided having a const for them with a variable name can help know the usecase better
| privacy_score: f64, | ||
| } | ||
|
|
||
| impl InitiatePayjoinOutcome { |
There was a problem hiding this comment.
We now have fee_savings and privacy_score calculation in InitiatePayjoinOutcome should this be done for RespondToPayjoinOutcome so scoring is not affected?
There was a problem hiding this comment.
Yes, RespondToPayjoinOutcome should have the same privacy_score as InitiatePayjoinOutcome to ensure fair comparison between initiating vs responding to payjoins. since both actions provides identical fee savings and privacy benefits.
| let score = base_score + fee_benefit + privacy_benefit; | ||
| debug!("InitiatePayjoinEvent score: {:?} (base: {:?}, fee: {:?}, privacy: {:?})", | ||
| score, base_score, fee_benefit, privacy_benefit); | ||
| ActionScore(score) |
There was a problem hiding this comment.
This question is for anyone reviewing
if maybe a simulation where fee_benefit is meant to matter in. (maybe to see the fee saving benefits of transaction cut through in multi party)
Should it be scaled up or have an option of scaling it up? with a utility factor or something else
as currently with this score, base_score will mostly be higher and be the main decider due to payjoin_utility_factor increase
There was a problem hiding this comment.
Yes. Fee's right now are static.
One TODO item is to pay a higher fee rate the more anxious you are for your deadline. This should be modeled as a piecewise linear with a cap. Also this should probably be implemented first in the unilateral strategy then else where.
arminsabouri
left a comment
There was a problem hiding this comment.
Thanks for picking up a hard ticket for your first PR in this repo!
- The privacy score stuff we can come back to once we start work on subset sum density. For now I would just remove that code and its TODO.
- Left some comments about the fee savings logic.
I would encourage you to stick with this !
| // TODO: somekind of privacy gained metric? | ||
| /// Privacy score based on input/output mixing and timing analysis resistance | ||
| privacy_score: f64, |
There was a problem hiding this comment.
Looking back at this privacy score comment now. I think its a bit outdated and should be removed of 2 party payjoins. Eventually we want dense subset score. i.e given I payjoin with this UTXO over others how dense is subtransaction model. Or given I do a mp pj with this participant over others how dense is the subtransaction model.
| // Larger amounts might justify slightly higher fee savings due to more inputs | ||
| // Cap at 2x for very large amounts | ||
| let amount_factor = (amount / 100000.0).min(2.0); |
There was a problem hiding this comment.
Not sure I understand this comment. A fee a user would pay is a reflection of their impatience not really a function of the payment amount.
| let amount_factor = (amount / 100000.0).min(2.0); | ||
| let total_savings = (base_savings_sats * (1.0 + amount_factor * 0.2)) as u64; | ||
|
|
||
| Amount::from_sat(total_savings) |
There was a problem hiding this comment.
For context: fees are largely ignored by the simulation right now. If you look in the coin selection code you see that fee rate is hardcoded and the unilateral txs all have the same "weight" so they are paying the same absolute fee.
The fee savings for a 2-party payjoin is mainly for the responder / receiver. Where they only need to cover the fees of a input and output contribution and the rest is covered by the sender.
Ideally the fee rate a agent choose is a function of their impatience (how close to the deadline they are). This should be a TODO -- I dont think we have this documented anywhere.
An easier to place to start is probably representing fee savings to the batched unilateral strategy. Where an agent make 1 tx instead of N when they know about N payment obligation
In general fee savings should always reflect how much blockspace you saved. For the payjoin receiver they would compare the absolute fee they would have to pay in a unilateral Tx ( something that we can hardcode for now given that all txs weight and pay the same fee rate) vs the absolute fee they would have to contribute to just adding an input and output.
| let score = base_score + fee_benefit + privacy_benefit; | ||
| debug!("InitiatePayjoinEvent score: {:?} (base: {:?}, fee: {:?}, privacy: {:?})", | ||
| score, base_score, fee_benefit, privacy_benefit); | ||
| ActionScore(score) |
There was a problem hiding this comment.
Yes. Fee's right now are static.
One TODO item is to pay a higher fee rate the more anxious you are for your deadline. This should be modeled as a piecewise linear with a cap. Also this should probably be implemented first in the unilateral strategy then else where.
This PR implements a fee savings calculation model for payjoin transactions, also adding a privacy metrics to payjoin outcome scoring