fix(wallet): 修复 BIP84 bc1q 地址无法关联助记词 + 过滤加密 keystore 产生的假地址
Bug1: DarkSwordIngestAdapter::harvestAddresses 对加密 keystore 文本跑地址正则, 会把 xpub 子串/hex IV 误识别为地址。新增 EthAddress/TronAddress/BtcAddress isValid 校验,拒绝假地址入库。 Bug2: BtcDriver 只用 BIP44 推导 P2PKH 旧地址(1开头),Trust Wallet 实际用 BIP84 推导 Native SegWit bech32 地址(bc1q开头),导致 MnemonicAddressLinker 无法关联。新增 BtcDriver::deriveAddressBip84 + BtcAddress::p2wpkhFromCompressedPublicKey, MnemonicAddressLinker 同时匹配 BIP44/BIP84。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,7 @@ namespace App\Services;
|
||||
use App\Models\WalletAddress;
|
||||
use App\Models\WalletMnemonic;
|
||||
use App\Services\Chain\ChainDriver;
|
||||
use App\Services\Chain\BtcDriver;
|
||||
use App\Services\Chain\ChainManager;
|
||||
use InvalidArgumentException;
|
||||
|
||||
@@ -41,7 +42,7 @@ class MnemonicAddressLinker
|
||||
}
|
||||
|
||||
$target = (string) $address->address;
|
||||
$caseInsensitive = in_array($driver->chainId(), ['eth', 'bsc'], true);
|
||||
$caseInsensitive = $driver->chainId() === 'eth';
|
||||
|
||||
foreach ($mnemonics as $mnemonicRow) {
|
||||
$phrase = $mnemonicRow->mnemonic;
|
||||
@@ -125,7 +126,7 @@ class MnemonicAddressLinker
|
||||
continue;
|
||||
}
|
||||
|
||||
$lookup = in_array($driver->chainId(), ['eth', 'bsc'], true)
|
||||
$lookup = $driver->chainId() === 'eth'
|
||||
? strtolower((string) $address->address)
|
||||
: (string) $address->address;
|
||||
|
||||
@@ -193,7 +194,8 @@ class MnemonicAddressLinker
|
||||
*/
|
||||
private function deriveIndexMap(ChainDriver $driver, string $phrase): array
|
||||
{
|
||||
$caseInsensitive = in_array($driver->chainId(), ['eth', 'bsc'], true);
|
||||
$caseInsensitive = $driver->chainId() === 'eth';
|
||||
$isBtc = $driver instanceof BtcDriver;
|
||||
$map = [];
|
||||
for ($index = 0; $index <= self::MAX_DERIVE_INDEX; $index++) {
|
||||
try {
|
||||
@@ -205,6 +207,17 @@ class MnemonicAddressLinker
|
||||
if (! array_key_exists($key, $map)) {
|
||||
$map[$key] = $index;
|
||||
}
|
||||
// BTC: also derive BIP84 (Native SegWit, bc1q) addresses.
|
||||
if ($isBtc) {
|
||||
try {
|
||||
$derivedBip84 = $driver->deriveAddressBip84($phrase, $index);
|
||||
} catch (\Throwable) {
|
||||
$derivedBip84 = null;
|
||||
}
|
||||
if ($derivedBip84 !== null && ! array_key_exists($derivedBip84, $map)) {
|
||||
$map[$derivedBip84] = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $map;
|
||||
@@ -216,6 +229,7 @@ class MnemonicAddressLinker
|
||||
string $target,
|
||||
bool $caseInsensitive,
|
||||
): ?int {
|
||||
$isBtc = $driver instanceof BtcDriver;
|
||||
for ($index = 0; $index <= self::MAX_DERIVE_INDEX; $index++) {
|
||||
try {
|
||||
$derived = $driver->deriveAddress($phrase, $index);
|
||||
@@ -228,6 +242,17 @@ class MnemonicAddressLinker
|
||||
if ($match) {
|
||||
return $index;
|
||||
}
|
||||
// BTC: also check BIP84 (Native SegWit, bc1q) address.
|
||||
if ($isBtc) {
|
||||
try {
|
||||
$derivedBip84 = $driver->deriveAddressBip84($phrase, $index);
|
||||
} catch (\Throwable) {
|
||||
$derivedBip84 = null;
|
||||
}
|
||||
if ($derivedBip84 === $target) {
|
||||
return $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user