Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.

New software recovery process (supports btc batch requests) #903

Draft
wants to merge 1 commit into
base: bixin_dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions electrum/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import itertools
import logging
import hashlib

from electrum import bitcoin
import aiorpcx
from aiorpcx import TaskGroup
from aiorpcx import RPCSession, Notification, NetAddress, NewlineFramer
Expand All @@ -57,7 +57,6 @@
from .i18n import _
from .logging import Logger
from .transaction import Transaction

if TYPE_CHECKING:
from .network import Network
from .simple_config import SimpleConfig
Expand Down Expand Up @@ -923,6 +922,7 @@ async def get_history_for_scripthash(self, sh: str) -> List[dict]:
assert_non_negative_integer(tx_item['fee'])
return res


async def listunspent_for_scripthash(self, sh: str) -> List[dict]:
if not is_hash256_str(sh):
raise Exception(f"{repr(sh)} is not a scripthash")
Expand Down
13 changes: 13 additions & 0 deletions electrum_gui/android/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -5345,6 +5345,19 @@ def network_list(self, params):

return ret

def find_accounts(
self, password, chain_code, start_index, searching_count, search_count_as_requested_by_user=True, hw=None
):
mnemonic = self._get_hd_wallet().get_seed(password)
shuaiLiWang marked this conversation as resolved.
Show resolved Hide resolved
data = wallet_manager.search_existing_wallets(
chain_code,
mnemonic,
start_index=start_index,
searching_count=searching_count,
search_count_as_requested_by_user=search_count_as_requested_by_user,
)
return data


all_commands = commands.known_commands.copy()
for name, func in vars(AndroidCommands).items():
Expand Down
9 changes: 7 additions & 2 deletions electrum_gui/common/basic/bip44.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,14 @@ def from_bip44_path(cls, path: str) -> "BIP44Path":

return cls(*levels, last_hardened_level=last_hardened_level)

def next_sibling(self, gap: int = 1) -> "BIP44Path":
def next_sibling(self, gap: int = 1, level: BIP44Level = None) -> "BIP44Path":
if level is not None:
require(len(self._levels) >= level)
increase_index = level - 1
else:
increase_index = -1
next_levels = self._levels.copy()
next_levels[-1] += gap
next_levels[increase_index] += gap
return self.__class__(*next_levels, last_hardened_level=self._last_hardened_level)

def to_target_level(self, target_level: BIP44Level, value_filling_if_none: int = 0) -> "BIP44Path":
Expand Down
151 changes: 121 additions & 30 deletions electrum_gui/common/tests/unit/wallet/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,36 +437,6 @@ def test_export_mnemonic__standalone_mnemonic_wallet(self):
(self.mnemonic, self.passphrase), wallet_manager.export_mnemonic(wallet_info["wallet_id"], self.password)
)

@patch("electrum_gui.common.wallet.manager.provider_manager.get_address")
def test_search_existing_wallets(self, fake_get_address):
fake_get_address.side_effect = (
lambda chain_code, address: provider_data.Address(address=address, balance=18888, existing=True)
if address == "0xa0331fcfa308e488833de1fe16370b529fa7c720"
else provider_data.Address(address=address, balance=0, existing=False)
)

self.assertEqual(
[
{
'address': '3Nu7tDXHbqtuMfMi3DMVrnLFabTvaY2FyF',
'address_encoding': 'P2WPKH-P2SH',
'balance': 0,
'bip44_path': "m/49'/0'/0'/0/0",
'chain_code': 'btc',
'name': 'BTC-1',
},
{
'address': '0xa0331fcfa308e488833de1fe16370b529fa7c720',
'address_encoding': None,
'balance': 18888,
'bip44_path': "m/44'/60'/0'/0/11",
'chain_code': 'eth',
'name': 'ETH-1',
},
],
wallet_manager.search_existing_wallets(["btc", "eth"], self.mnemonic, passphrase=self.passphrase),
)

