jeffro256 full-time dev work 2024Q4
What
The last quarter I began implementing Jamtis-RCT, as written by tevador. However, with the FCMP++ integration PR opened against master, and upon discussion of the general health of wallet development in the broader ecosystem, it became readily apparent that the way to move forward is to initially support existing Monero addresses in a way that would be indistinguishable on-chain from Jamtis-RCT, adding full Jamtis-RCT support later. As such, I formulated the Carrot specification, which expanded upon the legacy address section in tevador's original Jamtis-RCT proposal. I contacted and conducted meetings with auditors in regards to auditing this spec, which culminated in several proposals. I also implemented transaction scanning code and transaction construction code for Carrot. I would like to continue this work for the next few months ahead of the hardfork. The main things to work on for Carrot at this point are 1) persistent enote stores for both legacy and Carrot scan types together, 2) integration into the main wallet codepaths, 3) hardware device support, and 4) picking and organizing an auditor to move forward with. Ideally, there should also come a point in the near future where the implementation is reviewed against the audited specification. I wish the development of Carrot generally to be swift, in order not to impede the release date of the FCMP++ consensus protocol. It should be noted that if the current addressing protocol is not modified, then users' transactions will not be afforded conditional forward secrecy. This would mean that a potential future adversary with the ability to solve the decisional Diffie-Helman problem (e.g. a usable quantum computer) would be able to retroactively reveal the transaction graph without any obfuscation. Carrot, like Jamtis-RCT, leverages the forward secrecy property of FCMP++ while also tackling other issues like the burning bug, Janus attacks, etc. If all goes well, the adoption of Carrot will seamlessly move Monero users into the full realization of the privacy and security that the FCMP++ proving system has to offer.
To recap, here is a list of things I will attempt to work on this quarter, in rough order of execution:
- Finalize Carrot spec audit
- Implement Carrot enote store
- Implement Carrot hardware device support
- Integrate Carrot into main wallet codepaths
- Begin soliciting Carrot implementation audit
P.S. To all the generous supporters of my previous proposals, I apologize that the direction of my work has shifted so significantly and so frequently in the past. So many developments have occurred within the last year that it makes my head spin, which in the end will no doubt be a good thing. So while a lot of previous goals have been abandoned, and a lot of previous work put on ice indefinitely, things seem to be finally solidifying towards a forseeable, readily-achieveable outcome in regards to the upcoming hardfork, thanks to many hard-working contributors. Hopefully, all of the work for this quarter will actually see the light of day in the short to medium term. Thanks for your patience. I am very grateful for it.
Who
I have been contributing to the Monero core repository for over two years with a total of 76 merged commits to master thus far, with many open PRs. I also began working on the Seraphis migration project, so you can see some of my contributions here and here. Additionally, as I mentioned, last quarter I wrote up the Carrot specification for formal auditing, which will be the main addressing protocol post-FCMP++ if all goes according to plan.
Previous Proposals:
Payment
I propose to work 40 hours/week for 3 months so 40 (hours/week) * 3 (months) * weeks_per_month = 40 (hours/week) * 3 (months) * (365 / 12 / 7) (weeks/month) = 521
hours total on-paper, though I usually work more than that. The proposal is broken into 3 milestones, one for each month. I am setting my hourly rate at 47 USD/hour (+1 USD/hour higher than last quarter), and at a market price of 170.37 USD/XMR, that makes for a total of 143.7 XMR. Price was calculated as 14-day simple average of opening prices on CoinGecko from 2024-09-04 to 2024-09-17 (day of writing), same as last quarter.
Merge request reports
Activity
mentioned in commit 9796587e
Milestone Update 1: September/October 2024
WIP branches
PRs
- https://github.com/monero-project/monero/pull/9505
- https://github.com/monero-project/monero/pull/9508
- https://github.com/monero-project/monero/pull/9514
- https://github.com/monero-project/monero/pull/9522
- https://github.com/monero-project/monero/pull/9548
- https://github.com/monero-project/monero/pull/9556
- https://github.com/monero-project/monero/pull/9558
- https://github.com/monero-project/monero/pull/9559
- https://github.com/monero-project/monero/pull/9560
Update Notes
A lot has happened since the last update. Cypherstack was chosen as the auditor for the Carrot spec, a CCS was opened and funded for them, and they are apparently chugging along briskly. I spent a lot of time recently refactoring the design of the Carrot implementation to make it well documented and clear, as well as highly reusable. I also spent a lot of time removing dependencies so that it's ready to be quickly parsed by future implementation auditors. You can see a PR for the "core" library code here. Static construction/scanning code is mostly finished. There are a number of things still left to work on, most notably hardware device support, the rest of which can be found in the PR task list. The next things I will tackle is hardware device interfaces and an enote store.
Milestone Update 2: November 2024
WIP branches
PRs
- https://github.com/monero-project/monero/pull/9605
- https://github.com/monero-project/monero/pull/9607
CypherStack audit
CypherStack posted a final release of their review of the Carrot specification, which you can view here: https://github.com/cypherstack/carrot-audit. There weren't any problems identified with the cryptography, but CypherStack recommended that sections of the specification should be clarified and/or more formalized. I have begun implementing these changes to the specification.
Switch Commitments
KayabaNerve suggested that we implement switch commitments in Carrot as part of the addressing protocol, which I agreed with. After some discussion in the MRL, there is rough consensus to move forward with switch commitments as a part of Carrot, which I have begun to work on. There is still some discussion on how exactly to implement it, the discussion can be viewed here: https://github.com/monero-project/research-lab/issues/131#issuecomment-2537588673.
Carrot Core changes
Since the last milestone update, I have implemented the "Tests for new enotes addressed to legacy cryptonote accounts/addresses", "Transaction output set finalization logic", and "Hardware device interface" tasks. I also added tasks "Switch commitments" and "Internal self-send messages". This means that there are unit tests verifying that old wallets with old addresses can indeed scan and spend enotes in Carrot transactions. There is also now complete logic to "finish" transaction output enote sets, given a list of payment proposals. This logic ensures that all key images are recoverable, even without precomputation, and sender-receiver secrets are always unique, even for 2-out selfsends. The hardware device interface can be viewed here: https://github.com/monero-project/monero/blob/3b5d17ab2762c1f0bc3c822e15c8ae7efeabd7c6/src/carrot_core/device.h. There are 2 simple device interfaces in this file which should provide all functionality that Carrot needs for transaction scanning and construction. However, these devices don't cover account secret derivation and subaddress derivation, but those are largely orthogonal to the existing device interfaces, and may not even need an interface depending on the implementation. I wrote these interfaces to make implementation for existing hardware wallets as dead simple as possible. There's only five simple functions, and none of them require a lick of state between calls besides the actual value of the permanent key/secret. They all do just one simple step of a computation that would otherwise reveal that key/secret. The API does not attempt to hide per-enote sender-receiver secrets from the host machine, as I think this feature is largely useless and hardly ever gets used. However, I am open to input on this point.
Monerotopia presentation
I gave a presentation on Carrot at Monerotopia in Mexico City. During this presentation, I broke down all of the high-level usability features and security fixes that users can expect from it. I also go in-depth into the math that makes this possible. It doesn't appear that the presentation videos are ready for publishing yet, but it should be available for viewing soon. I spent a lot of time talking with the attendees and speakers, which taught me a lot about how the real-world ecosystem is doing and where Monero could be headed. Great experience overall.
Carrot extension apps
- https://gist.github.com/jeffro256/b54af81983f1e24e2e5329408443154d
- https://gist.github.com/jeffro256/9b2bdb8f40ed1103d3041f02708ba3ec
I uploaded above a few sketches of applications for Carrot, which don't require any modifications to the addressing protocol. One is a blockchain data attestation scheme, and the other is an externally-indistinguishable human-readable memo scheme.
FCMP tree handling improvements
https://github.com/monero-project/monero/pull/9436#issuecomment-2519858103
j-berman and I have been brainstorming a lot on FCMP integration improvements this past month. One of the things to come out of that was that was a hugely simplified and more efficient way to "trim" the FCMP++ tree in our database. Now that the daemon is handling the FCMP++ tree, when we encounter reorgs, we must "trim" the tree. This means recognizing which outputs are being dropped from the tree and modified the nodes so that it matches its state at the point which we are rolling back to. Before, this was done with a
hash_trim
function that was effectively the inverse of thehash_grow
function which we use to grow the FCMP++ with the outputs from each block. However, this implementation required a ton of complicated business logic and edge case handling to get right. It was also terribly slow, which could make reorgs a DoS vector greater than it already is.I threw out the idea of caching and storing persistently the right-most branch of the FCMP++ tree after each block. Then, if we rollback the chain, we only have to simply drop any excess nodes and then reassign the right-most branch of the tree. This doesn't require any crypto operations, so it should be orders of magnitude faster. This also means that we can drop
hash_trim
and all the associated business logic from the FCMP++ integration review, which apparently was one of the most complicated parts of the review. The downside of this approach is that is adds an extra 256=8*32 bytes to the database per block. This means that it would increase the blockchain size by about 67MB per year. However, I think this storage cost is pretty modest compared to the benefits.Banlist review
https://github.com/Boog900/monero-ban-list
I DM'ed boog900 and received some source code to review the IPs in the banlist. I also researched the methodology myself and it seems sound. I then cross-referenced each IP on the list and confirmed that they showed signs of running non-standard, potentially malicious code. Because of all this confirmation, I signed the ban list with my PGP key, as it receives my approval. Props to boog and syntheticbird for digging into this issue.
And thanks to everyone who contributed to my CCS, it is greatly appreciated!
Edited by jeffro256Milestone Update 3: December 2024
WIP branches
- https://github.com/jeffro256/monero/tree/carrot_core
- https://github.com/jeffro256/monero/tree/carrot_impl
Monero Core PRs
- https://github.com/monero-project/monero/pull/9616
- https://github.com/monero-project/monero/pull/9621
- https://github.com/monero-project/monero/pull/9649
- https://github.com/monero-project/monero/pull/9656
- https://github.com/monero-project/monero/pull/9657
- https://github.com/monero-project/monero/pull/9659
- https://github.com/monero-project/monero/pull/9691
- https://github.com/monero-project/monero/pull/9692
Wownero Decoy Selection Fix
I found the root cause of the bug causing Wownero's decoy selection to be ineffective since 2021: https://codeberg.org/wownero/wownero/issues/488#issuecomment-2514880.
Carrot protocol changes
There are a few minor tweaks being proposed to Carrot after weeks of discussion about post-quantum adversaries, as well as optimization.
Switch commitments
We now bind the amount blinding factor to the address spend pubkey and the amount itself. We bind to the address spend pubkey K_s^j to prevent spend spoofing against quantum computers in a hypothetical post-quantum migration. We bind to the amount a for a higher security parameter to protect against supply inflation during a post-quantum migration.
Removing cofactor clear from the X25519 key exchange
Before, we calculated the shared Diffie-Helman shared key as s_{sr} = 8 * k_v * D_e = 8 * d_e * K_s^j, but we have removed the multiplication by 8. We are protected against small subgroup attacks during our Janus attack mitigation, where we reconstruct the ephemeral pubkey with the recalculated ephemeral private key (after checking that the nominal K_s^j is in the prime subgroup).
This change saves us time in the ECDH calculation, which is the most expensive part of scanning. Preliminary performance testing on my
carrot_core
library point to Carrot scanning taking 37% fewer CPU cycles than the current crypto code.[POTENTIAL]: Removing delegated subaddress generation
An issue arises with the mixing of delegated subaddress generation and post-quantum migrations. An entity with a quantum computer and knowledge of a Monero address A can scan all incoming (i.e. not change or other self-send) enotes to that account, and determine exactly where enotes addressed to A were spent. They can also determine where all other incoming enotes to address B != A were spent, given that enotes to that address were spent more than once on-chain. This issue for reusable, non-interactive, elliptic curve based addresses is not easily fixable. A delegated subaddress generator, knowing all Monero addresses belonging to an account, will be able to trace the transaction graph for all incoming (again, not change or other self-send) enotes for that account, given that they have access to a quantum computer in the future. It may be advantageous privacy-wise to not support delegated subaddress generation officially to minimize the damage done post-quantum. However, one could also argue that the transaction graph knowledge gained for a PQ adversary from knowing just one public address, without the generate-address secret, is not that much worse than the knowledge gained for a PQ delegated subaddress generator.
carrot_core
Implemented "internal messages", PQ resistant messages to self in internal enotes. Integrated the fast X25519 key exchange. Added performance tests. Enhanced unit tests.
carrot_impl
Implemented unit tests for the payment proposal -> transaction serialization -> scanning pipeline, end-to-end.
And thanks to everyone who contributed to my CCS, it is greatly appreciated!
mentioned in merge request !540 (merged)