Stake command to control snapshots flag

pull/2211/head
vzotova 2020-08-31 13:46:49 +03:00
parent ae20a749b4
commit 719b35889e
9 changed files with 157 additions and 5 deletions

View File

@ -1243,6 +1243,28 @@ class Staker(NucypherTokenActor):
receipt = self._set_winding_down(value=False)
return receipt
@property
def is_taking_snapshots(self) -> bool:
winding_down = self.staking_agent.is_taking_snapshots(staker_address=self.checksum_address)
return winding_down
@only_me
@save_receipt
def _set_snapshots(self, value: bool) -> TxReceipt:
# if self.is_contract:
# receipt = self.preallocation_escrow_agent.set_snapshots(activate=value)
# else:
receipt = self.staking_agent.set_snapshots(staker_address=self.checksum_address, activate=value)
return receipt
def enable_snapshots(self) -> TxReceipt:
receipt = self._set_snapshots(value=True)
return receipt
def disable_snapshots(self) -> TxReceipt:
receipt = self._set_snapshots(value=False)
return receipt
def non_withdrawable_stake(self) -> NU:
staked_amount: NuNits = self.staking_agent.non_withdrawable_stake(staker_address=self.checksum_address)
return NU.from_nunits(staked_amount)

View File

@ -32,7 +32,7 @@ from nucypher.cli.literature import (
CONFIRM_STAGED_STAKE,
RESTAKING_AGREEMENT,
RESTAKING_LOCK_AGREEMENT,
WINDING_DOWN_AGREEMENT
WINDING_DOWN_AGREEMENT, SNAPSHOTS_DISABLING_AGREEMENT, CONFIRM_DISABLE_SNAPSHOTS
)
from nucypher.config.node import CharacterConfiguration
@ -75,6 +75,13 @@ def confirm_enable_winding_down(emitter: StdoutEmitter, staking_address: str) ->
return True
def confirm_disable_snapshots(emitter: StdoutEmitter, staking_address: str) -> bool:
"""Interactively confirm disabling of taking snapshots with user agreements."""
emitter.message(SNAPSHOTS_DISABLING_AGREEMENT)
click.confirm(CONFIRM_DISABLE_SNAPSHOTS.format(staking_address=staking_address), abort=True)
return True
def confirm_staged_stake(staker_address: str, value: NU, lock_periods: int) -> bool:
"""Interactively confirm a new stake reviewing all staged stake details."""
click.confirm(CONFIRM_STAGED_STAKE.format(nunits=str(value.to_nunits()),

View File

@ -33,7 +33,7 @@ from nucypher.cli.actions.confirm import (
confirm_enable_restaking_lock,
confirm_enable_winding_down,
confirm_large_stake,
confirm_staged_stake
confirm_staged_stake, confirm_disable_snapshots
)
from nucypher.cli.actions.select import select_client_account_for_staking, select_stake
from nucypher.cli.utils import setup_emitter
@ -70,7 +70,8 @@ from nucypher.cli.literature import (
CONFIRM_COLLECTING_WITHOUT_MINTING, NO_TOKENS_TO_WITHDRAW, NO_FEE_TO_WITHDRAW, CONFIRM_INCREASING_STAKE,
PROMPT_STAKE_INCREASE_VALUE, SUCCESSFUL_STAKE_INCREASE, INSUFFICIENT_BALANCE_TO_INCREASE, MAXIMUM_STAKE_REACHED,
INSUFFICIENT_BALANCE_TO_CREATE, PROMPT_STAKE_CREATE_VALUE, PROMPT_DEPOSIT_OR_LOCK, PROMPT_STAKE_CREATE_LOCK_PERIODS,
ONLY_DISPLAYING_MERGEABLE_STAKES_NOTE, CONFIRM_MERGE, SUCCESSFUL_STAKES_MERGE
ONLY_DISPLAYING_MERGEABLE_STAKES_NOTE, CONFIRM_MERGE, SUCCESSFUL_STAKES_MERGE, CONFIRM_DISABLE_SNAPSHOTS,
SUCCESSFUL_ENABLE_SNAPSHOTS, SUCCESSFUL_DISABLE_SNAPSHOTS, CONFIRM_ENABLE_SNAPSHOTS
)
from nucypher.cli.options import (
group_options,
@ -732,6 +733,52 @@ def winddown(general_config, transacting_staker_options, config_file, enable, fo
paint_receipt_summary(receipt=receipt, emitter=emitter, chain_name=blockchain.client.chain_name)
@stake.command()
@group_transacting_staker_options
@option_config_file
@click.option('--enable/--disable', help="Used to enable and disable taking snapshots", is_flag=True, default=True)
@option_force
@group_general_config
def snapshots(general_config, transacting_staker_options, config_file, enable, force):
"""Manage snapshots with --enable or --disable."""
# Setup
emitter = setup_emitter(general_config)
STAKEHOLDER = transacting_staker_options.create_character(emitter, config_file)
blockchain = transacting_staker_options.get_blockchain()
client_account, staking_address = select_client_account_for_staking(
emitter=emitter,
stakeholder=STAKEHOLDER,
staking_address=transacting_staker_options.staker_options.staking_address,
individual_allocation=STAKEHOLDER.individual_allocation,
force=force)
# Inner Exclusive Switch
if enable:
if not force:
click.confirm(CONFIRM_ENABLE_SNAPSHOTS.format(staking_address=staking_address), abort=True)
# Authenticate and Execute
password = transacting_staker_options.get_password(blockchain, client_account)
STAKEHOLDER.assimilate(password=password)
receipt = STAKEHOLDER.enable_snapshots()
emitter.echo(SUCCESSFUL_ENABLE_SNAPSHOTS.format(staking_address=staking_address), color='green', verbosity=1)
else:
if not force:
confirm_disable_snapshots(emitter, staking_address=staking_address)
# Authenticate and Execute
password = transacting_staker_options.get_password(blockchain, client_account)
STAKEHOLDER.assimilate(password=password)
receipt = STAKEHOLDER.disable_snapshots()
emitter.echo(SUCCESSFUL_DISABLE_SNAPSHOTS.format(staking_address=staking_address), color='green', verbosity=1)
paint_receipt_summary(receipt=receipt, emitter=emitter, chain_name=blockchain.client.chain_name)
@stake.command()
@group_transacting_staker_options
@option_config_file

View File

@ -191,6 +191,22 @@ CONFIRM_DISABLE_RESTAKING = "Confirm disable re-staking for staker {staking_addr
SUCCESSFUL_DISABLE_RESTAKING = 'Successfully disabled re-staking for {staking_address}'
#
# Snapshots
#
SNAPSHOTS_DISABLING_AGREEMENT = """
By disabling the taking snapshots for {staking_address}, specified address will be excluded in all future DAO validations
until snapshots will be enabled again.
"""
CONFIRM_ENABLE_SNAPSHOTS = "Confirm enable automatic taking snapshots for staker {staking_address}?"
SUCCESSFUL_ENABLE_SNAPSHOTS = 'Successfully enabled taking snapshots for {staking_address}'
CONFIRM_DISABLE_SNAPSHOTS = "Confirm disable taking snapshots for staker {staking_address}?"
SUCCESSFUL_DISABLE_SNAPSHOTS = 'Successfully disabled taking snapshots for {staking_address}'
#
# Bonding
#

View File

@ -27,7 +27,7 @@ from nucypher.cli.literature import POST_STAKING_ADVICE
from nucypher.cli.painting.transactions import paint_receipt_summary
STAKE_TABLE_COLUMNS = ('Idx', 'Value', 'Remaining', 'Enactment', 'Termination', 'Status')
STAKER_TABLE_COLUMNS = ('Status', 'Restaking', 'Winding Down', 'Unclaimed Fees', 'Min fee rate')
STAKER_TABLE_COLUMNS = ('Status', 'Restaking', 'Winding Down', 'Snapshots', 'Unclaimed Fees', 'Min fee rate')
def paint_all_stakes(emitter: StdoutEmitter,
@ -73,6 +73,7 @@ def paint_stakes(emitter: StdoutEmitter,
staker_data = [missing_info,
f'{"Yes" if staker.is_restaking else "No"} ({"Locked" if staker.restaking_lock_enabled else "Unlocked"})',
"Yes" if bool(staker.is_winding_down) else "No",
"Yes" if bool(staker.is_taking_snapshots) else "No",
pretty_fees,
min_fee_rate]

View File

@ -162,6 +162,7 @@ def paint_stakers(emitter, stakers: List[str], registry: BaseContractRegistry) -
worker = staker.worker_address
is_restaking = staker.is_restaking
is_winding_down = staker.is_winding_down
is_taking_snapshots = staker.is_taking_snapshots
missing_commitments = current_period - last_committed_period
owned_in_nu = round(owned_tokens, 2)
@ -180,6 +181,7 @@ def paint_stakers(emitter, stakers: List[str], registry: BaseContractRegistry) -
else:
emitter.echo(f"{tab} {'Re-staking:':10} No")
emitter.echo(f"{tab} {'Winding down:':10} {'Yes' if is_winding_down else 'No'}")
emitter.echo(f"{tab} {'Snapshots:':10} {'Yes' if is_taking_snapshots else 'No'}")
emitter.echo(f"{tab} {'Activity:':10} ", nl=False)
if missing_commitments == -1:
emitter.echo(f"Next period committed (#{last_committed_period})", color='green')

View File

@ -354,6 +354,24 @@ def test_staker_manages_winding_down(testerchain,
assert staker.locked_tokens(base_duration) == 0
def test_staker_manages_snapshots(testerchain,
test_registry,
staker,
token_economics,
ursula_decentralized_test_config):
# Disable taking snapshots
testerchain.time_travel(periods=1)
assert staker.is_taking_snapshots
receipt = staker.disable_snapshots()
assert receipt['status'] == 1
assert not staker.is_taking_snapshots
# Enable taking snapshots
receipt = staker.enable_snapshots()
assert receipt['status'] == 1
assert staker.is_taking_snapshots
def test_set_min_fee_rate(testerchain, test_registry, staker):
# Check before set
_minimum, default, maximum = FEE_RATE_RANGE

View File

@ -490,6 +490,45 @@ def test_stake_winddown(click_runner,
assert "Successfully disabled" in result.output
def test_stake_snapshots(click_runner,
manual_staker,
custom_filepath,
testerchain,
agency_local_registry,
stakeholder_configuration_file_location):
staker = Staker(is_me=True, checksum_address=manual_staker, registry=agency_local_registry)
assert staker.is_taking_snapshots
restake_args = ('stake', 'snapshots',
'--disable',
'--config-file', stakeholder_configuration_file_location,
'--staking-address', manual_staker,
'--force')
result = click_runner.invoke(nucypher_cli,
restake_args,
input=INSECURE_DEVELOPMENT_PASSWORD,
catch_exceptions=False)
assert result.exit_code == 0
assert not staker.is_taking_snapshots
assert "Successfully disabled" in result.output
disable_args = ('stake', 'snapshots',
'--enable',
'--config-file', stakeholder_configuration_file_location,
'--staking-address', manual_staker,
'--force')
result = click_runner.invoke(nucypher_cli,
disable_args,
input=INSECURE_DEVELOPMENT_PASSWORD,
catch_exceptions=False)
assert result.exit_code == 0
assert staker.is_taking_snapshots
assert "Successfully enabled" in result.output
def test_collect_rewards_integration(click_runner,
testerchain,
agency_local_registry,

View File

@ -98,7 +98,7 @@ MOCK_ALLOCATION_REGISTRY_FILEPATH = BASE_TEMP_DIR / f'{BASE_TEMP_PREFIX}test-all
MOCK_INDIVIDUAL_ALLOCATION_FILEPATH = BASE_TEMP_DIR / f'{BASE_TEMP_PREFIX}test-individual-allocation-{datetime.now().strftime(DATETIME_FORMAT)}.json'
MOCK_CUSTOM_INSTALLATION_PATH_2 = '/tmp/nucypher-tmp-test-custom-2-{}'.format(time.time())
MOCK_CUSTOM_INSTALLATION_PATH_2 = BASE_TEMP_DIR / f'{BASE_TEMP_PREFIX}test-custom-2-{datetime.now().strftime(DATETIME_FORMAT)}'
MOCK_REGISTRY_FILEPATH = BASE_TEMP_DIR / f'{BASE_TEMP_PREFIX}mock-registry-{datetime.now().strftime(DATETIME_FORMAT)}.json'