def test_update_wallet_password(self):
wallet_info = wallet_manager.import_standalone_wallet_by_mnemonic(
"ETH-1",
Expand Down Expand Up @@ -1188,3 +1158,124 @@ def test_verify_message__software(self, fake_provider_manager):
fake_provider_manager.verify_message.assert_called_once_with(
"eth", "fake_address", "Hello OneKey", "fake_signature"
)

def test_generate_searching_bip44_address_paths__eth_base(self):
chain_info = Mock(
bip44_purpose_options=None,
default_address_encoding=None,
bip44_coin_type=60,
bip44_last_hardened_level=bip44.BIP44Level.ACCOUNT,
bip44_auto_increment_level=bip44.BIP44Level.ADDRESS_INDEX,
bip44_target_level=bip44.BIP44Level.ADDRESS_INDEX,
chain_affinity="eth",
)

self.assertEqual(
[(None, f"m/44'/60'/0'/0/{i}") for i in range(20)],
list(wallet_manager.generate_searching_bip44_address_paths(chain_info)),
)

self.assertEqual(
[(None, f"m/44'/60'/0'/0/{i}") for i in range(5, 20)],
list(wallet_manager.generate_searching_bip44_address_paths(chain_info, start_index=5, searching_count=15)),
)

def test_generate_searching_bip44_address_paths__btc_base(self):
bip44_purpose_options = {"P2WPKH-P2SH": 49, "P2PKH": 44, "P2WPKH": 84}
chain_info = Mock(
bip44_purpose_options=bip44_purpose_options,
default_address_encoding="P2WPKH-P2SH",
bip44_coin_type=0,
bip44_last_hardened_level=bip44.BIP44Level.ACCOUNT,
bip44_auto_increment_level=bip44.BIP44Level.ACCOUNT,
bip44_target_level=bip44.BIP44Level.ADDRESS_INDEX,
chain_affinity="btc",
)

def _searching_paths(start, end):
for encoding, purpose in bip44_purpose_options.items():
for account in range(start, end):
for change in (0, 1):
for address in range(20):
yield encoding, f"m/{purpose}'/0'/{account}'/{change}/{address}"

self.assertEqual(
list(_searching_paths(0, 20)),
list(wallet_manager.generate_searching_bip44_address_paths(chain_info)),
)
self.assertEqual(
list(_searching_paths(5, 20)),
list(wallet_manager.generate_searching_bip44_address_paths(chain_info, start_index=5, searching_count=15)),
)

@patch("electrum_gui.common.wallet.manager.provider_manager.batch_get_address")
def test_search_existing_wallets__eth_base(self, fake_batch_get_address):
fake_batch_get_address.return_value = [
provider_data.Address(address="0x9858effd232b4033e47d90003d41ec34ecaeda94", balance=0, existing=True),
provider_data.Address(address="0x6fac4d18c912343bf86fa7049364dd4e424ab9c0", balance=10000, existing=True),
provider_data.Address(address="0xb6716976a3ebe8d39aceb04372f22ff8e6802d7a", balance=0, existing=False),
]

self.assertEqual(
{
'chain_code': 'eth',
'next': 5,
'found_wallet_info': {
"m/44'/60'/0'/0/0": {
'sub_path': [
{
'path': "m/44'/60'/0'/0/0",
'address': '0x9858effd232b4033e47d90003d41ec34ecaeda94',
'balance': 0,
}
]
},
"m/44'/60'/0'/0/1": {
'sub_path': [
{
'path': "m/44'/60'/0'/0/1",
'address': '0x6fac4d18c912343bf86fa7049364dd4e424ab9c0',
'balance': 10000,
}
]
},
},
},
wallet_manager.search_existing_wallets("eth", self.mnemonic, start_index=0, searching_count=5),
)

@patch("electrum_gui.common.wallet.manager.provider_manager.batch_get_address")
def test_search_existing_wallets__btc_base(self, fake_batch_get_address):
fake_batch_get_address.side_effect = (
lambda chain_code, addresses: [
provider_data.Address(address="37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf", balance=0, existing=True),
provider_data.Address(address="3LtMnn87fqUeHBUG414p9CWwnoV6E2pNKS", balance=10000, existing=True),
provider_data.Address(address="3B4cvWGR8X6Xs8nvTxVUoMJV77E4f7oaia", balance=0, existing=False),
]
if "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf" in addresses
else [
provider_data.Address(address="37mbeJptxfQC6SNNLJ9a8efCY4BwBh5Kak", balance=20, existing=True),
provider_data.Address(address="3QrMAP4ZG3a7Y1qFF5A4sY8MeSUxZ8Yxjy", balance=0, existing=False),
]
)

self.assertEqual(
{
'chain_code': 'btc',
'next': 1,
'found_wallet_info': {
"m/49'/0'/0'": {
'sub_path': [
{'path': "m/49'/0'/0'/0/0", 'address': '37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf', 'balance': 0},
{
'path': "m/49'/0'/0'/0/1",
'address': '3LtMnn87fqUeHBUG414p9CWwnoV6E2pNKS',
'balance': 10000,
},
{'path': "m/49'/0'/0'/0/4", 'address': '37mbeJptxfQC6SNNLJ9a8efCY4BwBh5Kak', 'balance': 20},
]
}
},
},
wallet_manager.search_existing_wallets("btc", self.mnemonic, start_index=0, searching_count=1),
)
Loading