mirror of https://github.com/nucypher/nucypher.git
Merge pull request #2460 from KPrasch/probation
Complete grant CLI policy interactons and probationary period enforcementpull/2461/head
commit
af1c11b0d4
|
@ -0,0 +1 @@
|
|||
Introduces a probationary period for policy creation in the network, until 2021-02-28 23:59:59 UTC.
|
|
@ -0,0 +1 @@
|
|||
Complete interactive collection of policy parameters via alice grant CLI.
|
|
@ -15,14 +15,14 @@
|
|||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
import click
|
||||
from marshmallow import validates_schema
|
||||
from nucypher.cli import options, types
|
||||
|
||||
from nucypher.characters.control.specifications import fields
|
||||
from nucypher.characters.control.specifications.base import BaseSchema
|
||||
from nucypher.characters.control.specifications.exceptions import (
|
||||
InvalidArgumentCombo)
|
||||
from nucypher.cli import options, types
|
||||
from nucypher.characters.control.specifications.exceptions import InvalidArgumentCombo
|
||||
|
||||
|
||||
class PolicyBaseSchema(BaseSchema):
|
||||
|
@ -52,7 +52,8 @@ class PolicyBaseSchema(BaseSchema):
|
|||
click=click.option(
|
||||
'--expiration',
|
||||
help="Expiration Datetime of a policy",
|
||||
type=click.STRING))
|
||||
type=click.DateTime())
|
||||
)
|
||||
|
||||
# optional input
|
||||
value = fields.Wei(
|
||||
|
@ -96,7 +97,7 @@ class GrantPolicy(PolicyBaseSchema):
|
|||
|
||||
label = fields.Label(
|
||||
load_only=True, required=True,
|
||||
click=options.option_label(required=True))
|
||||
click=options.option_label(required=False))
|
||||
|
||||
# output fields
|
||||
treasure_map = fields.TreasureMap(dump_only=True)
|
||||
|
|
|
@ -14,56 +14,68 @@ GNU Affero General Public License for more details.
|
|||
You should have received a copy of the GNU Affero General Public License
|
||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
import contextlib
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
|
||||
import maya
|
||||
import random
|
||||
import time
|
||||
from base64 import b64decode, b64encode
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
from json.decoder import JSONDecodeError
|
||||
from queue import Queue
|
||||
from random import shuffle
|
||||
from typing import Dict, Iterable, List, Optional, Set, Tuple, Union
|
||||
|
||||
from bytestring_splitter import (
|
||||
BytestringKwargifier,
|
||||
BytestringSplitter,
|
||||
BytestringSplittingError,
|
||||
VariableLengthBytestring
|
||||
)
|
||||
from constant_sorrow import constants
|
||||
from constant_sorrow.constants import (
|
||||
INCLUDED_IN_BYTESTRING,
|
||||
PUBLIC_ONLY,
|
||||
STRANGER_ALICE,
|
||||
UNKNOWN_VERSION,
|
||||
READY,
|
||||
INVALIDATED
|
||||
)
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
|
||||
from cryptography.hazmat.primitives.serialization import Encoding
|
||||
from cryptography.x509 import Certificate, NameOID, load_pem_x509_certificate
|
||||
from datetime import datetime
|
||||
from eth_utils import to_checksum_address
|
||||
from flask import Response, request
|
||||
from functools import partial
|
||||
from json.decoder import JSONDecodeError
|
||||
from queue import Queue
|
||||
from random import shuffle
|
||||
from twisted.internet import reactor, stdio, threads
|
||||
from twisted.internet.task import LoopingCall
|
||||
from typing import Dict, Iterable, List, Optional, Tuple, Union
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.kfrags import KFrag
|
||||
from umbral.pre import UmbralCorrectnessError
|
||||
from umbral.signing import Signature
|
||||
|
||||
import nucypher
|
||||
from bytestring_splitter import BytestringKwargifier, BytestringSplitter, BytestringSplittingError, \
|
||||
VariableLengthBytestring
|
||||
from constant_sorrow import constants
|
||||
from constant_sorrow.constants import (INCLUDED_IN_BYTESTRING,
|
||||
PUBLIC_ONLY,
|
||||
STRANGER_ALICE,
|
||||
UNKNOWN_VERSION,
|
||||
READY,
|
||||
INVALIDATED)
|
||||
from nucypher.acumen.nicknames import Nickname
|
||||
from nucypher.acumen.perception import FleetSensor
|
||||
from nucypher.blockchain.eth.actors import BlockchainPolicyAuthor, Worker
|
||||
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent
|
||||
from nucypher.blockchain.eth.constants import LENGTH_ECDSA_SIGNATURE_WITH_RECOVERY, ETH_ADDRESS_BYTE_LENGTH
|
||||
from nucypher.blockchain.eth.constants import ETH_ADDRESS_BYTE_LENGTH
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||
from nucypher.blockchain.eth.registry import BaseContractRegistry
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.blockchain.eth.token import WorkTracker
|
||||
from nucypher.characters.banners import ALICE_BANNER, BOB_BANNER, ENRICO_BANNER, URSULA_BANNER
|
||||
from nucypher.characters.base import Character, Learner
|
||||
from nucypher.characters.control.controllers import (
|
||||
WebController
|
||||
)
|
||||
from nucypher.characters.control.controllers import WebController
|
||||
from nucypher.characters.control.emitters import StdoutEmitter
|
||||
from nucypher.characters.control.interfaces import AliceInterface, BobInterface, EnricoInterface
|
||||
from nucypher.cli.processes import UrsulaCommandProtocol
|
||||
from nucypher.config.constants import END_OF_POLICIES_PROBATIONARY_PERIOD
|
||||
from nucypher.config.storages import ForgetfulNodeStorage, NodeStorage
|
||||
from nucypher.crypto.api import encrypt_and_sign, keccak_digest
|
||||
from nucypher.crypto.constants import HRAC_LENGTH, PUBLIC_KEY_LENGTH
|
||||
|
@ -80,11 +92,6 @@ from nucypher.network.protocols import InterfaceInfo, parse_node_uri
|
|||
from nucypher.network.server import ProxyRESTServer, TLSHostingPower, make_rest_app
|
||||
from nucypher.network.trackers import AvailabilityTracker
|
||||
from nucypher.utilities.logging import Logger
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.kfrags import KFrag
|
||||
from umbral.pre import UmbralCorrectnessError
|
||||
from umbral.signing import Signature
|
||||
|
||||
|
||||
class Alice(Character, BlockchainPolicyAuthor):
|
||||
|
@ -288,7 +295,13 @@ class Alice(Character, BlockchainPolicyAuthor):
|
|||
self.remember_node(node=handpicked_ursula)
|
||||
|
||||
policy = self.create_policy(bob=bob, label=label, **policy_params)
|
||||
self.log.debug(f"Successfully created {policy} ... ")
|
||||
|
||||
# TODO: Remove when the time is right.
|
||||
if policy.expiration > END_OF_POLICIES_PROBATIONARY_PERIOD:
|
||||
raise self.ActorError(f"The requested duration for this policy (until {policy.expiration}) exceeds the "
|
||||
f"probationary period ({END_OF_POLICIES_PROBATIONARY_PERIOD}).")
|
||||
|
||||
self.log.debug(f"Generated new policy proposal {policy} ... ")
|
||||
|
||||
#
|
||||
# We'll find n Ursulas by default. It's possible to "play the field" by trying different
|
||||
|
|
|
@ -65,7 +65,7 @@ def get_nucypher_password(confirm: bool = False, envvar=NUCYPHER_ENVVAR_KEYRING_
|
|||
|
||||
def unlock_nucypher_keyring(emitter: StdoutEmitter, password: str, character_configuration: CharacterConfiguration) -> bool:
|
||||
"""Unlocks a nucypher keyring and attaches it to the supplied configuration if successful."""
|
||||
emitter.message(DECRYPTING_CHARACTER_KEYRING.format(name=character_configuration.NAME), color='yellow')
|
||||
emitter.message(DECRYPTING_CHARACTER_KEYRING.format(name=character_configuration.NAME.capitalize()), color='yellow')
|
||||
|
||||
# precondition
|
||||
if character_configuration.dev_mode:
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
You should have received a copy of the GNU Affero General Public License
|
||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from typing import Type, Union
|
||||
from tabulate import tabulate
|
||||
from typing import Type, Union, Dict
|
||||
|
||||
import click
|
||||
from constant_sorrow.constants import UNKNOWN_DEVELOPMENT_CHAIN_ID
|
||||
|
@ -144,3 +145,11 @@ def verify_upgrade_details(blockchain: Union[BlockchainDeployerInterface, Blockc
|
|||
click.confirm(CONFIRM_VERSIONED_UPGRADE.format(contract_name=deployer.contract_name,
|
||||
old_version=old_contract.version,
|
||||
new_version=new_version), abort=True)
|
||||
|
||||
|
||||
def confirm_staged_grant(emitter, grant_request: Dict) -> None:
|
||||
# TODO: Expand and detail
|
||||
emitter.echo("Successfully staged grant. Please review the details:\n", color='green')
|
||||
table = ([field, value] for field, value in grant_request.items())
|
||||
emitter.echo(tabulate(table, tablefmt="simple"))
|
||||
click.confirm('\nGrant access and sign transaction?', abort=True)
|
||||
|
|
|
@ -15,9 +15,13 @@ You should have received a copy of the GNU Affero General Public License
|
|||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
import click
|
||||
import maya
|
||||
import os
|
||||
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION, NO_PASSWORD
|
||||
from datetime import timedelta
|
||||
from web3.main import Web3
|
||||
|
||||
from nucypher.blockchain.eth.signers.software import ClefSigner
|
||||
from nucypher.characters.control.emitters import StdoutEmitter
|
||||
|
@ -25,8 +29,10 @@ from nucypher.characters.control.interfaces import AliceInterface
|
|||
from nucypher.cli.actions.auth import get_client_password, get_nucypher_password
|
||||
from nucypher.cli.actions.configure import (
|
||||
destroy_configuration,
|
||||
handle_missing_configuration_file, get_or_update_configuration
|
||||
handle_missing_configuration_file,
|
||||
get_or_update_configuration
|
||||
)
|
||||
from nucypher.cli.actions.confirm import confirm_staged_grant
|
||||
from nucypher.cli.actions.select import select_client_account, select_config_file
|
||||
from nucypher.cli.commands.deploy import option_gas_strategy
|
||||
from nucypher.cli.config import group_general_config
|
||||
|
@ -55,12 +61,19 @@ from nucypher.cli.options import (
|
|||
option_teacher_uri,
|
||||
option_lonely
|
||||
)
|
||||
from nucypher.cli.painting.help import paint_new_installation_help
|
||||
from nucypher.cli.painting.help import (
|
||||
paint_new_installation_help,
|
||||
paint_probationary_period_disclaimer,
|
||||
enforce_probationary_period
|
||||
)
|
||||
from nucypher.cli.processes import get_geth_provider_process
|
||||
from nucypher.cli.types import EIP55_CHECKSUM_ADDRESS
|
||||
from nucypher.cli.types import EIP55_CHECKSUM_ADDRESS, GWEI
|
||||
from nucypher.cli.utils import make_cli_character, setup_emitter
|
||||
from nucypher.config.characters import AliceConfiguration
|
||||
from nucypher.config.constants import NUCYPHER_ENVVAR_ALICE_ETH_PASSWORD, TEMPORARY_DOMAIN
|
||||
from nucypher.config.constants import (
|
||||
NUCYPHER_ENVVAR_ALICE_ETH_PASSWORD,
|
||||
TEMPORARY_DOMAIN,
|
||||
)
|
||||
from nucypher.config.keyring import NucypherKeyring
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
|
||||
|
@ -428,6 +441,7 @@ def derive_policy_pubkey(general_config, label, character_options, config_file):
|
|||
@option_config_file
|
||||
@group_general_config
|
||||
@group_character_options
|
||||
@option_force
|
||||
def grant(general_config,
|
||||
bob_encrypting_key,
|
||||
bob_verifying_key,
|
||||
|
@ -437,7 +451,8 @@ def grant(general_config,
|
|||
expiration,
|
||||
m, n,
|
||||
character_options,
|
||||
config_file):
|
||||
config_file,
|
||||
force):
|
||||
"""Create and enact an access policy for some Bob. """
|
||||
|
||||
# Setup
|
||||
|
@ -447,13 +462,62 @@ def grant(general_config,
|
|||
# Input validation
|
||||
if ALICE.federated_only:
|
||||
if any((value, rate)):
|
||||
raise click.BadOptionUsage(option_name="--value, --rate",
|
||||
message="Can't use --value or --rate with a federated Alice.")
|
||||
message = "Can't use --value or --rate with a federated Alice."
|
||||
raise click.BadOptionUsage(option_name="--value, --rate", message=message)
|
||||
elif bool(value) and bool(rate):
|
||||
raise click.BadOptionUsage(option_name="--rate", message="Can't use --value if using --rate")
|
||||
elif not (bool(value) or bool(rate)):
|
||||
rate = ALICE.default_rate # TODO #1709
|
||||
click.confirm(f"Confirm default rate {rate}?", abort=True)
|
||||
|
||||
# Interactive collection follows:
|
||||
# TODO: Extricate to support modules
|
||||
# - Disclaimer
|
||||
# - Label
|
||||
# - Expiration Date & Time
|
||||
# - M of N
|
||||
# - Policy Value (ETH)
|
||||
|
||||
# Policy Expiration
|
||||
# TODO: Remove this line when the time is right.
|
||||
paint_probationary_period_disclaimer(emitter)
|
||||
|
||||
# Label
|
||||
if not label:
|
||||
label = click.prompt(f'Enter label to grant Bob {bob_verifying_key[:8]}', type=click.STRING)
|
||||
|
||||
if not force and not expiration:
|
||||
if ALICE.duration_periods:
|
||||
# TODO: use a default in days or periods?
|
||||
expiration = maya.now() + timedelta(days=ALICE.duration_periods) # default
|
||||
if not click.confirm(f'Use default policy duration (expires {expiration})?'):
|
||||
expiration = click.prompt('Enter policy expiration datetime', type=click.DateTime())
|
||||
else:
|
||||
# No policy duration default default available; Go interactive
|
||||
expiration = click.prompt('Enter policy expiration datetime', type=click.DateTime())
|
||||
|
||||
# TODO: Remove this line when the time is right.
|
||||
enforce_probationary_period(emitter=emitter, expiration=expiration)
|
||||
|
||||
# Policy Threshold and Shares
|
||||
if not n:
|
||||
n = ALICE.n
|
||||
if not force and not click.confirm(f'Use default value for N ({n})?', default=True):
|
||||
n = click.prompt('Enter total number of shares (N)', type=click.INT)
|
||||
if not m:
|
||||
m = ALICE.m
|
||||
if not force and not click.confirm(f'Use default value for M ({m})?', default=True):
|
||||
m = click.prompt('Enter threshold (M)', type=click.IntRange(1, n))
|
||||
|
||||
# Policy Value
|
||||
policy_value_provided = bool(value) or bool(rate)
|
||||
if not ALICE.federated_only and not policy_value_provided:
|
||||
rate = ALICE.default_rate # TODO #1709 - Fine tuning and selection of default rates
|
||||
if not force:
|
||||
default_gwei = Web3.fromWei(rate, 'gwei')
|
||||
prompt = "Confirm rate of {node_rate} gwei ({total_rate} gwei per period)?"
|
||||
if not click.confirm(prompt.format(node_rate=default_gwei, total_rate=default_gwei*n), default=True):
|
||||
interactive_rate = click.prompt('Enter rate per period in gwei', type=GWEI)
|
||||
# TODO: Validate interactively collected rate (#1709)
|
||||
click.confirm(prompt.format(node_rate=rate, total_rate=rate*n), default=True, abort=True)
|
||||
rate = Web3.toWei(interactive_rate, 'gwei')
|
||||
|
||||
# Request
|
||||
grant_request = {
|
||||
|
@ -468,7 +532,11 @@ def grant(general_config,
|
|||
if value:
|
||||
grant_request['value'] = value
|
||||
elif rate:
|
||||
grant_request['rate'] = rate
|
||||
grant_request['rate'] = rate # in wei
|
||||
|
||||
if not force and not general_config.json_ipc:
|
||||
confirm_staged_grant(emitter=emitter, grant_request=grant_request)
|
||||
emitter.echo(f'Granting Access to {bob_verifying_key[:8]}', color='yellow')
|
||||
return ALICE.controller.grant(request=grant_request)
|
||||
|
||||
|
||||
|
|
|
@ -454,6 +454,10 @@ def unbond_worker(general_config: GroupGeneralConfig,
|
|||
blockchain=blockchain,
|
||||
client_account=client_account,
|
||||
hw_wallet=transacting_staker_options.hw_wallet)
|
||||
|
||||
if not force:
|
||||
click.confirm("Are you sure you want to unbond your worker?", abort=True)
|
||||
|
||||
STAKEHOLDER.assimilate(password=password)
|
||||
receipt = STAKEHOLDER.unbond_worker()
|
||||
|
||||
|
|
|
@ -355,7 +355,7 @@ COLLECT_NUCYPHER_PASSWORD = "Enter NuCypher keyring password"
|
|||
|
||||
GENERIC_PASSWORD_PROMPT = "Enter password"
|
||||
|
||||
DECRYPTING_CHARACTER_KEYRING = 'Decrypting {name} keyring...'
|
||||
DECRYPTING_CHARACTER_KEYRING = 'Authenticating {name}'
|
||||
|
||||
|
||||
#
|
||||
|
|
|
@ -16,10 +16,11 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
"""
|
||||
|
||||
import click
|
||||
import maya
|
||||
|
||||
from nucypher.blockchain.eth.sol.__conf__ import SOLIDITY_COMPILER_VERSION
|
||||
from nucypher.characters.banners import NUCYPHER_BANNER
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, USER_LOG_DIR
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, USER_LOG_DIR, END_OF_POLICIES_PROBATIONARY_PERIOD
|
||||
|
||||
|
||||
def echo_version(ctx, param, value):
|
||||
|
@ -74,6 +75,38 @@ def paint_new_installation_help(emitter, new_configuration):
|
|||
character_name_starts_with_vowel = character_name[0].lower() in vowels
|
||||
adjective = 'an' if character_name_starts_with_vowel else 'a'
|
||||
suggested_command = f'nucypher {character_name} run'
|
||||
how_to_run_message = f"\nTo run {adjective} {character_name.capitalize()} node from the default configuration filepath run: \n\n'{suggested_command}'\n"
|
||||
how_to_run_message = f"\nTo run {adjective} {character_name.capitalize()} node from the default configuration " \
|
||||
f"filepath run: \n\n'{suggested_command}'\n"
|
||||
|
||||
emitter.echo(how_to_run_message.format(suggested_command), color='green')
|
||||
|
||||
|
||||
def paint_probationary_period_disclaimer(emitter):
|
||||
width = 60
|
||||
import textwrap
|
||||
disclaimer_title = " DISCLAIMER ".center(width, "=")
|
||||
paragraph = f"""
|
||||
Some areas of the NuCypher network are still under active development;
|
||||
as a consequence, we have established a probationary period for policies in the network.
|
||||
Currently the creation of sharing policies with durations beyond {END_OF_POLICIES_PROBATIONARY_PERIOD} are prevented.
|
||||
After this date the probationary period will be over, and you will be able to create policies with any duration
|
||||
as supported by nodes on the network.
|
||||
"""
|
||||
|
||||
text = (
|
||||
"\n",
|
||||
disclaimer_title,
|
||||
*[line.center(width) for line in textwrap.wrap(paragraph, width - 2)],
|
||||
"=" * len(disclaimer_title),
|
||||
"\n"
|
||||
)
|
||||
for sentence in text:
|
||||
emitter.echo(sentence, color='yellow')
|
||||
|
||||
|
||||
def enforce_probationary_period(emitter, expiration):
|
||||
"""Used during CLI grant to prevent publication of a policy outside the probationary period."""
|
||||
if maya.MayaDT.from_datetime(expiration) > END_OF_POLICIES_PROBATIONARY_PERIOD:
|
||||
emitter.echo(f"The requested duration for this policy (until {expiration}) exceeds the probationary period"
|
||||
f" ({END_OF_POLICIES_PROBATIONARY_PERIOD}).", color="red")
|
||||
raise click.Abort()
|
||||
|
|
|
@ -22,6 +22,8 @@ from pathlib import Path
|
|||
import os
|
||||
from appdirs import AppDirs
|
||||
|
||||
from maya import MayaDT
|
||||
|
||||
import nucypher
|
||||
|
||||
# Environment variables
|
||||
|
@ -69,3 +71,6 @@ TEMPORARY_DOMAIN = ":temporary-domain:" # for use with `--dev` node runtimes
|
|||
|
||||
# Event Blocks Throttling
|
||||
NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS = 'NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS'
|
||||
|
||||
# Probationary period (see #2353)
|
||||
END_OF_POLICIES_PROBATIONARY_PERIOD = MayaDT.from_iso8601('2021-02-28T23:59:59.0Z')
|
||||
|
|
|
@ -294,6 +294,7 @@ def run_entire_cli_lifecycle(click_runner,
|
|||
bob_keys = side_channel.fetch_bob_public_keys()
|
||||
bob_encrypting_key = bob_keys.bob_encrypting_key
|
||||
bob_verifying_key = bob_keys.bob_verifying_key
|
||||
expiration = (maya.now() + datetime.timedelta(days=3)).datetime().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
grant_args = ('alice', 'grant',
|
||||
'--mock-networking',
|
||||
|
@ -303,7 +304,7 @@ def run_entire_cli_lifecycle(click_runner,
|
|||
'--config-file', alice_configuration_file_location,
|
||||
'--m', 2,
|
||||
'--n', 3,
|
||||
'--expiration', (maya.now() + datetime.timedelta(days=3)).iso8601(),
|
||||
'--expiration', expiration,
|
||||
'--label', random_label,
|
||||
'--bob-encrypting-key', bob_encrypting_key,
|
||||
'--bob-verifying-key', bob_verifying_key)
|
||||
|
@ -314,9 +315,8 @@ def run_entire_cli_lifecycle(click_runner,
|
|||
grant_args += ('--provider', TEST_PROVIDER_URI,
|
||||
'--rate', Web3.toWei(9, 'gwei'))
|
||||
|
||||
# TODO: Stop.
|
||||
grant_result = click_runner.invoke(nucypher_cli, grant_args, catch_exceptions=False, env=envvars)
|
||||
assert grant_result.exit_code == 0
|
||||
assert grant_result.exit_code == 0, grant_result.output
|
||||
|
||||
grant_result = json.loads(grant_result.output)
|
||||
|
||||
|
|
|
@ -755,6 +755,7 @@ def test_stake_unbond_worker(click_runner,
|
|||
init_args = ('stake', 'unbond-worker',
|
||||
'--config-file', stakeholder_configuration_file_location,
|
||||
'--staking-address', manual_staker,
|
||||
'--force'
|
||||
)
|
||||
|
||||
user_input = f'{INSECURE_DEVELOPMENT_PASSWORD}'
|
||||
|
|
|
@ -118,7 +118,7 @@ def test_unlock_nucypher_keyring_invalid_password(mocker, test_emitter, alice_bl
|
|||
keyring_attach_spy.assert_called_once()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert DECRYPTING_CHARACTER_KEYRING.format(name='alice') in captured.out
|
||||
assert DECRYPTING_CHARACTER_KEYRING.format(name=alice_blockchain_test_config.NAME.capitalize()) in captured.out
|
||||
|
||||
|
||||
def test_unlock_nucypher_keyring_dev_mode(mocker, test_emitter, capsys, alice_blockchain_test_config):
|
||||
|
@ -137,7 +137,7 @@ def test_unlock_nucypher_keyring_dev_mode(mocker, test_emitter, capsys, alice_bl
|
|||
|
||||
assert result
|
||||
output = capsys.readouterr().out
|
||||
message = DECRYPTING_CHARACTER_KEYRING.format(name=alice_blockchain_test_config.NAME)
|
||||
message = DECRYPTING_CHARACTER_KEYRING.format(name=alice_blockchain_test_config.NAME.capitalize())
|
||||
assert message in output
|
||||
|
||||
unlock_spy.assert_not_called()
|
||||
|
@ -166,7 +166,7 @@ def test_unlock_nucypher_keyring(mocker,
|
|||
|
||||
assert result
|
||||
captured = capsys.readouterr()
|
||||
message = DECRYPTING_CHARACTER_KEYRING.format(name=alice_blockchain_test_config.NAME)
|
||||
message = DECRYPTING_CHARACTER_KEYRING.format(name=alice_blockchain_test_config.NAME.capitalize())
|
||||
assert message in captured.out
|
||||
|
||||
unlock_spy.assert_called_once_with(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
|
|
Loading…
Reference in New Issue