Conversation
Update the react-native peer dependency requirement from a fixed tilde range (~0.82.0) to a wider compatible range (>=0.81.0 <0.83.0) to allow for more flexible versioning within the supported major versions.
…ases decode correctly
<utility> is already compiled into this Android target via Cryptonote/Varint.h (included by crypto.cpp), so there is no build risk in re-adding it here. Moving the already-normalized local string into the vector avoids an unnecessary copy per word on every decode. Co-authored-by: Cursor <cursoragent@cursor.com>
The header declares std::string parameters/returns but only compiled because <string> was pulled in transitively via includes in Mnemonics.cpp. Include it directly so the header is self-contained. Co-authored-by: Cursor <cursoragent@cursor.com>
Every other header under cpp/ uses #pragma once. Mnemonics.h lacked one, leaving it vulnerable to multiple-inclusion/redefinition errors. Co-authored-by: Cursor <cursoragent@cursor.com>
|
1 issue outstanding. See task
Review of 7be6a81 (PR is already merged, so this is post-merge follow-up input) Verified clean:
One low-severity follow-up: the repo has no tests at all, and a fix of this severity should get a regression test (details in the inline comment). Reviewed 7be6a81 |
| /* Normalize to lower case up front so word validation, checksum | ||
| derivation, and word list index lookups all operate on the same | ||
| casing; otherwise a mixed-case phrase can pass validation while | ||
| the index lookup misses and decodes a wrong private key */ | ||
| std::vector<std::string> normalizedWords; | ||
| normalizedWords.reserve(words.size()); | ||
|
|
||
| for (const auto &word : words) { | ||
| std::string lowerWord = word; | ||
| std::transform(lowerWord.begin(), lowerWord.end(), lowerWord.begin(), ::tolower); | ||
| normalizedWords.push_back(std::move(lowerWord)); | ||
| } |
There was a problem hiding this comment.
🟢 Low: no regression coverage for the mixed-case mnemonic fix
I verified this fix empirically: on main before this PR, a phrase with a miscased word in position 2/3 of a word triple (e.g. unUsual) passed the checksum and the val % wlLen == w1 check, silently decoding a wrong private key (bytes 8–10 differed from the lowercase decode — a fund-loss-class bug). With this normalization the same phrase decodes correctly, and invalid words / tampered checksums are still rejected.
Given that severity, the fix deserves a regression test so it can't be reintroduced. The repo currently has no test script at all; even a small standalone C++ roundtrip check (compilable in CI with just g++, no JS test framework needed) would lock this behavior in:
| /* Normalize to lower case up front so word validation, checksum | |
| derivation, and word list index lookups all operate on the same | |
| casing; otherwise a mixed-case phrase can pass validation while | |
| the index lookup misses and decodes a wrong private key */ | |
| std::vector<std::string> normalizedWords; | |
| normalizedWords.reserve(words.size()); | |
| for (const auto &word : words) { | |
| std::string lowerWord = word; | |
| std::transform(lowerWord.begin(), lowerWord.end(), lowerWord.begin(), ::tolower); | |
| normalizedWords.push_back(std::move(lowerWord)); | |
| } | |
| /* Regression-tested: a miscased word previously bypassed the checksum | |
| (first 3 chars) and word-index lookups here, silently producing a | |
| wrong private key; normalization must run before every consumer. */ | |
| std::vector<std::string> normalizedWords; |
Example invariant to test: mnemonicToPrivateKey(privateKeyToMnemonic(k)) equals mnemonicToPrivateKey(mixedCaseVariantOfThatPhrase) equals k, for variants that uppercase any character at any position, plus negative cases (unknown word, swapped words).
No description provided.