class StakeTracker: REFRESH_RATE = 60 tracking_addresses = set() __stakes = dict() # type: Dict[str: List[Stake]] __actions = list() # type: List[Tuple[Callable, tuple]] def __init__(self, checksum_addresses: List[str], refresh_rate: int = None, start_now: bool = False, *args, **kwargs): super().__init__(*args, **kwargs) self.log = Logger('stake-tracker') self.staking_agent = StakingEscrowAgent() self._refresh_rate = refresh_rate or self.REFRESH_RATE self._tracking_task = task.LoopingCall(self.__update) self.__current_period = None self.__stakes = dict() self.__start_time = NOT_STAKING self.__uptime_period = NOT_STAKING self.__terminal_period = NOT_STAKING self._abort_on_stake_tracking_error = True # "load-in": Read on-chain stakes for checksum_address in checksum_addresses: if not is_checksum_address(checksum_address): raise ValueError( f'{checksum_address} is not a valid EIP-55 checksum address' ) self.tracking_addresses.add(checksum_address) if start_now: self.start() # deamonize else: self.refresh(checksum_addresses=checksum_addresses) # read-once @validate_checksum_address def __getitem__(self, checksum_address: str): stakes = self.stakes(checksum_address=checksum_address) return stakes def add_action(self, func: Callable, args=()) -> None: self.__actions.append((func, args)) def clear_actions(self) -> None: self.__actions.clear() @property def current_period(self): return self.__current_period @validate_checksum_address def stakes(self, checksum_address: str) -> List[Stake]: """Return all cached stake instances from the blockchain.""" try: return self.__stakes[checksum_address] except KeyError: return NO_STAKES.bool_value(False) except TypeError: if self.__stakes in (UNKNOWN_STAKES, NO_STAKES): return NO_STAKES.bool_value(False) raise @validate_checksum_address def refresh(self, checksum_addresses: List[str] = None) -> None: """Public staking cache invalidation method""" return self.__read_stakes(checksum_addresses=checksum_addresses) def stop(self) -> None: self._tracking_task.stop() self.log.info(f"STOPPED STAKE TRACKING") def start(self, force: bool = False) -> None: """ High-level stake tracking initialization, this function aims to be safely called at any time - For example, it is okay to call this function multiple times within the same period. """ if self._tracking_task.running and not force: return # Record the start time and period self.__start_time = maya.now() self.__uptime_period = self.staking_agent.get_current_period() self.__current_period = self.__uptime_period d = self._tracking_task.start(interval=self._refresh_rate) d.addErrback(self.handle_tracking_errors) self.log.info( f"STARTED STAKE TRACKING for {len(self.tracking_addresses)} addresses" ) def _crash_gracefully(self, failure=None) -> None: """ A facility for crashing more gracefully in the event that an exception is unhandled in a different thread. """ self._crashed = failure failure.raiseException() def handle_tracking_errors(self, *args, **kwargs) -> None: failure = args[0] if self._abort_on_stake_tracking_error: self.log.critical( f"Unhandled error during node stake tracking. {failure}") reactor.callFromThread(self._crash_gracefully, failure=failure) else: self.log.warn( f"Unhandled error during stake tracking: {failure.getTraceback()}" ) def __update(self) -> None: self.log.info( f"Checking for new period. Current period is {self.__current_period}" ) onchain_period = self.staking_agent.get_current_period( ) # < -- Read from contract if self.__current_period != onchain_period: self.__current_period = onchain_period self.__read_stakes() for action, args in self.__actions: action(*args) @validate_checksum_address def __read_stakes(self, checksum_addresses: List[str] = None) -> None: """Rewrite the local staking cache by reading on-chain stakes""" if not checksum_addresses: checksum_addresses = self.tracking_addresses for checksum_address in checksum_addresses: if not is_checksum_address(checksum_address): if self._abort_on_stake_tracking_error: raise ValueError( f'{checksum_address} is not a valid EIP-55 checksum address' ) self.tracking_addresses.remove(checksum_address) # Prune existing_records = len( self.stakes(checksum_address=checksum_address)) # Candidate replacement cache values onchain_stakes, terminal_period = list(), 0 # Read from blockchain stakes_reader = self.staking_agent.get_all_stakes( staker_address=checksum_address) for onchain_index, stake_info in enumerate(stakes_reader): if not stake_info: onchain_stake = EMPTY_STAKING_SLOT else: onchain_stake = Stake.from_stake_info( checksum_address=checksum_address, stake_info=stake_info, index=onchain_index) # rack the latest terminal period if onchain_stake.end_period > terminal_period: terminal_period = onchain_stake.end_period # Store the replacement stake onchain_stakes.append(onchain_stake) # Commit the new stake and terminal values to the cache if not onchain_stakes: self.__stakes[checksum_address] = NO_STAKES.bool_value(False) else: self.__terminal_period = terminal_period self.__stakes[checksum_address] = onchain_stakes new_records = existing_records - len( self.__stakes[checksum_address]) self.log.debug( f"Updated local staking cache ({new_records} new stakes).") # Record most recent cache update self.__updated = maya.now()
def estimate_gas(analyzer: AnalyzeGas = None) -> None: """ Execute a linear sequence of NyCypher transactions mimicking post-deployment usage on a local PyEVM blockchain; Record the resulting estimated transaction gas expenditure. Note: The function calls below are *order dependant* """ # # Setup # if analyzer is None: analyzer = AnalyzeGas() log = Logger(AnalyzeGas.LOG_NAME) os.environ[ 'GAS_ESTIMATOR_BACKEND_FUNC'] = 'eth.estimators.gas.binary_gas_search_exact' # Blockchain economics = StandardTokenEconomics(base_penalty=MIN_ALLOWED_LOCKED - 1, penalty_history_coefficient=0, percentage_penalty_coefficient=2, reward_coefficient=2) testerchain, registry = TesterBlockchain.bootstrap_network( economics=economics) web3 = testerchain.w3 print("\n********* SIZE OF MAIN CONTRACTS *********") MAX_SIZE = 24576 rows = list() for contract_name in NUCYPHER_CONTRACT_NAMES: compiled_contract = testerchain._raw_contract_cache[contract_name] version = list(compiled_contract).pop() bin_runtime = compiled_contract[version]['bin-runtime'] bin_length_in_bytes = len(bin_runtime) // 2 percentage = int(100 * bin_length_in_bytes / MAX_SIZE) bar = ('*' * (percentage // 2)).ljust(50) rows.append( (contract_name, bin_length_in_bytes, f'{bar} {percentage}%')) headers = ('Contract', 'Size (B)', f'% of max allowed contract size ({MAX_SIZE} B)') print(tabulate.tabulate(rows, headers=headers, tablefmt="simple"), end="\n\n") # Accounts origin, staker1, staker2, staker3, staker4, alice1, alice2, *everyone_else = testerchain.client.accounts ursula_with_stamp = mock_ursula(testerchain, staker1) # Contracts token_agent = NucypherTokenAgent(registry=registry) staking_agent = StakingEscrowAgent(registry=registry) policy_agent = PolicyManagerAgent(registry=registry) adjudicator_agent = AdjudicatorAgent(registry=registry) # Contract Callers token_functions = token_agent.contract.functions staker_functions = staking_agent.contract.functions policy_functions = policy_agent.contract.functions adjudicator_functions = adjudicator_agent.contract.functions analyzer.start_collection() print("********* Estimating Gas *********") def transact_and_log(label, function, transaction): estimates = function.estimateGas(transaction) transaction.update(gas=estimates) tx = function.transact(transaction) receipt = testerchain.wait_for_receipt(tx) log.info(f"{label} = {estimates} | {receipt['gasUsed']}") def transact(function, transaction): transaction.update(gas=1000000) tx = function.transact(transaction) testerchain.wait_for_receipt(tx) # # Give Ursula and Alice some coins # transact_and_log( "Transfer tokens", token_functions.transfer(staker1, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(staker2, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(staker3, MIN_ALLOWED_LOCKED * 10), {'from': origin}) # # Ursula and Alice give Escrow rights to transfer # transact_and_log( "Approving transfer", token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 7), {'from': staker1}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': staker2}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': staker3}) # # Batch deposit tokens # current_period = staking_agent.get_current_period() transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact_and_log( "Batch deposit tokens for 5 owners x 2 sub-stakes", staker_functions.batchDeposit(everyone_else[0:5], [2] * 5, [MIN_ALLOWED_LOCKED] * 10, [MIN_LOCKED_PERIODS] * 10), {'from': origin}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 24), {'from': origin}) transact_and_log( "Batch deposit tokens for 1 owners x 24 sub-stakes", staker_functions.batchDeposit([everyone_else[6]], [24], [MIN_ALLOWED_LOCKED] * 24, [MIN_LOCKED_PERIODS] * 24), {'from': origin}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 24 * 5), {'from': origin}) transact_and_log( "Batch deposit tokens for 5 owners x 24 sub-stakes", staker_functions.batchDeposit(everyone_else[7:12], [24] * 5, [MIN_ALLOWED_LOCKED] * (24 * 5), [MIN_LOCKED_PERIODS] * (24 * 5)), {'from': origin}) # # Ursula and Alice transfer some tokens to the escrow and lock them # transact_and_log( "Initial deposit tokens, first", staker_functions.deposit(staker1, MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': staker1}) transact_and_log( "Initial deposit tokens, other", staker_functions.deposit(staker2, MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': staker2}) transact( staker_functions.deposit(staker3, MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': staker3}) transact(staker_functions.bondWorker(staker1), {'from': staker1}) transact(staker_functions.bondWorker(staker2), {'from': staker2}) transact(staker_functions.bondWorker(staker3), {'from': staker3}) transact(staker_functions.setReStake(False), {'from': staker1}) transact(staker_functions.setReStake(False), {'from': staker2}) transact(staker_functions.setWindDown(True), {'from': staker1}) transact(staker_functions.setWindDown(True), {'from': staker2}) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.commitToNextPeriod(), {'from': staker2}) # # Wait 1 period and make a commitment # testerchain.time_travel(periods=1) transact_and_log("Make a commitment, first", staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log("Make a commitment, other", staker_functions.commitToNextPeriod(), {'from': staker2}) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact_and_log("Minting (1 stake), first", staker_functions.mint(), {'from': staker1}) transact_and_log("Minting (1 stake), other", staker_functions.mint(), {'from': staker2}) transact_and_log("Make a commitment again, first", staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log("Make a commitment again, other", staker_functions.commitToNextPeriod(), {'from': staker2}) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) # # Commit again # testerchain.time_travel(periods=1) transact_and_log("Make a commitment + mint, first", staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log("Make a commitment + mint, other", staker_functions.commitToNextPeriod(), {'from': staker2}) # # Create policy # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) number_of_periods = 10 rate = 100 one_period = economics.hours_per_period * 60 * 60 value = number_of_periods * rate current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (1 node, 10 periods, pre-committed), first", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [staker1]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (1 node, 10 periods, pre-committed), other", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [staker1]), { 'from': alice1, 'value': value }) # # Get locked tokens # transact_and_log("Getting locked tokens", staker_functions.getLockedTokens(staker1, 0), {}) # # Wait 1 period and withdraw tokens # testerchain.time_travel(periods=1) transact_and_log("Withdraw", staker_functions.withdraw(1), {'from': staker1}) # # Make a commitment with re-stake # transact(staker_functions.setReStake(True), {'from': staker1}) transact(staker_functions.setReStake(True), {'from': staker2}) # Used to remove spending for first call in a day for mint and commitToNextPeriod transact(staker_functions.commitToNextPeriod(), {'from': staker3}) transact_and_log("Make a commitment + mint + re-stake", staker_functions.commitToNextPeriod(), {'from': staker2}) transact_and_log( "Make a commitment + mint + re-stake + first fee + first fee rate", staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.setReStake(False), {'from': staker1}) transact(staker_functions.setReStake(False), {'from': staker2}) # # Wait 2 periods and make a commitment after downtime # testerchain.time_travel(periods=2) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) transact_and_log("Make a commitment after downtime", staker_functions.commitToNextPeriod(), {'from': staker2}) transact_and_log("Make a commitment after downtime + updating fee", staker_functions.commitToNextPeriod(), {'from': staker1}) # # Ursula and Alice deposit some tokens to the escrow again # transact_and_log( "Deposit tokens after making a commitment", staker_functions.deposit(staker1, MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS), {'from': staker1}) transact( staker_functions.deposit(staker2, MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS), {'from': staker2}) # # Revoke policy # transact_and_log("Revoking policy", policy_functions.revokePolicy(policy_id_1), {'from': alice1}) # # Wait 1 period # testerchain.time_travel(periods=1) # # Create policy with multiple pre-committed nodes # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(Policy.POLICY_ID_LENGTH)) number_of_periods = 100 value = 3 * number_of_periods * rate current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (3 nodes, 100 periods, pre-committed), first", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [staker1, staker2, staker3]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (3 nodes, 100 periods, pre-committed), other", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [staker1, staker2, staker3]), { 'from': alice1, 'value': value }) value = 2 * number_of_periods * rate transact_and_log( "Creating policy (2 nodes, 100 periods, pre-committed), other", policy_functions.createPolicy(policy_id_3, alice1, end_timestamp, [staker1, staker2]), { 'from': alice1, 'value': value }) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': staker3}) transact_and_log("Last minting + updating fee + updating fee rate", staker_functions.mint(), {'from': staker1}) transact_and_log("Last minting + first fee + first fee rate", staker_functions.mint(), {'from': staker2}) # # Create policy again without pre-committed nodes # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(Policy.POLICY_ID_LENGTH)) number_of_periods = 100 value = number_of_periods * rate current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (1 node, 100 periods)", policy_functions.createPolicy(policy_id_1, alice2, end_timestamp, [staker2]), { 'from': alice1, 'value': value }) testerchain.time_travel(periods=1) current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (1 node, 100 periods), next period", policy_functions.createPolicy(policy_id_2, alice2, end_timestamp, [staker2]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (1 node, 100 periods), another node", policy_functions.createPolicy(policy_id_3, alice2, end_timestamp, [staker1]), { 'from': alice1, 'value': value }) # # Mint and revoke policy # testerchain.time_travel(periods=10) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) testerchain.time_travel(periods=2) transact(staker_functions.mint(), {'from': staker3}) transact_and_log("Last minting after downtime + updating fee", staker_functions.mint(), {'from': staker1}) testerchain.time_travel(periods=10) transact_and_log("Revoking policy after downtime, 1st policy", policy_functions.revokePolicy(policy_id_1), {'from': alice2}) transact_and_log("Revoking policy after downtime, 2nd policy", policy_functions.revokePolicy(policy_id_2), {'from': alice2}) transact_and_log("Revoking policy after downtime, 3rd policy", policy_functions.revokePolicy(policy_id_3), {'from': alice2}) for index in range(5): transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': staker1}) # # Check regular deposit # transact_and_log( "Deposit tokens to new sub-stake", staker_functions.deposit(staker1, MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': staker1}) transact_and_log( "Deposit tokens using existing sub-stake", staker_functions.depositAndIncrease(0, MIN_ALLOWED_LOCKED), {'from': staker1}) # # ApproveAndCall # testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': staker1}) transact_and_log( "ApproveAndCall", token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)), {'from': staker1}) # # Locking tokens # testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log( "Locking tokens and creating new sub-stake", staker_functions.lockAndCreate(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': staker1}) transact_and_log("Locking tokens using existing sub-stake", staker_functions.lockAndIncrease(0, MIN_ALLOWED_LOCKED), {'from': staker1}) # # Divide stake # transact_and_log("Divide stake", staker_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2), {'from': staker1}) transact(staker_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2), {'from': staker1}) # # Divide almost finished stake # testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) # # Slashing tests # transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) # # Slashing # slashing_args = generate_args_for_slashing(ursula_with_stamp) transact_and_log("Slash just value", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) deposit = staker_functions.stakerInfo(staker1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(staker1, 0).call() transact(staker_functions.withdraw(unlocked), {'from': staker1}) sub_stakes_length = str( staker_functions.getSubStakesLength(staker1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) transact_and_log( "Slashing one sub stake and saving old one (" + sub_stakes_length + " sub stakes), 1st", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) sub_stakes_length = str( staker_functions.getSubStakesLength(staker1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) transact_and_log( "Slashing one sub stake and saving old one (" + sub_stakes_length + " sub stakes), 2nd", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) sub_stakes_length = str( staker_functions.getSubStakesLength(staker1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) transact_and_log( "Slashing one sub stake and saving old one (" + sub_stakes_length + " sub stakes), 3rd", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) sub_stakes_length = str( staker_functions.getSubStakesLength(staker1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) transact_and_log( "Slashing two sub stakes and saving old one (" + sub_stakes_length + " sub stakes)", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) for index in range(18): transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) transact( staker_functions.lockAndCreate(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': staker1}) deposit = staker_functions.stakerInfo(staker1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(staker1, 1).call() transact(staker_functions.withdraw(unlocked), {'from': staker1}) sub_stakes_length = str( staker_functions.getSubStakesLength(staker1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) transact_and_log( "Slashing two sub stakes, shortest and new one (" + sub_stakes_length + " sub stakes)", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) sub_stakes_length = str( staker_functions.getSubStakesLength(staker1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) transact_and_log( "Slashing three sub stakes, two shortest and new one (" + sub_stakes_length + " sub stakes)", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) slashing_args = generate_args_for_slashing(ursula_with_stamp, corrupt_cfrag=False) transact_and_log("Evaluating correct CFrag", adjudicator_functions.evaluateCFrag(*slashing_args), {'from': alice1}) transact_and_log("Prolong stake", staker_functions.prolongStake(0, 20), {'from': staker1}) transact_and_log("Merge sub-stakes", staker_functions.mergeStake(2, 3), {'from': staker1}) # Large number of sub-stakes number_of_sub_stakes = 24 transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * number_of_sub_stakes), {'from': origin}) transact( staker_functions.batchDeposit( [staker4], [number_of_sub_stakes], [MIN_ALLOWED_LOCKED] * number_of_sub_stakes, [MIN_LOCKED_PERIODS] * number_of_sub_stakes), {'from': origin}) transact(staker_functions.bondWorker(staker4), {'from': staker4}) transact(staker_functions.setWindDown(True), {'from': staker4}) # Used to remove spending for first call in a day for mint and commitToNextPeriod transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log(f"Make a commitment ({number_of_sub_stakes} sub-stakes)", staker_functions.commitToNextPeriod(), {'from': staker4}) testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker4}) testerchain.time_travel(periods=1) # Used to remove spending for first call in a day for mint and commitToNextPeriod transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log( f"Make a commitment + mint + re-stake ({number_of_sub_stakes} sub-stakes)", staker_functions.commitToNextPeriod(), {'from': staker4}) print("********* All Done! *********")
def test_nucypher_deploy_contracts(click_runner, mock_primary_registry_filepath, mock_allocation_infile, token_economics): Agency.clear() # # Setup # # We start with a blockchain node, and nothing else... if os.path.isfile(mock_primary_registry_filepath): os.remove(mock_primary_registry_filepath) assert not os.path.isfile(mock_primary_registry_filepath) # # Main # command = [ 'contracts', '--registry-outfile', mock_primary_registry_filepath, '--provider-uri', TEST_PROVIDER_URI, '--poa' ] user_input = '0\n' + 'Y\n' + (f'{INSECURE_SECRETS[1]}\n' * 8) + 'DEPLOY' result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 # Ensure there is a report on each contract for registry_name in Deployer.contract_names: assert registry_name in result.output # Check that the primary contract registry was written # and peek at some of the registered entries assert os.path.isfile(mock_primary_registry_filepath) with open(mock_primary_registry_filepath, 'r') as file: # Ensure every contract's name was written to the file, somehow raw_registry_data = file.read() for registry_name in Deployer.contract_names: assert registry_name in raw_registry_data # Ensure the Registry is JSON deserializable registry_data = json.loads(raw_registry_data) # and that is has the correct number of entries assert len(registry_data) == 9 # Read several records token_record, escrow_record, dispatcher_record, *other_records = registry_data registered_name, registered_address, registered_abi = token_record # # Agency # token_agent = NucypherTokenAgent() assert token_agent.contract_name == registered_name assert token_agent.registry_contract_name == registered_name assert token_agent.contract_address == registered_address # Now show that we can use contract Agency and read from the blockchain assert token_agent.get_balance() == 0 staking_agent = StakingEscrowAgent() assert staking_agent.get_current_period() # and at least the others can be instantiated assert PolicyAgent()