mirror of https://github.com/nucypher/nucypher.git
migrate to new role names in progress
parent
32f8513ad7
commit
2669cfdedd
|
@ -1282,7 +1282,6 @@ class ThresholdWorker(BaseActor):
|
|||
self.is_me = is_me
|
||||
|
||||
self.__worker_address = worker_address
|
||||
self.__operator_address = None
|
||||
|
||||
# PRE Application
|
||||
self.pre_application_agent = ContractAgency.get_agent(PREApplicationAgent, registry=self.registry)
|
||||
|
@ -1295,21 +1294,21 @@ class ThresholdWorker(BaseActor):
|
|||
return self.__worker_address
|
||||
|
||||
@property
|
||||
def operator_address(self):
|
||||
if not self.__operator_address:
|
||||
self.__operator_address = self.get_operator_address()
|
||||
return self.__operator_address
|
||||
def staking_provider_address(self):
|
||||
if not self.__staking_provider_address:
|
||||
self.__staking_provider_address = self.get_staking_provider_address()
|
||||
return self.__staking_provider_address
|
||||
|
||||
def get_operator_address(self):
|
||||
self.__operator_address = self.pre_application_agent.get_operator_from_worker(self.worker_address)
|
||||
return self.__operator_address
|
||||
def get_staking_provider_address(self):
|
||||
self.__staking_provider_address = self.pre_application_agent.get_staking_provider_from_operator(self.worker_address)
|
||||
return self.__staking_provider_address
|
||||
|
||||
@property
|
||||
def is_confirmed(self):
|
||||
return self.pre_application_agent.is_worker_confirmed(self.worker_address)
|
||||
return self.pre_application_agent.is_operator_confirmed(self.worker_address)
|
||||
|
||||
def confirm_worker_address(self, fire_and_forget: bool = True) -> Union[TxReceipt, HexBytes]:
|
||||
txhash_or_receipt = self.pre_application_agent.confirm_worker_address(self.transacting_power, fire_and_forget=fire_and_forget)
|
||||
def confirm_operator_address(self, fire_and_forget: bool = True) -> Union[TxReceipt, HexBytes]:
|
||||
txhash_or_receipt = self.pre_application_agent.confirm_operator_address(self.transacting_power, fire_and_forget=fire_and_forget)
|
||||
return txhash_or_receipt
|
||||
|
||||
def block_until_ready(self, poll_rate: int = None, timeout: int = None, feedback_rate: int = None):
|
||||
|
@ -1327,11 +1326,11 @@ class ThresholdWorker(BaseActor):
|
|||
funded, balance = True, Web3.fromWei(ether_balance, 'ether')
|
||||
emitter.message(f"✓ Worker is funded with {balance} ETH", color='green')
|
||||
|
||||
if (not bonded) and (self.get_operator_address() != NULL_ADDRESS):
|
||||
if (not bonded) and (self.get_staking_provider_address() != NULL_ADDRESS):
|
||||
bonded = True
|
||||
emitter.message(f"✓ Worker is bonded to {self.operator_address}", color='green')
|
||||
emitter.message(f"✓ Worker is bonded to {self.worker_address}", color='green')
|
||||
else:
|
||||
emitter.message(f"✓ Worker {self.worker_address } is not bonded to an operator.", color='yellow')
|
||||
emitter.message(f"✓ Operator {self.worker_address } is not bonded to a staking provider.", color='yellow')
|
||||
|
||||
time.sleep(poll_rate)
|
||||
|
||||
|
|
|
@ -1029,13 +1029,13 @@ class PREApplicationAgent(EthereumContractAgent):
|
|||
return result
|
||||
|
||||
@contract_api(CONTRACT_CALL)
|
||||
def get_operator_from_worker(self, worker_address: ChecksumAddress) -> ChecksumAddress:
|
||||
result = self.contract.functions.operatorFromWorker(worker_address).call()
|
||||
def get_staking_provider_from_operator(self, worker_address: ChecksumAddress) -> ChecksumAddress:
|
||||
result = self.contract.functions.stakingProviderFromOperator(worker_address).call()
|
||||
return result
|
||||
|
||||
@contract_api(CONTRACT_CALL)
|
||||
def get_worker_from_operator(self, operator: ChecksumAddress) -> ChecksumAddress:
|
||||
result = self.contract.functions.getWorkerFromOperator(operator).call()
|
||||
def get_operator_from_staking_provider(self, operator: ChecksumAddress) -> ChecksumAddress:
|
||||
result = self.contract.functions.getOperatorFromStakingProvider(operator).call()
|
||||
return result
|
||||
|
||||
@contract_api(CONTRACT_CALL)
|
||||
|
@ -1044,8 +1044,8 @@ class PREApplicationAgent(EthereumContractAgent):
|
|||
return result
|
||||
|
||||
@contract_api(CONTRACT_CALL)
|
||||
def is_worker_confirmed(self, worker: ChecksumAddress) -> bool:
|
||||
result = self.contract.functions.isWorkerConfirmed(worker).call()
|
||||
def is_operator_confirmed(self, worker: ChecksumAddress) -> bool:
|
||||
result = self.contract.functions.isOperatorConfirmed(worker).call()
|
||||
return result
|
||||
|
||||
@contract_api(CONTRACT_CALL)
|
||||
|
@ -1068,7 +1068,7 @@ class PREApplicationAgent(EthereumContractAgent):
|
|||
#
|
||||
|
||||
@contract_api(TRANSACTION)
|
||||
def confirm_worker_address(self, transacting_power: TransactingPower, fire_and_forget: bool = True) -> TxReceipt:
|
||||
def confirm_operator_address(self, transacting_power: TransactingPower, fire_and_forget: bool = True) -> TxReceipt:
|
||||
"""Confirm the sender's account as a worker"""
|
||||
contract_function: ContractFunction = self.contract.functions.confirmWorkerAddress()
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||
|
|
|
@ -881,7 +881,7 @@ class SimplePREAppWorkTracker(WorkTrackerBaseClass):
|
|||
return True
|
||||
|
||||
def _final_work_prep_before_transaction(self):
|
||||
should_continue = self.worker.get_operator_address() != NULL_ADDRESS
|
||||
should_continue = self.worker.get_staking_provider_address() != NULL_ADDRESS
|
||||
if should_continue:
|
||||
return True
|
||||
self.log.warn('COMMIT PREVENTED - Worker is not bonded to an operator.')
|
||||
|
@ -891,9 +891,9 @@ class SimplePREAppWorkTracker(WorkTrackerBaseClass):
|
|||
"""Makes an initial/replacement worker commitment transaction"""
|
||||
transacting_power = self.worker.transacting_power
|
||||
with transacting_power:
|
||||
txhash = self.worker.confirm_worker_address(fire_and_forget=True) # < --- blockchain WRITE
|
||||
self.log.info(f"Confirming worker address {self.worker.worker_address} with operator {self.worker.operator_address} - TxHash: {txhash.hex()}")
|
||||
return txhash
|
||||
txhash = self.worker.confirm_operator_address(fire_and_forget=True) # < --- blockchain WRITE
|
||||
self.log.info(f"Confirming worker address {self.worker.worker_address} with staking provider {self.worker.staking_provider_address} - TxHash: {txhash.hex()}")
|
||||
return txhash
|
||||
|
||||
|
||||
class StakeList(UserList):
|
||||
|
|
|
@ -39,377 +39,19 @@ CONFIRMATION_SLOT = 1
|
|||
MIN_WORKER_SECONDS = 24 * 60 * 60
|
||||
|
||||
|
||||
|
||||
def log(message):
|
||||
logger.debug(message)
|
||||
print(message)
|
||||
|
||||
|
||||
def test_bond_worker(testerchain, threshold_staking, pre_application, token_economics):
|
||||
creator, operator1, operator2, operator3, operator4, worker1, worker2, worker3, owner3, *everyone_else = \
|
||||
testerchain.client.accounts
|
||||
min_authorization = token_economics.minimum_allowed_locked
|
||||
MIN_WORKER_SECONDS = 24 * 60 * 60
|
||||
|
||||
worker_log = pre_application.events.WorkerBonded.createFilter(fromBlock='latest')
|
||||
|
||||
# Prepare operators: two with intermediary contract and two just an operator
|
||||
tx = threshold_staking.functions.setRoles(operator1).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(operator1, min_authorization, 0, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setRoles(operator2).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(
|
||||
operator2, min_authorization // 3, min_authorization // 3, min_authorization // 3 - 1).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setRoles(operator3, owner3, everyone_else[0], everyone_else[1]).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(operator3, 0, min_authorization, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setRoles(operator4).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(operator4, 0, 0, min_authorization).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
assert pre_application.functions.getWorkerFromOperator(operator1).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.operatorFromWorker(operator1).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.getWorkerFromOperator(operator2).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.operatorFromWorker(operator2).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.getWorkerFromOperator(operator3).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.operatorFromWorker(operator3).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.getWorkerFromOperator(operator4).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.operatorFromWorker(operator4).call() == NULL_ADDRESS
|
||||
|
||||
# Operator can't confirm worker address because there is no worker by default
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': operator1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Operator can't bond another operator as worker
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator1, operator2).transact({'from': operator1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Operator can't bond worker if stake is less than minimum
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator2, worker1).transact({'from': operator2})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Only operator or stake owner can bond worker
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator3, worker1).transact({'from': everyone_else[0]})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator3, worker1).transact({'from': everyone_else[1]})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Operator bonds worker and now worker can make a confirmation
|
||||
tx = pre_application.functions.bondWorker(operator3, worker1).transact({'from': owner3})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
timestamp = testerchain.w3.eth.getBlock('latest').timestamp
|
||||
assert pre_application.functions.getWorkerFromOperator(operator3).call() == worker1
|
||||
assert pre_application.functions.operatorFromWorker(worker1).call() == operator3
|
||||
assert not pre_application.functions.operatorInfo(operator3).call()[CONFIRMATION_SLOT]
|
||||
assert not pre_application.functions.isWorkerConfirmed(worker1).call()
|
||||
assert pre_application.functions.getOperatorsLength().call() == 1
|
||||
assert pre_application.functions.operators(0).call() == operator3
|
||||
|
||||
# No active operators before confirmation
|
||||
all_locked, operators = pre_application.functions.getActiveOperators(0, 0).call()
|
||||
assert all_locked == 0
|
||||
assert len(operators) == 0
|
||||
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': worker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert pre_application.functions.operatorInfo(operator3).call()[CONFIRMATION_SLOT]
|
||||
assert pre_application.functions.isWorkerConfirmed(worker1).call()
|
||||
|
||||
number_of_events = 1
|
||||
events = worker_log.get_all_entries()
|
||||
assert len(events) == number_of_events
|
||||
event_args = events[-1]['args']
|
||||
assert event_args['operator'] == operator3
|
||||
assert event_args['worker'] == worker1
|
||||
assert event_args['startTimestamp'] == timestamp
|
||||
|
||||
# After confirmation worker is becoming active
|
||||
all_locked, operators = pre_application.functions.getActiveOperators(0, 0).call()
|
||||
assert all_locked == min_authorization
|
||||
assert len(operators) == 1
|
||||
assert to_checksum_address(operators[0][0]) == operator3
|
||||
assert operators[0][1] == min_authorization
|
||||
|
||||
# Worker is in use so other operators can't bond him
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator4, worker1).transact({'from': operator4})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# # Worker can't be an operator
|
||||
# tx = threshold_staking.functions.setRoles(worker1).transact()
|
||||
# testerchain.wait_for_receipt(tx)
|
||||
# tx = threshold_staking.functions.setStakes(worker1, min_authorization, 0, 0).transact()
|
||||
# testerchain.wait_for_receipt(tx)
|
||||
# with pytest.raises((TransactionFailed, ValueError)):
|
||||
# tx = threshold_staking.functions.increaseAuthorization(
|
||||
# worker1, min_authorization, pre_application.address).transact({'from': worker1})
|
||||
# testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Can't bond worker twice too soon
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator3, worker2).transact({'from': operator3})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# She can't unbond her worker too, until enough time has passed
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator3, NULL_ADDRESS).transact({'from': operator3})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Let's advance some time and unbond the worker
|
||||
testerchain.time_travel(seconds=MIN_WORKER_SECONDS)
|
||||
tx = pre_application.functions.bondWorker(operator3, NULL_ADDRESS).transact({'from': operator3})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
timestamp = testerchain.w3.eth.getBlock('latest').timestamp
|
||||
assert pre_application.functions.getWorkerFromOperator(operator3).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.operatorFromWorker(operator3).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.operatorFromWorker(worker1).call() == NULL_ADDRESS
|
||||
assert not pre_application.functions.operatorInfo(operator3).call()[CONFIRMATION_SLOT]
|
||||
assert not pre_application.functions.isWorkerConfirmed(worker1).call()
|
||||
assert pre_application.functions.getOperatorsLength().call() == 1
|
||||
assert pre_application.functions.operators(0).call() == operator3
|
||||
|
||||
# Resetting worker removes from active list before next confirmation
|
||||
all_locked, operators = pre_application.functions.getActiveOperators(0, 0).call()
|
||||
assert all_locked == 0
|
||||
assert len(operators) == 0
|
||||
|
||||
number_of_events += 1
|
||||
events = worker_log.get_all_entries()
|
||||
assert len(events) == number_of_events
|
||||
event_args = events[-1]['args']
|
||||
assert event_args['operator'] == operator3
|
||||
# Now the worker has been unbonded ...
|
||||
assert event_args['worker'] == NULL_ADDRESS
|
||||
# ... with a new starting period.
|
||||
assert event_args['startTimestamp'] == timestamp
|
||||
|
||||
# The operator can bond now a new worker, without waiting additional time.
|
||||
tx = pre_application.functions.bondWorker(operator3, worker2).transact({'from': operator3})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
timestamp = testerchain.w3.eth.getBlock('latest').timestamp
|
||||
assert pre_application.functions.getWorkerFromOperator(operator3).call() == worker2
|
||||
assert pre_application.functions.operatorFromWorker(worker2).call() == operator3
|
||||
assert not pre_application.functions.operatorInfo(operator3).call()[CONFIRMATION_SLOT]
|
||||
assert not pre_application.functions.isWorkerConfirmed(worker2).call()
|
||||
assert pre_application.functions.getOperatorsLength().call() == 1
|
||||
assert pre_application.functions.operators(0).call() == operator3
|
||||
|
||||
number_of_events += 1
|
||||
events = worker_log.get_all_entries()
|
||||
assert len(events) == number_of_events
|
||||
event_args = events[-1]['args']
|
||||
assert event_args['operator'] == operator3
|
||||
assert event_args['worker'] == worker2
|
||||
assert event_args['startTimestamp'] == timestamp
|
||||
|
||||
# Now the previous worker can no longer make a confirmation
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': worker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
# Only new worker can
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': worker2})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert not pre_application.functions.isWorkerConfirmed(worker1).call()
|
||||
assert pre_application.functions.isWorkerConfirmed(worker2).call()
|
||||
assert pre_application.functions.operatorInfo(operator3).call()[CONFIRMATION_SLOT]
|
||||
|
||||
# Another staker can bond a free worker
|
||||
tx = pre_application.functions.bondWorker(operator4, worker1).transact({'from': operator4})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
timestamp = testerchain.w3.eth.getBlock('latest').timestamp
|
||||
assert pre_application.functions.getWorkerFromOperator(operator4).call() == worker1
|
||||
assert pre_application.functions.operatorFromWorker(worker1).call() == operator4
|
||||
assert not pre_application.functions.isWorkerConfirmed(worker1).call()
|
||||
assert not pre_application.functions.operatorInfo(operator4).call()[CONFIRMATION_SLOT]
|
||||
assert pre_application.functions.getOperatorsLength().call() == 2
|
||||
assert pre_application.functions.operators(1).call() == operator4
|
||||
|
||||
number_of_events += 1
|
||||
events = worker_log.get_all_entries()
|
||||
assert len(events) == number_of_events
|
||||
event_args = events[-1]['args']
|
||||
assert event_args['operator'] == operator4
|
||||
assert event_args['worker'] == worker1
|
||||
assert event_args['startTimestamp'] == timestamp
|
||||
|
||||
# # The first worker still can't be a staker
|
||||
# tx = threshold_staking.functions.setRoles(worker1).transact()
|
||||
# testerchain.wait_for_receipt(tx)
|
||||
# tx = threshold_staking.functions.setStakes(worker1, min_authorization, 0, 0).transact()
|
||||
# testerchain.wait_for_receipt(tx)
|
||||
# with pytest.raises((TransactionFailed, ValueError)):
|
||||
# tx = threshold_staking.functions.increaseAuthorization(
|
||||
# worker1, min_authorization, pre_application.address).transact({'from': worker1})
|
||||
# testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Bond worker again
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': worker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert pre_application.functions.isWorkerConfirmed(worker1).call()
|
||||
assert pre_application.functions.operatorInfo(operator4).call()[CONFIRMATION_SLOT]
|
||||
testerchain.time_travel(seconds=MIN_WORKER_SECONDS)
|
||||
tx = pre_application.functions.bondWorker(operator4, worker3).transact({'from': operator4})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
timestamp = testerchain.w3.eth.getBlock('latest').timestamp
|
||||
assert pre_application.functions.getWorkerFromOperator(operator4).call() == worker3
|
||||
assert pre_application.functions.operatorFromWorker(worker3).call() == operator4
|
||||
assert pre_application.functions.operatorFromWorker(worker1).call() == NULL_ADDRESS
|
||||
assert not pre_application.functions.isWorkerConfirmed(worker3).call()
|
||||
assert not pre_application.functions.isWorkerConfirmed(worker1).call()
|
||||
assert not pre_application.functions.operatorInfo(operator4).call()[CONFIRMATION_SLOT]
|
||||
assert pre_application.functions.getOperatorsLength().call() == 2
|
||||
assert pre_application.functions.operators(1).call() == operator4
|
||||
|
||||
# Resetting worker removes from active list before next confirmation
|
||||
all_locked, operators = pre_application.functions.getActiveOperators(1, 0).call()
|
||||
assert all_locked == 0
|
||||
assert len(operators) == 0
|
||||
|
||||
number_of_events += 1
|
||||
events = worker_log.get_all_entries()
|
||||
assert len(events) == number_of_events
|
||||
event_args = events[-1]['args']
|
||||
assert event_args['operator'] == operator4
|
||||
assert event_args['worker'] == worker3
|
||||
assert event_args['startTimestamp'] == timestamp
|
||||
|
||||
# The first worker is free and can deposit tokens and become a staker
|
||||
tx = threshold_staking.functions.setRoles(worker1).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(
|
||||
worker1, min_authorization // 3, min_authorization // 3, min_authorization // 3).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
# tx = threshold_staking.functions.increaseAuthorization(
|
||||
# worker1, min_authorization, pre_application.address).transact({'from': worker1})
|
||||
# testerchain.wait_for_receipt(tx)
|
||||
assert pre_application.functions.getWorkerFromOperator(worker1).call() == NULL_ADDRESS
|
||||
assert pre_application.functions.operatorFromWorker(worker1).call() == NULL_ADDRESS
|
||||
|
||||
# Operator can't bond the first worker again because worker is an operator now
|
||||
testerchain.time_travel(seconds=MIN_WORKER_SECONDS)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.bondWorker(operator4, worker1).transact({'from': operator4})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Operator without intermediary contract can bond itself as worker
|
||||
# (Probably not best idea, but whatever)
|
||||
tx = pre_application.functions.bondWorker(operator1, operator1).transact({'from': operator1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
timestamp = testerchain.w3.eth.getBlock('latest').timestamp
|
||||
assert pre_application.functions.getWorkerFromOperator(operator1).call() == operator1
|
||||
assert pre_application.functions.operatorFromWorker(operator1).call() == operator1
|
||||
assert pre_application.functions.getOperatorsLength().call() == 3
|
||||
assert pre_application.functions.operators(2).call() == operator1
|
||||
|
||||
number_of_events += 1
|
||||
events = worker_log.get_all_entries()
|
||||
assert len(events) == number_of_events
|
||||
event_args = events[-1]['args']
|
||||
assert event_args['operator'] == operator1
|
||||
assert event_args['worker'] == operator1
|
||||
assert event_args['startTimestamp'] == timestamp
|
||||
|
||||
# If stake will be less than minimum then confirmation is not possible
|
||||
tx = threshold_staking.functions.setStakes(operator1, 0, min_authorization - 1, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': operator1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Now operator can make a confirmation
|
||||
tx = threshold_staking.functions.setStakes(operator1, 0, 0, min_authorization).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': operator1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# If stake will be less than minimum then operator is not active
|
||||
all_locked, operators = pre_application.functions.getActiveOperators(0, 0).call()
|
||||
assert all_locked == 2 * min_authorization
|
||||
assert len(operators) == 2
|
||||
assert to_checksum_address(operators[0][0]) == operator3
|
||||
assert operators[0][1] == min_authorization
|
||||
assert to_checksum_address(operators[1][0]) == operator1
|
||||
assert operators[1][1] == min_authorization
|
||||
tx = threshold_staking.functions.setStakes(operator1, 0, min_authorization - 1, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
all_locked, operators = pre_application.functions.getActiveOperators(1, 0).call()
|
||||
assert all_locked == 0
|
||||
assert len(operators) == 0
|
||||
|
||||
|
||||
def test_confirm_address(testerchain, threshold_staking, pre_application, token_economics, deploy_contract):
|
||||
creator, operator, worker, *everyone_else = testerchain.client.accounts
|
||||
min_authorization = token_economics.minimum_allowed_locked
|
||||
|
||||
|
||||
confirmations_log = pre_application.events.WorkerConfirmed.createFilter(fromBlock='latest')
|
||||
|
||||
# Worker must be associated with operator that has minimum amount of tokens
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': operator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setRoles(operator).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(operator, min_authorization - 1, 0, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': operator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Deploy intermediary contract
|
||||
intermediary, _ = deploy_contract('Intermediary', pre_application.address)
|
||||
|
||||
# Bond contract as a worker
|
||||
tx = threshold_staking.functions.setStakes(operator, min_authorization, 0, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = pre_application.functions.bondWorker(operator, intermediary.address).transact({'from': operator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# But can't make a confirmation using an intermediary contract
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = intermediary.functions.confirmWorkerAddress().transact({'from': operator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Bond worker again and make confirmation
|
||||
testerchain.time_travel(seconds=MIN_WORKER_SECONDS)
|
||||
tx = pre_application.functions.bondWorker(operator, worker).transact({'from': operator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': worker})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert pre_application.functions.isWorkerConfirmed(worker).call()
|
||||
assert pre_application.functions.operatorInfo(operator).call()[CONFIRMATION_SLOT]
|
||||
|
||||
events = confirmations_log.get_all_entries()
|
||||
assert len(events) == 1
|
||||
event_args = events[-1]['args']
|
||||
assert event_args['operator'] == operator
|
||||
assert event_args['worker'] == worker
|
||||
|
||||
# Can't confirm twice
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = pre_application.functions.confirmWorkerAddress().transact({'from': worker})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
|
||||
def test_ursula_contract_interactions(ursula_decentralized_test_config, testerchain, threshold_staking, pre_application, token_economics, deploy_contract):
|
||||
creator, operator, worker_address, *everyone_else = testerchain.client.accounts
|
||||
creator, staking_provider, worker_address, *everyone_else = testerchain.client.accounts
|
||||
min_authorization = token_economics.minimum_allowed_locked
|
||||
|
||||
# make an operators and some stakes
|
||||
tx = threshold_staking.functions.setRoles(operator).transact()
|
||||
# make an staking_providers and some stakes
|
||||
tx = threshold_staking.functions.setRoles(staking_provider).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(operator, min_authorization, 0, 0).transact()
|
||||
tx = threshold_staking.functions.setStakes(staking_provider, min_authorization, 0, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# make an ursula.
|
||||
|
@ -421,20 +63,20 @@ def test_ursula_contract_interactions(ursula_decentralized_test_config, testerch
|
|||
# it's not confirmed
|
||||
assert blockchain_ursula.is_confirmed is False
|
||||
|
||||
# it has no operator
|
||||
assert blockchain_ursula.get_operator_address() == NULL_ADDRESS
|
||||
# it has no staking provider
|
||||
assert blockchain_ursula.get_staking_provider_address() == NULL_ADDRESS
|
||||
|
||||
# now lets visit stake.nucypher.network and bond this worker
|
||||
tx = pre_application.functions.bondWorker(operator, worker_address).transact({'from': operator})
|
||||
tx = pre_application.functions.bondWorker(staking_provider, worker_address).transact({'from': staking_provider})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# now the worker has an operator
|
||||
assert blockchain_ursula.get_operator_address() == operator
|
||||
# now the worker has a staking provider
|
||||
assert blockchain_ursula.get_staking_provider_address() == staking_provider
|
||||
# but it still isn't confirmed
|
||||
assert blockchain_ursula.is_confirmed is False
|
||||
|
||||
# lets confirm it. It will probably do this automatically in real life...
|
||||
tx = blockchain_ursula.confirm_worker_address()
|
||||
tx = blockchain_ursula.confirm_staking_provider_address()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
assert blockchain_ursula.is_confirmed is True
|
||||
|
@ -443,13 +85,13 @@ def test_ursula_contract_interactions(ursula_decentralized_test_config, testerch
|
|||
@pytest_twisted.inlineCallbacks
|
||||
def test_worker_auto_confirm_on_startup(mocker, ursula_decentralized_test_config, testerchain, threshold_staking, pre_application, token_economics, deploy_contract):
|
||||
|
||||
creator, operator, worker_address, *everyone_else = testerchain.client.accounts
|
||||
creator, staking_provider, operator, *everyone_else = testerchain.client.accounts
|
||||
min_authorization = token_economics.minimum_allowed_locked
|
||||
|
||||
# make an operators and some stakes
|
||||
tx = threshold_staking.functions.setRoles(operator).transact()
|
||||
# make an staking_providers and some stakes
|
||||
tx = threshold_staking.functions.setRoles(staking_provider).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = threshold_staking.functions.setStakes(operator, min_authorization, 0, 0).transact()
|
||||
tx = threshold_staking.functions.setStakes(staking_provider, min_authorization, 0, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Control time
|
||||
|
@ -457,15 +99,15 @@ def test_worker_auto_confirm_on_startup(mocker, ursula_decentralized_test_config
|
|||
WorkTracker.CLOCK = clock
|
||||
|
||||
# Bond the Worker and Staker
|
||||
tx = pre_application.functions.bondWorker(operator, worker_address).transact({'from': operator})
|
||||
tx = pre_application.functions.bondOperator(staking_provider, operator).transact({'from': staking_provider})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
commit_spy = mocker.spy(Worker, 'confirm_worker_address')
|
||||
commit_spy = mocker.spy(Worker, 'confirm_operator_address')
|
||||
# replacement_spy = mocker.spy(WorkTracker, '_WorkTracker__fire_replacement_commitment')
|
||||
|
||||
# Make the Worker
|
||||
ursula = ursula_decentralized_test_config.produce(
|
||||
worker_address=worker_address,
|
||||
worker_address=operator,
|
||||
db_filepath=MOCK_DB,
|
||||
rest_port=9151)
|
||||
|
||||
|
@ -474,7 +116,7 @@ def test_worker_auto_confirm_on_startup(mocker, ursula_decentralized_test_config
|
|||
start_reactor=False,
|
||||
worker=True,
|
||||
eager=True,
|
||||
block_until_ready=False) # "start" services
|
||||
block_until_ready=True) # "start" services
|
||||
|
||||
def start():
|
||||
log("Starting Worker for auto confirm address simulation")
|
||||
|
@ -524,7 +166,7 @@ def test_worker_auto_confirm_on_startup(mocker, ursula_decentralized_test_config
|
|||
assert commit_spy.call_count == expected_commitments
|
||||
# assert replacement_spy.call_count == 0
|
||||
|
||||
assert ursula.is_confirmed is True
|
||||
assert pre_application.functions.isOperatorConfirmed(operator).call()
|
||||
|
||||
# Behavioural Test, like a screenplay made of legos
|
||||
|
||||
|
|
Loading…
Reference in New Issue