mirror of https://github.com/nucypher/nucypher.git
Merging #2128, #2137, #2155 into a rebase over main (instead of three separate github-generated merge commits, which caused a conflict).
commit
a6a873482f
|
@ -20,9 +20,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from constant_sorrow.constants import FULL, NO_WORKER_BONDED, WORKER_NOT_RUNNING
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Dict, List, Optional, Tuple
|
|
||||||
from web3.types import TxReceipt
|
from web3.types import TxReceipt
|
||||||
import traceback
|
import traceback
|
||||||
import click
|
import click
|
||||||
|
@ -894,6 +892,47 @@ class Staker(NucypherTokenActor):
|
||||||
stakes = sorted(filtered_stakes, key=lambda s: s.address_index_ordering_key)
|
stakes = sorted(filtered_stakes, key=lambda s: s.address_index_ordering_key)
|
||||||
return stakes
|
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
|
@only_me
|
||||||
def initialize_stake(self,
|
def initialize_stake(self,
|
||||||
amount: NU = None,
|
amount: NU = None,
|
||||||
|
@ -1027,7 +1066,8 @@ class Staker(NucypherTokenActor):
|
||||||
|
|
||||||
# Calculate stake duration in periods
|
# Calculate stake duration in periods
|
||||||
if expiration:
|
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:
|
if additional_periods <= 0:
|
||||||
raise ValueError(f"New expiration {expiration} must be at least 1 period from the "
|
raise ValueError(f"New expiration {expiration} must be at least 1 period from the "
|
||||||
f"current stake's end period ({stake.final_locked_period}).")
|
f"current stake's end period ({stake.final_locked_period}).")
|
||||||
|
|
|
@ -20,6 +20,8 @@ from eth_tester.exceptions import TransactionFailed
|
||||||
|
|
||||||
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent
|
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent
|
||||||
from nucypher.blockchain.eth.token import NU, Stake
|
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 tests.utils.ursula import make_decentralized_ursulas
|
||||||
from nucypher.crypto.powers import TransactingPower
|
from nucypher.crypto.powers import TransactingPower
|
||||||
from nucypher.blockchain.eth.utils import datetime_at_period
|
from nucypher.blockchain.eth.utils import datetime_at_period
|
||||||
|
|
|
@ -30,11 +30,6 @@ import maya
|
||||||
import pytest
|
import pytest
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
from eth_utils import to_checksum_address
|
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 web3 import Web3
|
||||||
|
|
||||||
from nucypher.blockchain.economics import BaseEconomics, StandardTokenEconomics
|
from nucypher.blockchain.economics import BaseEconomics, StandardTokenEconomics
|
||||||
|
@ -429,7 +424,6 @@ def lonely_ursula_maker(ursula_federated_test_config):
|
||||||
#
|
#
|
||||||
|
|
||||||
def make_token_economics(blockchain):
|
def make_token_economics(blockchain):
|
||||||
|
|
||||||
# Get current blocktime
|
# Get current blocktime
|
||||||
now = blockchain.w3.eth.getBlock(block_identifier='latest').timestamp
|
now = blockchain.w3.eth.getBlock(block_identifier='latest').timestamp
|
||||||
|
|
||||||
|
@ -445,7 +439,7 @@ def make_token_economics(blockchain):
|
||||||
economics = StandardTokenEconomics(
|
economics = StandardTokenEconomics(
|
||||||
worklock_boosting_refund_rate=200,
|
worklock_boosting_refund_rate=200,
|
||||||
worklock_commitment_duration=60, # periods
|
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_start_date=bidding_start_date,
|
||||||
bidding_end_date=bidding_end_date,
|
bidding_end_date=bidding_end_date,
|
||||||
cancellation_end_date=cancellation_end_date,
|
cancellation_end_date=cancellation_end_date,
|
||||||
|
@ -583,11 +577,11 @@ def _make_agency(testerchain,
|
||||||
registry=test_registry)
|
registry=test_registry)
|
||||||
worklock_deployer.deploy()
|
worklock_deployer.deploy()
|
||||||
|
|
||||||
token_agent = token_deployer.make_agent() # 1 Token
|
token_agent = token_deployer.make_agent() # 1 Token
|
||||||
staking_agent = staking_escrow_deployer.make_agent() # 2 Staking Escrow
|
staking_agent = staking_escrow_deployer.make_agent() # 2 Staking Escrow
|
||||||
policy_agent = policy_manager_deployer.make_agent() # 3 Policy Agent
|
policy_agent = policy_manager_deployer.make_agent() # 3 Policy Agent
|
||||||
_adjudicator_agent = adjudicator_deployer.make_agent() # 4 Adjudicator
|
_adjudicator_agent = adjudicator_deployer.make_agent() # 4 Adjudicator
|
||||||
_worklock_agent = worklock_deployer.make_agent() # 5 Worklock
|
_worklock_agent = worklock_deployer.make_agent() # 5 Worklock
|
||||||
|
|
||||||
# Set additional parameters
|
# Set additional parameters
|
||||||
minimum, default, maximum = FEE_RATE_RANGE
|
minimum, default, maximum = FEE_RATE_RANGE
|
||||||
|
@ -685,6 +679,8 @@ def stakers(testerchain, agency, token_economics, test_registry):
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def blockchain_ursulas(testerchain, stakers, ursula_decentralized_test_config):
|
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,
|
_ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
|
||||||
stakers_addresses=testerchain.stakers_accounts,
|
stakers_addresses=testerchain.stakers_accounts,
|
||||||
workers_addresses=testerchain.ursulas_accounts,
|
workers_addresses=testerchain.ursulas_accounts,
|
||||||
|
@ -897,7 +893,8 @@ def manual_staker(testerchain, agency):
|
||||||
address = '0xaaa23A5c74aBA6ca5E7c09337d5317A7C4563075'
|
address = '0xaaa23A5c74aBA6ca5E7c09337d5317A7C4563075'
|
||||||
if address not in testerchain.client.accounts:
|
if address not in testerchain.client.accounts:
|
||||||
staker_private_key = '13378db1c2af06933000504838afc2d52efa383206454deefb1836f8f4cd86f8'
|
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,
|
tx = {'to': address,
|
||||||
'from': testerchain.etherbase_account,
|
'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()
|
ursula.known_nodes.checksum = b"This is a fleet state checksum..".hex()
|
||||||
yield _ursulas
|
yield _ursulas
|
||||||
|
|
||||||
|
for ursula in _ursulas:
|
||||||
|
del MOCK_KNOWN_URSULAS_CACHE[ursula.rest_interface.port]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def highperf_mocked_alice(fleet_of_highperf_mocked_ursulas):
|
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()
|
bob._learning_task.stop()
|
||||||
return bob
|
return bob
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# CLI
|
# CLI
|
||||||
#
|
#
|
||||||
|
|
|
@ -30,6 +30,14 @@ from twisted.internet.threads import deferToThread
|
||||||
from nucypher.characters.lawful import Ursula
|
from nucypher.characters.lawful import Ursula
|
||||||
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE
|
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE
|
||||||
from nucypher.datastore.base import RecordField
|
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 (
|
from tests.mock.performance_mocks import (
|
||||||
NotAPublicKey,
|
NotAPublicKey,
|
||||||
NotARestApp,
|
NotARestApp,
|
||||||
|
|
Loading…
Reference in New Issue