Merging #2128, #2137, #2155 into a rebase over main (instead of three separate github-generated merge commits, which caused a conflict).

pull/2175/head
jMyles 2020-08-01 00:46:19 -07:00
commit a6a873482f
4 changed files with 67 additions and 16 deletions

View File

@ -20,9 +20,7 @@ import json
import os
import sys
import time
from constant_sorrow.constants import FULL, NO_WORKER_BONDED, WORKER_NOT_RUNNING
from decimal import Decimal
from typing import Dict, List, Optional, Tuple
from web3.types import TxReceipt
import traceback
import click
@ -894,6 +892,47 @@ class Staker(NucypherTokenActor):
stakes = sorted(filtered_stakes, key=lambda s: s.address_index_ordering_key)
return stakes
@only_me
def divide_stake(self,
stake_index: int,
target_value: NU,
additional_periods: int = None,
expiration: maya.MayaDT = None) -> tuple:
# Calculate duration in periods
if additional_periods and expiration:
raise ValueError("Pass the number of lock periods or an expiration MayaDT; not both.")
# Update staking cache element
stakes = self.stakes
# Select stake to divide from local cache
try:
current_stake = stakes[stake_index]
except KeyError:
if len(stakes):
message = f"Cannot divide stake - No stake exists with index {stake_index}."
else:
message = "Cannot divide stake - There are no active stakes."
raise Stake.StakingError(message)
# Calculate stake duration in periods
if expiration:
additional_periods = datetime_to_period(datetime=expiration,
seconds_per_period=self.economics.seconds_per_period) - current_stake.final_locked_period
if additional_periods <= 0:
raise Stake.StakingError(f"New expiration {expiration} must be at least 1 period from the "
f"current stake's end period ({current_stake.final_locked_period}).")
# Do it already!
modified_stake, new_stake = current_stake.divide(target_value=target_value,
additional_periods=additional_periods)
# Update staking cache element
self.stakes.refresh()
return modified_stake, new_stake
@only_me
def initialize_stake(self,
amount: NU = None,
@ -1027,7 +1066,8 @@ class Staker(NucypherTokenActor):
# Calculate stake duration in periods
if expiration:
additional_periods = datetime_to_period(datetime=expiration, seconds_per_period=self.economics.seconds_per_period) - stake.final_locked_period
additional_periods = datetime_to_period(datetime=expiration,
seconds_per_period=self.economics.seconds_per_period) - current_stake.final_locked_period
if additional_periods <= 0:
raise ValueError(f"New expiration {expiration} must be at least 1 period from the "
f"current stake's end period ({stake.final_locked_period}).")

View File

@ -20,6 +20,8 @@ from eth_tester.exceptions import TransactionFailed
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent
from nucypher.blockchain.eth.token import NU, Stake
from nucypher.crypto.powers import TransactingPower
from tests.constants import FEE_RATE_RANGE, INSECURE_DEVELOPMENT_PASSWORD
from tests.utils.ursula import make_decentralized_ursulas
from nucypher.crypto.powers import TransactingPower
from nucypher.blockchain.eth.utils import datetime_at_period

View File

@ -30,11 +30,6 @@ import maya
import pytest
from click.testing import CliRunner
from eth_utils import to_checksum_address
from sqlalchemy.engine import create_engine
from twisted.internet import defer
from twisted.internet.defer import Deferred
from twisted.logger import Logger
from io import StringIO
from web3 import Web3
from nucypher.blockchain.economics import BaseEconomics, StandardTokenEconomics
@ -429,7 +424,6 @@ def lonely_ursula_maker(ursula_federated_test_config):
#
def make_token_economics(blockchain):
# Get current blocktime
now = blockchain.w3.eth.getBlock(block_identifier='latest').timestamp
@ -445,7 +439,7 @@ def make_token_economics(blockchain):
economics = StandardTokenEconomics(
worklock_boosting_refund_rate=200,
worklock_commitment_duration=60, # periods
worklock_supply=10*BaseEconomics._default_maximum_allowed_locked,
worklock_supply=10 * BaseEconomics._default_maximum_allowed_locked,
bidding_start_date=bidding_start_date,
bidding_end_date=bidding_end_date,
cancellation_end_date=cancellation_end_date,
@ -583,11 +577,11 @@ def _make_agency(testerchain,
registry=test_registry)
worklock_deployer.deploy()
token_agent = token_deployer.make_agent() # 1 Token
staking_agent = staking_escrow_deployer.make_agent() # 2 Staking Escrow
policy_agent = policy_manager_deployer.make_agent() # 3 Policy Agent
_adjudicator_agent = adjudicator_deployer.make_agent() # 4 Adjudicator
_worklock_agent = worklock_deployer.make_agent() # 5 Worklock
token_agent = token_deployer.make_agent() # 1 Token
staking_agent = staking_escrow_deployer.make_agent() # 2 Staking Escrow
policy_agent = policy_manager_deployer.make_agent() # 3 Policy Agent
_adjudicator_agent = adjudicator_deployer.make_agent() # 4 Adjudicator
_worklock_agent = worklock_deployer.make_agent() # 5 Worklock
# Set additional parameters
minimum, default, maximum = FEE_RATE_RANGE
@ -685,6 +679,8 @@ def stakers(testerchain, agency, token_economics, test_registry):
@pytest.fixture(scope="module")
def blockchain_ursulas(testerchain, stakers, ursula_decentralized_test_config):
if MOCK_KNOWN_URSULAS_CACHE:
raise RuntimeError("Ursulas cache was unclear at fixture loading time. Did you use one of the ursula maker functions without cleaning up?")
_ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
stakers_addresses=testerchain.stakers_accounts,
workers_addresses=testerchain.ursulas_accounts,
@ -897,7 +893,8 @@ def manual_staker(testerchain, agency):
address = '0xaaa23A5c74aBA6ca5E7c09337d5317A7C4563075'
if address not in testerchain.client.accounts:
staker_private_key = '13378db1c2af06933000504838afc2d52efa383206454deefb1836f8f4cd86f8'
address = testerchain.provider.ethereum_tester.add_account(staker_private_key, password=INSECURE_DEVELOPMENT_PASSWORD)
address = testerchain.provider.ethereum_tester.add_account(staker_private_key,
password=INSECURE_DEVELOPMENT_PASSWORD)
tx = {'to': address,
'from': testerchain.etherbase_account,
@ -994,6 +991,9 @@ def fleet_of_highperf_mocked_ursulas(ursula_federated_test_config, request):
ursula.known_nodes.checksum = b"This is a fleet state checksum..".hex()
yield _ursulas
for ursula in _ursulas:
del MOCK_KNOWN_URSULAS_CACHE[ursula.rest_interface.port]
@pytest.fixture(scope="module")
def highperf_mocked_alice(fleet_of_highperf_mocked_ursulas):
@ -1029,6 +1029,7 @@ def highperf_mocked_bob(fleet_of_highperf_mocked_ursulas):
bob._learning_task.stop()
return bob
#
# CLI
#

View File

@ -30,6 +30,14 @@ from twisted.internet.threads import deferToThread
from nucypher.characters.lawful import Ursula
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE
from nucypher.datastore.base import RecordField
import pytest_twisted
from twisted.internet import defer, reactor
from twisted.internet.threads import deferToThread, blockingCallFromThread
from nucypher.characters.lawful import Ursula
from tests.utils.middleware import SluggishLargeFleetMiddleware
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE
from umbral.keys import UmbralPublicKey
from tests.mock.performance_mocks import (
NotAPublicKey,
NotARestApp,