Wallet encryption (#783)
* update known commands * add wallet_unlock, block wallet startup on being unlocked * add wallet_decrypt and wallet_encrypt * wallet encryption unit tests * added use_keyring configuration option in order to make keyring password storage optional
This commit is contained in:
parent
bcdeea75d6
commit
8c2d381aee
6 changed files with 227 additions and 18 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -34,8 +34,20 @@ at anytime.
|
||||||
* Don't include file names when logging information about streams, only include sd hashes
|
* Don't include file names when logging information about streams, only include sd hashes
|
||||||
* Re-use addresses used for lbrycrd info exchange, this was a significant source of address bloat in the wallet
|
* Re-use addresses used for lbrycrd info exchange, this was a significant source of address bloat in the wallet
|
||||||
* Remove manual saving of the wallet in from lbrynet, let lbryum handle it
|
* Remove manual saving of the wallet in from lbrynet, let lbryum handle it
|
||||||
|
* Block wallet startup on being unlocked if it is encrypted
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
* Add link to instructions on how to change the default peer port
|
||||||
|
* Add `peer_port` to settings configurable using `settings_set`
|
||||||
|
* Added an option to disable max key fee check.
|
||||||
|
* Add `wallet_unlock`, a command available during startup to unlock an encrypted wallet
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* claim_show API command no longer takes name as argument
|
||||||
|
* Linux default downloads folder changed from `~/Downloads` to `XDG_DOWNLOAD_DIR`
|
||||||
|
* Linux folders moved from the home directory to `~/.local/share/lbry`
|
||||||
|
* Windows folders moved from `%AppData%/Roaming` to `%AppData%/Local/lbry`
|
||||||
|
* Block wallet startup on being unlocked
|
||||||
* Added `status`, `blobs_completed`, and `blobs_in_stream` fields to file objects returned by `file_list` and `get`
|
* Added `status`, `blobs_completed`, and `blobs_in_stream` fields to file objects returned by `file_list` and `get`
|
||||||
* Added `channel_import` and `channel_export` commands
|
* Added `channel_import` and `channel_export` commands
|
||||||
* Added `is_mine` field to `channel_list` results
|
* Added `is_mine` field to `channel_list` results
|
||||||
|
@ -43,6 +55,8 @@ at anytime.
|
||||||
* Added user configurable `auto_renew_claim_height_delta` setting, defaults to 0 (off)
|
* Added user configurable `auto_renew_claim_height_delta` setting, defaults to 0 (off)
|
||||||
* Added `lbrynet-console`, a tool to run or connect to lbrynet-daemon and launch an interactive python console with the api functions built in.
|
* Added `lbrynet-console`, a tool to run or connect to lbrynet-daemon and launch an interactive python console with the api functions built in.
|
||||||
* Added a table to the lbry file database to store the outpoint of the claim downloaded from
|
* Added a table to the lbry file database to store the outpoint of the claim downloaded from
|
||||||
|
* Added `wallet_unlock`, a command available during startup to unlock an encrypted wallet
|
||||||
|
* Added support for wallet encryption via new commands `wallet_decrypt` and `wallet_encrypt`
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
* Removed claim related filter arguments `name`, `claim_id`, and `outpoint` from `file_list`, `file_delete`, `file_set_status`, and `file_reflect`
|
* Removed claim related filter arguments `name`, `claim_id`, and `outpoint` from `file_list`, `file_delete`, `file_set_status`, and `file_reflect`
|
||||||
|
|
|
@ -282,6 +282,7 @@ ADJUSTABLE_SETTINGS = {
|
||||||
'peer_search_timeout': (int, 3),
|
'peer_search_timeout': (int, 3),
|
||||||
'use_auth_http': (bool, False),
|
'use_auth_http': (bool, False),
|
||||||
'use_upnp': (bool, True),
|
'use_upnp': (bool, True),
|
||||||
|
'use_keyring': (bool, False),
|
||||||
'wallet': (str, LBRYUM_WALLET),
|
'wallet': (str, LBRYUM_WALLET),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from lbryum.network import Network
|
||||||
from lbryum.simple_config import SimpleConfig
|
from lbryum.simple_config import SimpleConfig
|
||||||
from lbryum.constants import COIN
|
from lbryum.constants import COIN
|
||||||
from lbryum.commands import Commands
|
from lbryum.commands import Commands
|
||||||
|
from lbryum.errors import InvalidPassword
|
||||||
|
|
||||||
from lbryschema.uri import parse_lbry_uri
|
from lbryschema.uri import parse_lbry_uri
|
||||||
from lbryschema.claim import ClaimDict
|
from lbryschema.claim import ClaimDict
|
||||||
|
@ -1158,6 +1159,12 @@ class Wallet(object):
|
||||||
def get_least_used_address(self, account=None, for_change=False, max_count=100):
|
def get_least_used_address(self, account=None, for_change=False, max_count=100):
|
||||||
return defer.fail(NotImplementedError())
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
|
def decrypt_wallet(self):
|
||||||
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
|
def encrypt_wallet(self, new_password, update_keyring=False):
|
||||||
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
def _start(self):
|
def _start(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1172,6 +1179,9 @@ class LBRYumWallet(Wallet):
|
||||||
self.config = make_config(self._config)
|
self.config = make_config(self._config)
|
||||||
self.network = None
|
self.network = None
|
||||||
self.wallet = None
|
self.wallet = None
|
||||||
|
self._cmd_runner = None
|
||||||
|
self.wallet_pw_d = None
|
||||||
|
self.wallet_unlocked_d = defer.Deferred()
|
||||||
self.is_first_run = False
|
self.is_first_run = False
|
||||||
self.printed_retrieving_headers = False
|
self.printed_retrieving_headers = False
|
||||||
self._start_check = None
|
self._start_check = None
|
||||||
|
@ -1185,6 +1195,12 @@ class LBRYumWallet(Wallet):
|
||||||
return (not self.printed_retrieving_headers and
|
return (not self.printed_retrieving_headers and
|
||||||
self.network.blockchain.retrieving_headers)
|
self.network.blockchain.retrieving_headers)
|
||||||
|
|
||||||
|
def get_cmd_runner(self):
|
||||||
|
if self._cmd_runner is None:
|
||||||
|
self._cmd_runner = Commands(self.config, self.wallet, self.network)
|
||||||
|
|
||||||
|
return self._cmd_runner
|
||||||
|
|
||||||
def _start(self):
|
def _start(self):
|
||||||
network_start_d = defer.Deferred()
|
network_start_d = defer.Deferred()
|
||||||
|
|
||||||
|
@ -1206,6 +1222,34 @@ class LBRYumWallet(Wallet):
|
||||||
else:
|
else:
|
||||||
network_start_d.errback(ValueError("Failed to connect to network."))
|
network_start_d.errback(ValueError("Failed to connect to network."))
|
||||||
|
|
||||||
|
def unlock(password):
|
||||||
|
if self._cmd_runner and self._cmd_runner.locked:
|
||||||
|
try:
|
||||||
|
self._cmd_runner.unlock_wallet(password)
|
||||||
|
except InvalidPassword:
|
||||||
|
log.warning("Incorrect password")
|
||||||
|
check_locked()
|
||||||
|
raise InvalidPassword
|
||||||
|
if self._cmd_runner and self._cmd_runner.locked:
|
||||||
|
raise Exception("Failed to unlock wallet")
|
||||||
|
elif not self._cmd_runner:
|
||||||
|
raise Exception("Command runner hasn't been initialized yet")
|
||||||
|
self.wallet_unlocked_d.callback(True)
|
||||||
|
log.info("Unlocked the wallet!")
|
||||||
|
|
||||||
|
def check_locked():
|
||||||
|
if self._cmd_runner and self._cmd_runner.locked:
|
||||||
|
log.info("Waiting for wallet password")
|
||||||
|
d = defer.Deferred()
|
||||||
|
d.addCallback(unlock)
|
||||||
|
self.wallet_pw_d = d
|
||||||
|
return self.wallet_unlocked_d
|
||||||
|
elif not self._cmd_runner:
|
||||||
|
raise Exception("Command runner hasn't been initialized yet")
|
||||||
|
if not self.wallet.use_encryption:
|
||||||
|
log.info("Wallet is not encrypted")
|
||||||
|
self.wallet_unlocked_d.callback(True)
|
||||||
|
|
||||||
self._start_check = task.LoopingCall(check_started)
|
self._start_check = task.LoopingCall(check_started)
|
||||||
|
|
||||||
d = setup_network()
|
d = setup_network()
|
||||||
|
@ -1216,6 +1260,9 @@ class LBRYumWallet(Wallet):
|
||||||
d.addCallback(lambda _: log.info("Subscribing to addresses"))
|
d.addCallback(lambda _: log.info("Subscribing to addresses"))
|
||||||
d.addCallback(lambda _: self.wallet.wait_until_synchronized(lambda _: None))
|
d.addCallback(lambda _: self.wallet.wait_until_synchronized(lambda _: None))
|
||||||
d.addCallback(lambda _: log.info("Synchronized wallet"))
|
d.addCallback(lambda _: log.info("Synchronized wallet"))
|
||||||
|
d.addCallback(lambda _: self.get_cmd_runner())
|
||||||
|
d.addCallbacks(lambda _: log.info("Set up lbryum command runner"))
|
||||||
|
d.addCallbacks(lambda _: check_locked())
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _stop(self):
|
def _stop(self):
|
||||||
|
@ -1297,9 +1344,6 @@ class LBRYumWallet(Wallet):
|
||||||
d.addCallback(lambda _: blockchain_caught_d)
|
d.addCallback(lambda _: blockchain_caught_d)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _get_cmd_runner(self):
|
|
||||||
return Commands(self.config, self.wallet, self.network)
|
|
||||||
|
|
||||||
# run commands as a defer.succeed,
|
# run commands as a defer.succeed,
|
||||||
# lbryum commands should be run this way , unless if the command
|
# lbryum commands should be run this way , unless if the command
|
||||||
# only makes a lbrum server query, use _run_cmd_as_defer_to_thread()
|
# only makes a lbrum server query, use _run_cmd_as_defer_to_thread()
|
||||||
|
@ -1517,6 +1561,24 @@ class LBRYumWallet(Wallet):
|
||||||
def claim_renew(self, txid, nout):
|
def claim_renew(self, txid, nout):
|
||||||
return self._run_cmd_as_defer_succeed('renewclaim', txid, nout)
|
return self._run_cmd_as_defer_succeed('renewclaim', txid, nout)
|
||||||
|
|
||||||
|
def decrypt_wallet(self):
|
||||||
|
if not self.wallet.use_encryption:
|
||||||
|
return False
|
||||||
|
if not self._cmd_runner:
|
||||||
|
return False
|
||||||
|
if self._cmd_runner.locked:
|
||||||
|
return False
|
||||||
|
self._cmd_runner.decrypt_wallet()
|
||||||
|
return not self.wallet.use_encryption
|
||||||
|
|
||||||
|
def encrypt_wallet(self, new_password, update_keyring=False):
|
||||||
|
if not self._cmd_runner:
|
||||||
|
return False
|
||||||
|
if self._cmd_runner.locked:
|
||||||
|
return False
|
||||||
|
self._cmd_runner.update_password(new_password, update_keyring)
|
||||||
|
return not self.wallet.use_encryption
|
||||||
|
|
||||||
|
|
||||||
class LBRYcrdAddressRequester(object):
|
class LBRYcrdAddressRequester(object):
|
||||||
implements([IRequestCreator])
|
implements([IRequestCreator])
|
||||||
|
|
|
@ -21,6 +21,8 @@ from lbryschema.error import URIParseError, DecodeError
|
||||||
from lbryschema.validator import validate_claim_id
|
from lbryschema.validator import validate_claim_id
|
||||||
from lbryschema.address import decode_address
|
from lbryschema.address import decode_address
|
||||||
|
|
||||||
|
from lbryum.errors import InvalidPassword
|
||||||
|
|
||||||
# TODO: importing this when internet is disabled raises a socket.gaierror
|
# TODO: importing this when internet is disabled raises a socket.gaierror
|
||||||
from lbrynet.core.system_info import get_lbrynet_version
|
from lbrynet.core.system_info import get_lbrynet_version
|
||||||
from lbrynet import conf, analytics
|
from lbrynet import conf, analytics
|
||||||
|
@ -165,7 +167,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
allowed_during_startup = [
|
allowed_during_startup = [
|
||||||
'daemon_stop', 'status', 'version',
|
'daemon_stop', 'status', 'version', 'wallet_unlock'
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, analytics_manager):
|
def __init__(self, analytics_manager):
|
||||||
|
@ -541,6 +543,8 @@ class Daemon(AuthJSONRPCServer):
|
||||||
elif self.wallet_type == LBRYUM_WALLET:
|
elif self.wallet_type == LBRYUM_WALLET:
|
||||||
log.info("Using lbryum wallet")
|
log.info("Using lbryum wallet")
|
||||||
config = {'auto_connect': True}
|
config = {'auto_connect': True}
|
||||||
|
if 'use_keyring' in conf.settings:
|
||||||
|
config['use_keyring'] = conf.settings['use_keyring']
|
||||||
if conf.settings['lbryum_wallet_dir']:
|
if conf.settings['lbryum_wallet_dir']:
|
||||||
config['lbryum_path'] = conf.settings['lbryum_wallet_dir']
|
config['lbryum_path'] = conf.settings['lbryum_wallet_dir']
|
||||||
storage = SqliteStorage(self.db_dir)
|
storage = SqliteStorage(self.db_dir)
|
||||||
|
@ -971,16 +975,16 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Returns:
|
Returns:
|
||||||
(dict) lbrynet-daemon status
|
(dict) lbrynet-daemon status
|
||||||
{
|
{
|
||||||
'lbry_id': lbry peer id, base58
|
'lbry_id': lbry peer id, base58,
|
||||||
'installation_id': installation id, base58
|
'installation_id': installation id, base58,
|
||||||
'is_running': bool
|
'is_running': bool,
|
||||||
'is_first_run': bool
|
'is_first_run': bool,
|
||||||
'startup_status': {
|
'startup_status': {
|
||||||
'code': status code
|
'code': status code,
|
||||||
'message': status message
|
'message': status message
|
||||||
},
|
},
|
||||||
'connection_status': {
|
'connection_status': {
|
||||||
'code': connection status code
|
'code': connection status code,
|
||||||
'message': connection status message
|
'message': connection status message
|
||||||
},
|
},
|
||||||
'blockchain_status': {
|
'blockchain_status': {
|
||||||
|
@ -988,6 +992,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
'blocks_behind': remote_height - local_height,
|
'blocks_behind': remote_height - local_height,
|
||||||
'best_blockhash': block hash of most recent block,
|
'best_blockhash': block hash of most recent block,
|
||||||
},
|
},
|
||||||
|
'wallet_is_encrypted': bool,
|
||||||
|
|
||||||
If given the session status option:
|
If given the session status option:
|
||||||
'session_status': {
|
'session_status': {
|
||||||
|
@ -1001,13 +1006,13 @@ class Daemon(AuthJSONRPCServer):
|
||||||
'dht_status': {
|
'dht_status': {
|
||||||
'kbps_received': current kbps receiving,
|
'kbps_received': current kbps receiving,
|
||||||
'kbps_sent': current kdps being sent,
|
'kbps_sent': current kdps being sent,
|
||||||
'total_bytes_sent': total bytes sent
|
'total_bytes_sent': total bytes sent,
|
||||||
'total_bytes_received': total bytes received
|
'total_bytes_received': total bytes received,
|
||||||
'queries_received': number of queries received per second
|
'queries_received': number of queries received per second,
|
||||||
'queries_sent': number of queries sent per second
|
'queries_sent': number of queries sent per second,
|
||||||
'recent_contacts': count of recently contacted peers
|
'recent_contacts': count of recently contacted peers,
|
||||||
'unique_contacts': count of unique peers
|
'unique_contacts': count of unique peers
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -1016,6 +1021,8 @@ class Daemon(AuthJSONRPCServer):
|
||||||
local_height = self.session.wallet.network.get_local_height() if has_wallet else 0
|
local_height = self.session.wallet.network.get_local_height() if has_wallet else 0
|
||||||
remote_height = self.session.wallet.network.get_server_height() if has_wallet else 0
|
remote_height = self.session.wallet.network.get_server_height() if has_wallet else 0
|
||||||
best_hash = (yield self.session.wallet.get_best_blockhash()) if has_wallet else None
|
best_hash = (yield self.session.wallet.get_best_blockhash()) if has_wallet else None
|
||||||
|
wallet_is_encrypted = has_wallet and self.session.wallet.wallet and \
|
||||||
|
self.session.wallet.wallet.use_encryption
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
'lbry_id': base58.b58encode(self.node_id),
|
'lbry_id': base58.b58encode(self.node_id),
|
||||||
|
@ -1034,6 +1041,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
else ''
|
else ''
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
'wallet_is_encrypted': wallet_is_encrypted,
|
||||||
'blocks_behind': remote_height - local_height, # deprecated. remove from UI, then here
|
'blocks_behind': remote_height - local_height, # deprecated. remove from UI, then here
|
||||||
'blockchain_status': {
|
'blockchain_status': {
|
||||||
'blocks': local_height,
|
'blocks': local_height,
|
||||||
|
@ -1238,6 +1246,68 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return self._render_response(float(
|
return self._render_response(float(
|
||||||
self.session.wallet.get_address_balance(address, include_unconfirmed)))
|
self.session.wallet.get_address_balance(address, include_unconfirmed)))
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def jsonrpc_wallet_unlock(self, password):
|
||||||
|
"""
|
||||||
|
Unlock an encrypted wallet
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
wallet_unlock (<password>)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(bool) true if wallet is unlocked, otherwise false
|
||||||
|
"""
|
||||||
|
|
||||||
|
cmd_runner = self.session.wallet.get_cmd_runner()
|
||||||
|
if cmd_runner is not None and cmd_runner.locked:
|
||||||
|
result = True
|
||||||
|
elif self.session.wallet.wallet_pw_d is not None:
|
||||||
|
d = self.session.wallet.wallet_pw_d
|
||||||
|
if not d.called:
|
||||||
|
d.addCallback(lambda _: not self.session.wallet._cmd_runner.locked)
|
||||||
|
self.session.wallet.wallet_pw_d.callback(password)
|
||||||
|
try:
|
||||||
|
result = yield d
|
||||||
|
except InvalidPassword:
|
||||||
|
result = False
|
||||||
|
else:
|
||||||
|
result = self.session.wallet._cmd_runner.locked
|
||||||
|
response = yield self._render_response(result)
|
||||||
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def jsonrpc_wallet_decrypt(self):
|
||||||
|
"""
|
||||||
|
Decrypt an encrypted wallet, this will remove the wallet password
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
wallet_decrypt
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(bool) true if wallet is decrypted, otherwise false
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = self.session.wallet.decrypt_wallet()
|
||||||
|
response = yield self._render_response(result)
|
||||||
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def jsonrpc_wallet_encrypt(self, new_password):
|
||||||
|
"""
|
||||||
|
Encrypt a wallet with a password, if the wallet is already encrypted this will update
|
||||||
|
the password
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
wallet_encrypt (<new_password>)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(bool) true if wallet is decrypted, otherwise false
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.session.wallet.encrypt_wallet(new_password)
|
||||||
|
response = yield self._render_response(self.session.wallet.wallet.use_encryption)
|
||||||
|
defer.returnValue(response)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_daemon_stop(self):
|
def jsonrpc_daemon_stop(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
import lbryum.wallet
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
from twisted.internet import threads, defer
|
from twisted.internet import threads, defer
|
||||||
|
|
||||||
from lbrynet.core.Error import InsufficientFundsError
|
from lbrynet.core.Error import InsufficientFundsError
|
||||||
from lbrynet.core.Wallet import Wallet, ReservedPoints, InMemoryStorage
|
from lbrynet.core.Wallet import Wallet, LBRYumWallet, ReservedPoints, InMemoryStorage
|
||||||
|
from lbryum.commands import Commands
|
||||||
|
|
||||||
|
|
||||||
test_metadata = {
|
test_metadata = {
|
||||||
'license': 'NASA',
|
'license': 'NASA',
|
||||||
|
@ -44,8 +51,36 @@ class MocLbryumWallet(Wallet):
|
||||||
return defer.succeed(True)
|
return defer.succeed(True)
|
||||||
|
|
||||||
|
|
||||||
|
class MocEncryptedWallet(LBRYumWallet):
|
||||||
|
def __init__(self):
|
||||||
|
LBRYumWallet.__init__(self, InMemoryStorage())
|
||||||
|
self.wallet_balance = Decimal(10.0)
|
||||||
|
self.total_reserved_points = Decimal(0.0)
|
||||||
|
self.queued_payments = defaultdict(Decimal)
|
||||||
|
|
||||||
class WalletTest(unittest.TestCase):
|
class WalletTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
wallet = MocEncryptedWallet()
|
||||||
|
seed_text = "travel nowhere air position hill peace suffer parent beautiful rise " \
|
||||||
|
"blood power home crumble teach"
|
||||||
|
password = "secret"
|
||||||
|
|
||||||
|
user_dir = tempfile.mkdtemp()
|
||||||
|
path = os.path.join(user_dir, "somewallet")
|
||||||
|
storage = lbryum.wallet.WalletStorage(path)
|
||||||
|
wallet.wallet = lbryum.wallet.NewWallet(storage)
|
||||||
|
wallet.wallet.add_seed(seed_text, password)
|
||||||
|
wallet.wallet.create_master_keys(password)
|
||||||
|
wallet.wallet.create_main_account()
|
||||||
|
|
||||||
|
self.wallet_path = path
|
||||||
|
self.enc_wallet = wallet
|
||||||
|
self.enc_wallet_password = password
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
shutil.rmtree(os.path.dirname(self.wallet_path))
|
||||||
|
|
||||||
def test_failed_send_name_claim(self):
|
def test_failed_send_name_claim(self):
|
||||||
def not_enough_funds_send_name_claim(self, name, val, amount):
|
def not_enough_funds_send_name_claim(self, name, val, amount):
|
||||||
claim_out = {'success':False, 'reason':'Not enough funds'}
|
claim_out = {'success':False, 'reason':'Not enough funds'}
|
||||||
|
@ -198,3 +233,29 @@ class WalletTest(unittest.TestCase):
|
||||||
'test', "f43dc06256a69988bdbea09a58c80493ba15dcfa", 4))
|
'test', "f43dc06256a69988bdbea09a58c80493ba15dcfa", 4))
|
||||||
self.assertFailure(d, InsufficientFundsError)
|
self.assertFailure(d, InsufficientFundsError)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def test_unlock_wallet(self):
|
||||||
|
wallet = self.enc_wallet
|
||||||
|
wallet._cmd_runner = Commands(
|
||||||
|
wallet.config, wallet.wallet, wallet.network, None, self.enc_wallet_password)
|
||||||
|
cmd_runner = wallet.get_cmd_runner()
|
||||||
|
cmd_runner.unlock_wallet(self.enc_wallet_password)
|
||||||
|
self.assertIsNone(cmd_runner.new_password)
|
||||||
|
self.assertEqual(cmd_runner._password, self.enc_wallet_password)
|
||||||
|
|
||||||
|
def test_encrypt_decrypt_wallet(self):
|
||||||
|
wallet = self.enc_wallet
|
||||||
|
wallet._cmd_runner = Commands(
|
||||||
|
wallet.config, wallet.wallet, wallet.network, None, self.enc_wallet_password)
|
||||||
|
wallet.encrypt_wallet("secret2", False)
|
||||||
|
wallet.decrypt_wallet()
|
||||||
|
|
||||||
|
def test_update_password_keyring_off(self):
|
||||||
|
wallet = self.enc_wallet
|
||||||
|
wallet.config.use_keyring = False
|
||||||
|
wallet._cmd_runner = Commands(
|
||||||
|
wallet.config, wallet.wallet, wallet.network, None, self.enc_wallet_password)
|
||||||
|
|
||||||
|
# no keyring available, so ValueError is expected
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
wallet.encrypt_wallet("secret2", True)
|
||||||
|
|
|
@ -14,6 +14,7 @@ gmpy==1.17
|
||||||
jsonrpc==1.2
|
jsonrpc==1.2
|
||||||
jsonrpclib==0.1.7
|
jsonrpclib==0.1.7
|
||||||
jsonschema==2.6.0
|
jsonschema==2.6.0
|
||||||
|
keyring==10.4.0
|
||||||
git+https://github.com/lbryio/lbryum.git@v3.2.0rc7#egg=lbryum
|
git+https://github.com/lbryio/lbryum.git@v3.2.0rc7#egg=lbryum
|
||||||
git+https://github.com/lbryio/lbryschema.git@v0.0.15rc2#egg=lbryschema
|
git+https://github.com/lbryio/lbryschema.git@v0.0.15rc2#egg=lbryschema
|
||||||
miniupnpc==1.9
|
miniupnpc==1.9
|
||||||
|
@ -30,4 +31,4 @@ six>=1.9.0
|
||||||
slowaes==0.1a1
|
slowaes==0.1a1
|
||||||
txJSON-RPC==0.5
|
txJSON-RPC==0.5
|
||||||
wsgiref==0.1.2
|
wsgiref==0.1.2
|
||||||
zope.interface==4.3.3
|
zope.interface==4.3.3
|
Loading…
Reference in a new issue