Browse Source

commands: extend "importprivkey" to allow importing a list of keys

This is most useful if the user wants to import a significant number of keys,
as every invocation of `importprivkey` results in rewriting the wallet file to disk.

The API of "importprivkey" is left unchanged for the single privkey case.
master
SomberNight 5 years ago committed by Sander van Grieken
parent
commit
d35ed6935d
No known key found for this signature in database
GPG Key ID: 9BCF8209EA402EBA
  1. 20
      electrum/commands.py
  2. 38
      tests/test_commands.py

20
electrum/commands.py

@ -40,7 +40,8 @@ from decimal import Decimal, InvalidOperation
from typing import Optional, TYPE_CHECKING, Dict, List
import os
from .import util, ecc
from . import util, ecc
from . import keystore
from .util import (bfh, format_satoshis, json_decode, json_normalize,
is_hash256_str, is_hex_str, to_bytes, parse_max_spend, to_decimal,
UserFacingException)
@ -53,7 +54,7 @@ from .transaction import (Transaction, multisig_script, TxOutput, PartialTransac
from . import transaction
from .invoices import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
from .synchronizer import Notifier
from .wallet import Abstract_Wallet, create_new_wallet, restore_wallet_from_text, Deterministic_Wallet, BumpFeeStrategy
from .wallet import Abstract_Wallet, create_new_wallet, restore_wallet_from_text, Deterministic_Wallet, BumpFeeStrategy, Imported_Wallet
from .address_synchronizer import TX_HEIGHT_LOCAL
from .mnemonic import Mnemonic
from .lnutil import SENT, RECEIVED
@ -666,15 +667,26 @@ class Commands:
@command('wp')
async def importprivkey(self, privkey, password=None, wallet: Abstract_Wallet = None):
"""Import a private key."""
"""Import a private key or a list of private keys."""
if not wallet.can_import_privkey():
return "Error: This type of wallet cannot import private keys. Try to create a new wallet with that key."
assert isinstance(wallet, Imported_Wallet)
keys = privkey.split()
if not keys:
return "Error: no keys given"
elif len(keys) == 1:
try:
addr = wallet.import_private_key(privkey, password)
addr = wallet.import_private_key(keys[0], password)
out = "Keypair imported: " + addr
except Exception as e:
out = "Error: " + repr(e)
return out
else:
good_inputs, bad_inputs = wallet.import_private_keys(keys, password)
return {
"good_keys": len(good_inputs),
"bad_keys": len(bad_inputs),
}
def _resolver(self, x, wallet: Abstract_Wallet):
if x is None:

38
tests/test_commands.py

@ -357,3 +357,41 @@ class TestCommandsTestnet(ElectrumTestCase):
# test "from_coins" arg
self.assertEqual("02000000000101b9723dfc69af058ef6613539a000d2cd098a2c8a74e802b6d8739db708ba8c9a0100000000fdffffff02a00f00000000000016001429e1fd187f0cac845946ae1b11dc136c536bfc0f84b2000000000000160014100611bcb3aee7aad176936cf4ed56ade03027aa0247304402203aa63539b673a3bd70a76482b17f35f8843974fab28f84143a00450789010bc40220779c2ce2d0217f973f1f6c9f718e19fc7ebd14dd8821a962f002437cda3082ec012102ee3f00141178006c78b0b458aab21588388335078c655459afe544211f15aee000000000",
await cmds.bumpfee(tx=orig_rawtx, new_fee_rate='1.6', from_coins="9a8cba08b79d73d8b602e8748a2c8a09cdd200a0393561f68e05af69fc3d72b9:1", wallet=wallet))
@mock.patch.object(wallet.Abstract_Wallet, 'save_db')
async def test_importprivkey(self, mock_save_db):
wallet = restore_wallet_from_text('p2wpkh:cQUdWZehnGDwGn7CSc911cJBcWTAcnyzpLoJYTsFNYW1w6iaq7Nw p2wpkh:cNHsDLo137ngrr2wGf3mwqpwTUvpuDVAZrqzan9heHcMTK4rP5JB',
path='if_this_exists_mocking_failed_648151893',
config=self.config)['wallet']
cmds = Commands(config=self.config)
self.assertEqual(2, len(wallet.get_addresses()))
# try importing a single bad privkey
out = await cmds.importprivkey("asdasd", wallet=wallet) # type: str
self.assertTrue(out.startswith("Error: "))
self.assertTrue("cannot deserialize privkey" in out)
# try importing empty string
self.assertEqual("Error: no keys given",
await cmds.importprivkey("", wallet=wallet))
# try importing a single good privkey
self.assertEqual("Keypair imported: mfgn4NuNberN5D9gvXaYwkqA6Q6WmF7wtD",
await cmds.importprivkey("cVam1duhd5wSxPPFJFKHNoDA2ZjRq7okvnBWyajsnAEcfPjC6Wbm", wallet=wallet))
# try importing a list of good privkeys
privkeys1_str = " ".join([
"p2pkh:cR1C6p34Gt9gxNJ57rUy96jgN3HQcZCgQzDWtCDNCnx4iLXM2S6g",
"p2pkh:cR1xqAf2hhhfxwAzquDss7ALrMeUN5gR82qp1nRWjqSQppnCNa27",
"cMnMgCvkELEmmnpK8MbcdE8aWRMSCxFMCJU61YReXVXiqjgjhee8",
"p2wpkh:cUfjuZDxEoATQwPmWCBH9kGArALfPij5JruQNfM6NTtYF12fds8Y",
"p2wpkh:cP2U7f2jgaQf1zBAWzNUrhs6mGRCg3uyTvNFUUQ9Q8eyXnpkXSqo",
"p2wpkh:cThVmpx3VgZRhbKQqK1FmLzaFTiUsN1Kp1CBwZVL6VfR33mNMxok",
])
self.assertEqual({"good_keys": 6, "bad_keys": 0},
await cmds.importprivkey(privkeys1_str, wallet=wallet))
# try importing a list of mixed good/bad privkeys
privkeys2_str = " ".join([
"qweqwe",
"p2wpkh:cRFfD1EqocayY3xsw343inJ47LVsZHLbUgPzLmUbXhE6XNJ46Swn",
"p2pkh:cThVmpx3VgZRhbKQqK1FmLzaBAAADDDDkeeeeeeeeeeeeeeeeeeeey",
])
self.assertEqual({"good_keys": 1, "bad_keys": 2},
await cmds.importprivkey(privkeys2_str, wallet=wallet))
self.assertEqual(10, len(wallet.get_addresses()))

Loading…
Cancel
Save