fix(import): recognize real DragonX key formats in the import gate
The client-side pre-check rejected legitimate keys before the daemon ever
saw them, surfacing "Unrecognized key format" / a cryptic daemon "Invalid"
error. Two concrete defects plus the brittle heuristic behind them:
- Viewing keys: isViewingKey looked for Zcash's "zxview" extended-FVK
prefix, but DragonX's z_exportviewingkey emits a Sapling *incoming*
viewing key (HRP "zivks"), which z_importviewingkey is the only form the
daemon decodes. Every real DragonX viewing key was refused. (F1)
- Uncompressed transparent WIF: the length+first-char heuristic accepted
{5,K,L,U} only, but a version-188 uncompressed key starts with '7'. (F2)
Replace the heuristic with structural validation using the existing
checksum validators (F3): add util::decodeBase58Check (checksum-stripped
payload) and util::bech32Hrp (HRP of a valid Bech32 string). Transparent
keys are now accepted by decoding Base58Check and checking the payload is a
33/34-byte secret key with a DragonX SECRET_KEY version byte (188 main/
regtest, 128 testnet) — covering compressed and uncompressed, rejecting
addresses/typos by real checksum. Viewing keys are matched by the real
incoming-VK HRPs (zivks / zivktestsapling / zivkregtestsapling).
The Sweep gate and the dialog's live type indicator run off the same
predicates, so they are fixed too (F4). Messaging now names the likely
cause and appends a wrong-coin/network hint to the daemon's raw "Invalid"
error (F5).
Adds testPrivateKeyImportRecognition plus decodeBase58Check/bech32Hrp
coverage; suite green (1/1).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3834,7 +3834,9 @@ void App::importPrivateKey(const std::string& rawKey, int startHeight,
|
||||
// Reject anything that isn't a recognized Z/T private key or shielded viewing key before handing
|
||||
// it to the daemon (the dialog's indicator and this guard share isRecognizedImportKey).
|
||||
if (!services::WalletSecurityController::isRecognizedImportKey(key)) {
|
||||
if (callback) callback(false, "Unrecognized key format.", "");
|
||||
if (callback) callback(false,
|
||||
"Not a recognized DragonX private key or viewing key. Check for missing or "
|
||||
"mistyped characters, and that this is a DragonX key (not another coin).", "");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3874,6 +3876,14 @@ void App::importPrivateKey(const std::string& rawKey, int startHeight,
|
||||
}
|
||||
// Scrub the worker's copy of the key now that the request has been sent (all paths).
|
||||
if (!key.empty()) sodium_memzero(&key[0], key.size());
|
||||
// A checksum-valid key the daemon still rejects is almost always the right *format* but the
|
||||
// wrong network/coin (Komodo-family chains share version bytes) or a corrupted paste — say so,
|
||||
// since the bare "Invalid …" text reads like a wallet bug (F5).
|
||||
if (!err.empty() && err.find("Invalid") != std::string::npos &&
|
||||
err.find("DragonX") == std::string::npos) {
|
||||
err += " — check the key is for DragonX (not another coin or network) and has no missing "
|
||||
"or altered characters.";
|
||||
}
|
||||
return [this, err, addr, callback]() {
|
||||
if (!err.empty()) {
|
||||
if (callback) callback(false, err, "");
|
||||
|
||||
Reference in New Issue
Block a user