Add electrum_libsparkmobile - #1
levoncrypto wants to merge 6 commits into
Conversation
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
CodeAnt-AI DescriptionAdd a native Spark wallet library for Electrum-Firo What Changed
Impact
💡 Usage GuideChecking Your Pull RequestEvery time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later. Talking to CodeAnt AIGot a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask: This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code. ExamplePreserve Org Learnings with CodeAntYou can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input: This helps CodeAnt AI learn and adapt to your team's coding style and standards. ExampleRetrigger reviewAsk CodeAnt AI to review the PR again, by typing: Check Your Repository HealthTo analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health. |
CodeAnt Nitpicks2 code suggestions1. These variable names do not match the consumer, which checks
|
reubenyap
left a comment
There was a problem hiding this comment.
Requesting changes: this PR is not ready for a post-H2, V2-only Electrum release.
Release blockers
-
[P0] The ABI creates only legacy V1 spends. The current wrapper exposes neither V2 nor the extension commitment and calls the pre-V2 builder. At H2 (height 1,371,000), V1 remains single-input; multi-input is enabled only by the separate V2 format. For this wallet's post-fork contract, expose no version selector: pin sparkmobile
a9d078955312b3467f5bb14cbd64ab2ed8852256, hardcodeSpendTransactionVersion::V2in spend, fee, and Spark Name paths, and require exactly 32 commitment bytes. Plain spends use zero; Spark Name uses its computed commitment and appends the matching extension. The Electrum caller must emit and parsenVersion=3, nType=11, never silently fall back to type 9. -
[P1] The pinned Spark revision contains reproduced memory-safety defects. ASan confirms:
- every spend-key derivation writes 32 bytes through a vector after its size is cleared;
- an authenticated one-byte memo claiming length 31 causes a 31-byte stack overread;
- authenticated recipient data can declare and allocate a 32 MiB memo before EOF rejection.
The same pin also suppresses coin-identification failure and returns partially uninitialized metadata. Updating toa9d0789fixes these root causes, its first-use parameter race, and noncanonical address decoding.
-
[P1/P2] Outer serialized-coin parsing is still allocation-amplifiable, including on
a9d0789.AEADEncryptedDatageneric-deserializes attacker-declared vector sizes before checking fixed sizes. A direct test allocated exactly 5,000,000 bytes before reporting EOF. The wrapper also accepts trailing bytes: a valid 244-byte coin with 1 MiB appended was accepted. Use fixed-size field parsing, a tight total-size bound, and require stream exhaustion in the shared decoder. -
[P2 privacy] The server controls anonymity-set age. Core accepts a canonical historical reference within a group. Without an independent latest-mature-state check, an Electrum server can supply an older valid prefix containing the selected coin and reduce anonymity without invalidating the spend. Require the latest mature independently verified group reference and a minimum/expected set size.
Other confirmed findings
- Negative amounts/counts return successful fee estimates;
UINT64_MAXmint values and negativevoutwrapping are accepted. Core limits this to invalid-transaction/DoS behavior, not inflation. - Returned
serializedCoinContextis always empty. This breaks bookkeeping, although it does not invalidate the proof. - The dylib exports 4,689 globals: 17 intended C functions and 4,672 dependency/C++ symbols. Hardening flags cover only the wrapper files.
- There are no registered tests, and the documented public Electrum binding/type-11 integration is absent.
- OpenSSL 1.1.1w is EOL, and referenced LGPL/Boost license texts are missing.
Minimum path to merge
- Bump the Spark pin and patch the remaining fixed-size AEAD parser.
- Make the ABI unconditionally V2 and update Electrum atomically for type 11 and extension commitments.
- Centralize strict coin/numeric/aggregate validation.
- Validate cover-set freshness.
- Add one post-H2 end-to-end check covering single- and multi-input V2, local V1 rejection, malformed coins, and stale cover sets.
- Restrict exports and resolve OpenSSL/license packaging.
I built the exact head twice, built it again with ASan/UBSan, and independently reproduced the high-severity paths. I did not find a reachable value-inflation or key-extraction flaw in a9d0789's V2 proof construction.
| cppCoins.push_back(meta); | ||
| } | ||
|
|
||
| std::unordered_map<uint64_t, spark::CoverSetData> cppCoverSetDataAll; |
There was a problem hiding this comment.
[P2 privacy] The server supplies the cover set and historical block reference. A canonical but stale prefix can still yield a valid spend with reduced anonymity. The integration must require the latest mature independently verified group reference and a minimum/expected set size.
reubenyap
left a comment
There was a problem hiding this comment.
Second-pass review of c5cc9bb: the important fixes are real. Spend construction and fee estimation are now V2-only, the Spark pin contains the prior memory-safety fixes, a clean macOS build and ASan/UBSan build pass, GMP is gone, and the dylib exports only the intended 16 C symbols.
I am still requesting changes for the dependency-verification bypass, malformed-input allocation amplification, late V2 resource checks, incomplete redistribution notices, and the missing executable caller/CI gate.
Release requirements outside this repository also remain: the companion Electrum change must use nVersion=3/nType=11; testnet and devnet must disable Spark sends because Core keeps V2 activation at INT_MAX; and Electrum must independently require the latest mature cover-set reference because consensus accepts valid historical prefixes.
Correction to my earlier parser comment: do not require blanket stream exhaustion. A valid first-mint payload is a 244-byte coin followed by a 66-byte Schnorr proof. The remaining parser defect is nested length allocation before fixed-size validation, described inline below.
| const char* begin = reinterpret_cast<const char*>(serializedCoin); | ||
| CDataStream stream(begin, begin + length, SER_NETWORK, PROTOCOL_VERSION); | ||
| spark::Coin coin(spark::Params::get_default()); | ||
| stream >> coin; |
There was a problem hiding this comment.
[P2] The 64 KiB outer cap does not stop nested CompactSize allocation amplification. A reproduced 108-byte ABI input declared a 5,000,000-byte AEAD ciphertext and directly caused a 5,000,000-byte allocation before rejection. Validate the fixed ciphertext/tag/commitment sizes before resizing in sparkmobile, add the malformed-coin regression, and repin. Do not require stream.empty() here: the first mint output legitimately carries a trailing 66-byte proof.
|
|
||
| ## Tests | ||
|
|
||
| The ABI regression tests live with the caller, in |
There was a problem hiding this comment.
[P1] This referenced binding/test file is absent from public Electrum-Firo, this repository's ctest reports No tests were found, and the PR head has no GitHub status checks. Link the companion type-11 caller PR and make its V2/ABI regression test a required CI gate before merging this native library.
reubenyap
left a comment
There was a problem hiding this comment.
Current-head triage for 03cae944.
Address in this library PR
- P1: dependency pin verification must include Git-ignored files; an ignored OpenSSL header was compiled into the supposedly pinned archive.
- P2: fix the reproduced nested CompactSize allocation amplification in sparkmobile, add the malformed-input regression, and repin. The existing line-64 thread is the canonical report.
- P2: raise the declared CMake minimum to match the commands actually used.
- P3: correct the bundled sparkmobile copyright notice.
- P3: reject negative key indexes and diversifiers. The existing negative-diversifier thread is valid but low severity, not “Major.”
Required in the companion Electrum integration before release
- Add type-11 parsing/construction, the ctypes caller, and required end-to-end/ABI CI.
- Enforce independently verified latest-mature cover-set references and a minimum anonymity set.
- Disable Spark sends on testnet/devnet; do not add a V1 fallback.
- Ensure the packaging script selects a valid target platform; an unset platform currently produces a dylib with an extra
@rpath/libsparkmobile.dylibdependency.
Not actionable for this PR
The unresolved Boost-wrapper comments are either disproved by explicit exact-head builds or concern unused MPI, Locale, and iOS infrastructure. The shipped target links only Boost.Thread and Boost.Chrono. The UsedCoin and null-plus-zero comments are also false positives. V2 selection, the zero plain-spend commitment, V2 limits, amount validation, and the broad license-text issue are resolved.
Final review triage (
|
No description provided.