-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-use same outs & chosen mix outs across tx construction attempts #36
Conversation
@j-berman FYI Paul was fired from MyMonero nearly 2 years ago. |
@fluffypony ok but it was a valuable comment to improving my code and making it safer/easier to use, and it's open source, so figure it doesn't really matter? He wrote the structure initially, so I figured he'd have good thoughts on this since it has a material impact on the structure. And he did. I think I remember all the things he said specifically as it relates to how my code can be improved, so going to repeat for posterity:
And in general, make an effort toward converging on code used in wallet2, potentially not needing to rewrite duplicate code that also needs to be updated and maintained, to try and avoid issues like this. Which I think everyone seems to prefer if it's possible |
@j-berman sure - but this is largely kept around for historical significance; you may be better served using the Monero CPP library: https://github.com/monero-ecosystem/monero-cpp |
@fluffypony confirmed this repo is almost certainly the code that MyMonero is using in production. Even if not using this exact repo, this PR is almost certainly a fix for whatever code MyMonero is using today. I used the latest release of MyMonero's desktop app to make this transaction: Then I modified Running that outputs:
This fee calculation is distinct from wallet2 and therefore fingerprintable to code that has the same issues this PR and #35 are fixing. |
@j-berman ah yeah - to be clear, I didn't meant to imply it isn't in limited use, just that (generally speaking) efforts to align things with wallet2 might be wasted :) |
Updated this and mymonero/mymonero-libapp-cpp#4 as per @paulshapiro 's comments. Of note, I've left the following 2 areas untouched (these 2 areas do not utilize the fix of this PR), and seem like may impact consumers of this code: (1)
(2)
@fluffypony I think there is some confusion here so just going to clarify. In speaking with @devinpearson , AFAIU there aren't any immediate plans to transition away from using this repo's code. There are ideas floating around, and it would be really nice to not have to try to match wallet2 (and instead just re-use its internal components without modification), but AFAIU that isn't in the immediate plans. It's an involved task that is fairly challenging. So this PR is fairly important to get right for the time being to stop fingerprinting users to this repo's code. I agree that a general push toward not needing to write/maintain code that must maintain parity with wallet2 would be ideal, long-term. Speaking for myself, this code benefited from Paul's comment. I'm grateful that I realized I still had it in my e-mail to be able to re-read and apply his suggestions. Here is everything from his comment that I applied in this PR:
I also redacted Paul's comments on MyMonero generally, and his thoughts on future plans to try and migrate light wallet code to converge on wallet2/core code. I feel uncomfortable doing this, I felt it was useful information for people. I didn't want to get involved in this beef. Unfortunately, it seems I can't help myself. Regardless of historical context, comments on code should be left to stand on their own merits, especially on open source code. It would have been unfortunate to have lost his comment, not just for the sake of improving this PR, but also more existentially, I prefer to live in a world where opinions and thoughts are shared freely and live or die on their own merit. My 2 picos. |
Updated |
…ction attempts Upon completing round 1 of tx construction, the client determines if the fee used in the tx is > result of calculate_fee(). If not, it re-attempts the tx using the result of calculate_fee(). If the client does not re-use the same set of mix_outs from the prior attempt for each out, then the size of the transaction likely ends up being a little different (because transactions reference mix outs by on optimized offset, which varies in size depending on the set of mix outs), even though the attempt is targeting a fee for a transaction of an expected size. This can result in the transaction including a fee that is *not* the result of calculate_fee(final_tx). Thus, this change provides a way for the client to re-use mix outs across attempts, so that the final fee is equivalent ot the result of calculate_fee. This is now implemented the same way as wallet2 (which also re-uses the same set of decoys across attempts). Bonus: it avoids trips to the server to get new decoys every tx attempt as well.
fab3d09
to
71e7983
Compare
Requesting review from @paulshapiro on this general architecture. It kinda throws somewhat of a wrench into the initial step1 -> step2 design.*
Context
When a client attempts to construct a transaction, it constructs a mock tx first using an estimate for the fee, then retries using a a higher fee that is the result of the more accurate
calculate_fee(initial tx)
. Sometimes the client needs to make multiple retry attempts.Also, when a transaction is constructed, the tx references prior outputs in the chain. These references are stored on transactions as "key offsets" (e.g.
[ 301212232, 3827734, 312343, 15332, 193885, 14006, 599, 183, 5003, 101, 12003]
), which are described well here:Each tx construction retry attempt, the client fetches new decoys from the server, resulting in distinct key offsets for each attempt.
The problem
The key offsets of a transaction can vary in byte size across transaction attempts. This means the fee used in a transaction is unlikely to be the result of
calculate_fee
on the final transaction (which takes as input the tx's byte size when calculating the fee), but rather, the result ofcalculate_fee
of the penultimate transaction construction attempt. This behavior is different from wallet2, which re-uses the same set of outs->mix_outs across transaction construction attempts, resulting in wallet2 constructing transactions that use fees equivalent tocalculate_fee
of the transaction stored on chain in practice. Thus, this difference from wallet2 should be fingerprintable on chain.The solution
Re-use the same set of outputs and chosen mix outs for each output across transaction construction attempts. This avoids the above problem, matches wallet2, and also usually removes the need to make a trip to the server to fetch more decoys on subsequent tx construction attempts after the first.
[DONE 7/11/22] Lingering to-do's
I only updated 1 code path that the desktop app seems to use here: mymonero/mymonero-libapp-cpp#4Other code paths are not using this update. Leaving that to you guys because I'm pretty confused how the other stuff should be changed/tested :)*: I initially prefixed this new function with
step1_and_a_half
because I thought it would be funny, but decided that would be unprofessional :)