Merge pull request #2450 from cygnusv/unused

Improve user experience of removing unused substakes (CLI and docs)
pull/2452/head
David Núñez 2020-12-03 13:09:15 +01:00 committed by GitHub
commit a4cdecb100
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 6 deletions

View File

@ -512,15 +512,43 @@ This can help to decrease gas consumption in some operations. To merge two stake
Remove unused sub-stake
***********************
Merging or editing sub-stakes can lead to 'unused', inactive sub-stakes remaining on-chain.
These unused sub-stakes add unnecessary gas costs to daily operations.
To remove unused sub-stake:
When sub-stakes terminate, are merged or edited,
there may be 'unused', inactive sub-stakes remaining on-chain.
Continued tracking of these unused sub-stakes adds unnecessary gas costs to daily operations.
Consequently, removal of unused sub-stakes will reduce daily gas costs.
Unused sub-stakes can be displayed by listing all sub-stakes
and will be indicated by the ``INACTIVE`` status label.
.. code:: bash
(nucypher)$ nucypher stake list --all --hw-wallet
...
╒═══════╤═══════════════╤═════════════╤═════════════╤═══════════════╤═══════════╕
│ Idx │ Value │ Remaining │ Enactment │ Termination │ Status │
╞═══════╪═══════════════╪═════════════╪═════════════╪═══════════════╪═══════════╡
│ 0 │ 123456.789 NU │ -4 │ Oct 15 2020 │ Nov 19 2020 │ INACTIVE │
├───────┼───────────────┼─────────────┼─────────────┼───────────────┼───────────┤
│ 1 │ 123456.789 NU │ 27 │ Oct 15 2020 │ Dec 20 2020 │ DIVISIBLE │
├───────┼───────────────┼─────────────┼─────────────┼───────────────┼───────────┤
To remove an unused sub-stake, run the following command and select the index
of your ``INACTIVE`` sub-stake:
.. code:: bash
(nucypher)$ nucypher stake remove-unused --hw-wallet
In order to make the operation as simple and cheap as possible,
the removal algorithm simply relocates the last active sub-stake to the slot
occupied by the currently inactive one, so you will notice a slight
re-ordering of your sub-stakes. This is normal and doesn't have any negative implications.
Collect rewards earned by the staker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1 @@
Improve user experience when removing unused substakes (CLI and docs).

View File

@ -815,6 +815,7 @@ class StakeList(UserList):
# Read from blockchain
stakes_reader = self.staking_agent.get_all_stakes(staker_address=self.checksum_address)
inactive_substakes = []
for onchain_index, stake_info in enumerate(stakes_reader):
if not stake_info:
@ -836,6 +837,9 @@ class StakeList(UserList):
if onchain_stake.final_locked_period > terminal_period:
terminal_period = onchain_stake.final_locked_period
if onchain_stake.status().is_child(Stake.Status.INACTIVE):
inactive_substakes.append(onchain_index)
# Store the replacement stake
onchain_stakes.append(onchain_stake)
@ -846,6 +850,8 @@ class StakeList(UserList):
self.__terminal_period = terminal_period
changed_records = abs(existing_records - len(onchain_stakes))
self.log.debug(f"Updated {changed_records} local staking cache entries.")
if inactive_substakes:
self.log.debug(f"The following sub-stakes are inactive: {inactive_substakes}")
# Record most recent cache update
self.__updated = maya.now()

View File

@ -67,7 +67,8 @@ def select_stake(staker: Staker,
raise click.Abort
# Interactive Selection
paint_stakes(staker=staker, emitter=emitter, stakes=stakes)
paint_unlocked = stakes_status.is_child(Stake.Status.UNLOCKED)
paint_stakes(staker=staker, emitter=emitter, stakes=stakes, paint_unlocked=paint_unlocked)
indexed_stakes = {stake.index: stake for stake in stakes}
indices = [str(index) for index in indexed_stakes.keys()]
choice = click.prompt(SELECT_STAKE, type=click.Choice(indices))

View File

@ -72,7 +72,8 @@ def paint_stakes(emitter: StdoutEmitter,
missing_info = f'Missing {missing} commitments{"s" if missing > 1 else ""}' if missing else f'Committed #{last_committed}'
staker_data = [missing_info,
f'{"Yes" if staker.is_restaking else "No"} ({"Locked" if staker.restaking_lock_enabled else "Unlocked"})',
f'{"Yes" if staker.is_restaking else "No"} '
f'({"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,
@ -96,8 +97,11 @@ def paint_stakes(emitter: StdoutEmitter,
emitter.echo(f"\t Blockchain Provider: {worker_data['blockchain_provider']}")
emitter.echo(tabulate.tabulate(zip(STAKER_TABLE_COLUMNS, staker_data), floatfmt="fancy_grid"))
rows = list()
rows, inactive_substakes = list(), list()
for index, stake in enumerate(stakes):
if stake.status().is_child(Stake.Status.INACTIVE):
inactive_substakes.append(index)
if stake.status().is_child(Stake.Status.UNLOCKED) and not paint_unlocked:
# This stake is unlocked.
continue
@ -108,6 +112,10 @@ def paint_stakes(emitter: StdoutEmitter,
emitter.echo(tabulate.tabulate(rows, headers=STAKE_TABLE_COLUMNS, tablefmt="fancy_grid")) # newline
if not paint_unlocked and inactive_substakes:
emitter.echo(f"Note that some sub-stakes are inactive: {inactive_substakes}\n"
f"Run `nucypher stake list --all` to show all sub-stakes.", color='yellow')
def prettify_stake(stake, index: int = None) -> str:
start_datetime = stake.start_datetime.local_datetime().strftime("%b %d %H:%M %Z")