def collect_policy_reward(self, collector_address=None, policy_agent: PolicyManagerAgent = None): """Collect rewarded ETH""" policy_agent = policy_agent or PolicyManagerAgent( blockchain=self.blockchain) withdraw_address = collector_address or self.checksum_address receipt = policy_agent.collect_policy_reward( collector_address=withdraw_address, staker_address=self.checksum_address) return receipt
def __init__(self, checksum_address: str, policy_agent: PolicyManagerAgent = None, economics: TokenEconomics = None, *args, **kwargs) -> None: """ :param policy_agent: A policy agent with the blockchain attached; If not passed, a default policy agent and blockchain connection will be created from default values. """ super().__init__(checksum_address=checksum_address, *args, **kwargs) # From defaults if not policy_agent: self.token_agent = NucypherTokenAgent(blockchain=self.blockchain) self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain) self.policy_agent = PolicyManagerAgent(blockchain=self.blockchain) # Injected else: self.policy_agent = policy_agent self.economics = economics or TokenEconomics()
def __init__(self, blockchain: BlockchainDeployerInterface, deployer_address: str = None, client_password: str = None, bare: bool = True) -> None: self.log = Logger("Deployment-Actor") self.blockchain = blockchain self.__deployer_address = NO_DEPLOYER_ADDRESS self.deployer_address = deployer_address self.checksum_address = self.deployer_address if not bare: self.token_agent = NucypherTokenAgent(blockchain=blockchain) self.staking_agent = StakingEscrowAgent(blockchain=blockchain) self.policy_agent = PolicyManagerAgent(blockchain=blockchain) self.adjudicator_agent = AdjudicatorAgent(blockchain=blockchain) self.user_escrow_deployers = dict() self.deployers = {d.contract_name: d for d in self.deployer_classes} self.transacting_power = TransactingPower(blockchain=blockchain, password=client_password, account=deployer_address) self.transacting_power.activate()
def paint_contract_status(blockchain, emitter): token_agent = NucypherTokenAgent(blockchain=blockchain) staking_agent = StakingEscrowAgent(blockchain=blockchain) policy_agent = PolicyManagerAgent(blockchain=blockchain) adjudicator_agent = AdjudicatorAgent(blockchain=blockchain) contract_payload = f""" | NuCypher Contracts | Chain .................... {blockchain.client.chain_name} Provider URI ............. {blockchain.provider_uri} Registry Path ............ {blockchain.registry.filepath} NucypherToken ............ {token_agent.contract_address} StakingEscrow ............ {staking_agent.contract_address} PolicyManager ............ {policy_agent.contract_address} Adjudicator .............. {adjudicator_agent.contract_address} """ network_payload = f""" | Staking | Current Period ........... {staking_agent.get_current_period()} Actively Staked Tokens ... {NU.from_nunits(staking_agent.get_global_locked_tokens())} Published Stakes ......... {staking_agent.get_staker_population()} Gas Price ................ {Web3.fromWei(blockchain.client.gas_price, 'gwei')} Gwei """ emitter.echo(contract_payload) emitter.echo(network_payload)
def __init__(self, allocation_registry: AllocationRegistry = None, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.token_agent = NucypherTokenAgent(blockchain=self.blockchain) self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain) self.policy_agent = PolicyManagerAgent(blockchain=self.blockchain) self.__beneficiary_address = NO_BENEFICIARY self.__allocation_registry = allocation_registry or self.__allocation_registry( )
def test_make_agent(policy_manager_deployer, test_registry): # Create a PolicyManagerAgent policy_agent = policy_manager_deployer.make_agent() # Retrieve the PolicyManagerAgent singleton some_policy_agent = PolicyManagerAgent(registry=test_registry) assert policy_agent == some_policy_agent # __eq__ # Compare the contract address for equality assert policy_agent.contract_address == some_policy_agent.contract_address
def test_policy_manager_has_dispatcher(policy_manager_deployer, testerchain, test_registry): # Let's get the "bare" PolicyManager contract (i.e., unwrapped, no dispatcher) existing_bare_contract = testerchain.get_contract_by_name(registry=test_registry, contract_name=policy_manager_deployer.contract_name, proxy_name=DispatcherDeployer.contract_name, use_proxy_address=False) # This contract shouldn't be accessible directly through the deployer or the agent assert policy_manager_deployer.contract_address != existing_bare_contract.address policy_manager_agent = PolicyManagerAgent(registry=test_registry) assert policy_manager_agent.contract_address != existing_bare_contract # The wrapped contract, on the other hand, points to the bare one. target = policy_manager_deployer.contract.functions.target().call() assert target == existing_bare_contract.address
def test_rollback(testerchain, test_registry, transacting_power): deployer = PolicyManagerDeployer(registry=test_registry) policy_manager_agent = PolicyManagerAgent(registry=test_registry) current_target = policy_manager_agent.contract.functions.target().call() # Let's do one more upgrade receipts = deployer.upgrade(ignore_deployed=True, confirmations=0, transacting_power=transacting_power) for title, receipt in receipts.items(): assert receipt['status'] == 1 old_target = current_target current_target = policy_manager_agent.contract.functions.target().call() assert current_target != old_target # It's time to rollback. receipt = deployer.rollback(transacting_power=transacting_power) assert receipt['status'] == 1 new_target = policy_manager_agent.contract.functions.target().call() assert new_target != current_target assert new_target == old_target
def test_rollback(testerchain, test_registry): old_secret = bytes('new' + POLICY_MANAGER_DEPLOYMENT_SECRET, encoding='utf-8') new_secret_hash = keccak(text="third time's the charm") deployer = PolicyManagerDeployer( registry=test_registry, deployer_address=testerchain.etherbase_account) policy_manager_agent = PolicyManagerAgent(registry=test_registry) current_target = policy_manager_agent.contract.functions.target().call() # Let's do one more upgrade receipts = deployer.upgrade(existing_secret_plaintext=old_secret, new_secret_hash=new_secret_hash, ignore_deployed=True) for title, receipt in receipts.items(): assert receipt['status'] == 1 old_target = current_target current_target = policy_manager_agent.contract.functions.target().call() assert current_target != old_target # It's time to rollback. But first... wrong_secret = b"WRONG!!" with pytest.raises(deployer.ContractDeploymentError): deployer.rollback(existing_secret_plaintext=wrong_secret, new_secret_hash=new_secret_hash) # OK, *now* is time for rollback old_secret = b"third time's the charm" new_secret_hash = keccak(text="...maybe not.") receipt = deployer.rollback(existing_secret_plaintext=old_secret, new_secret_hash=new_secret_hash) assert receipt['status'] == 1 new_target = policy_manager_agent.contract.functions.target().call() assert new_target != current_target assert new_target == old_target
def test_rollback(testerchain, test_registry): deployer = PolicyManagerDeployer( registry=test_registry, deployer_address=testerchain.etherbase_account) policy_manager_agent = PolicyManagerAgent(registry=test_registry) current_target = policy_manager_agent.contract.functions.target().call() # Let's do one more upgrade receipts = deployer.upgrade(ignore_deployed=True) for title, receipt in receipts.items(): assert receipt['status'] == 1 old_target = current_target current_target = policy_manager_agent.contract.functions.target().call() assert current_target != old_target # It's time to rollback. receipt = deployer.rollback() assert receipt['status'] == 1 new_target = policy_manager_agent.contract.functions.target().call() assert new_target != current_target assert new_target == old_target
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.token_agent = NucypherTokenAgent(blockchain=self.blockchain) self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain) self.policy_agent = PolicyManagerAgent(blockchain=self.blockchain)
def test_nucypher_deploy_contracts(click_runner, token_economics, registry_filepath, testerchain): # # Main # assert not os.path.exists( registry_filepath), f"Registry File '{registry_filepath}' Exists." assert not os.path.lexists( registry_filepath), f"Registry File '{registry_filepath}' Exists." command = [ 'contracts', '--registry-outfile', registry_filepath, '--provider', TEST_PROVIDER_URI, '--se-test-mode' ] user_input = '0\n' + 'Y\n' + '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 primary contract contract_names = tuple( a.contract_name for a in ContractAdministrator.primary_deployer_classes) for registry_name in 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(registry_filepath) with open(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 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_version, registered_address, registered_abi = token_record # # Agency # registry = LocalContractRegistry(filepath=registry_filepath) token_agent = NucypherTokenAgent(registry=registry) assert token_agent.contract_name == registered_name assert token_agent.registry_contract_name == registered_name assert token_agent.contract_address == registered_address assert token_agent.contract.version == registered_version # Now show that we can use contract Agency and read from the blockchain assert token_agent.get_balance() == 0 staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) assert staking_agent.get_current_period() assert staking_agent.contract.functions.isTestContract().call() # and at least the others can be instantiated assert PolicyManagerAgent(registry=registry) assert AdjudicatorAgent(registry=registry)
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() # FIXME this value includes constructor code size but should not bin_runtime = compiled_contract[version]['evm']['bytecode']['object'] 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) # First deposit ever is the most expensive, make it to remove unusual gas spending transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact( staker_functions.deposit(everyone_else[0], MIN_ALLOWED_LOCKED, LOCKED_PERIODS), {'from': origin}) testerchain.time_travel(periods=1) # # 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}) # # 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, LOCKED_PERIODS), {'from': staker1}) transact_and_log( "Initial deposit tokens, other", staker_functions.deposit(staker2, MIN_ALLOWED_LOCKED * 3, LOCKED_PERIODS), {'from': staker2}) transact( staker_functions.deposit(staker3, MIN_ALLOWED_LOCKED * 3, 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 period 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, LOCKED_PERIODS), {'from': staker1}) transact( staker_functions.deposit(staker2, MIN_ALLOWED_LOCKED * 2, 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}) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.commitToNextPeriod(), {'from': staker2}) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) testerchain.time_travel(periods=1) # # Batch granting # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period value = 3 * number_of_periods * rate transact_and_log( "Creating 2 policies (3 nodes, 100 periods, pre-committed)", policy_functions.createPolicies([policy_id_1, policy_id_2], alice1, end_timestamp, [staker1, staker2, staker3]), { 'from': alice1, 'value': 2 * value }) for index in range(4): 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, 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(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, 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}) testerchain.time_travel(periods=1) for index in range(18): transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) transact( staker_functions.lockAndCreate(MIN_ALLOWED_LOCKED, 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}) 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, 0), {'from': origin}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * number_of_sub_stakes), {'from': origin}) for i in range(number_of_sub_stakes): transact( staker_functions.deposit(staker4, MIN_ALLOWED_LOCKED, LOCKED_PERIODS), {'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 period 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 period 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("********* Estimates of migration *********") registry = InMemoryContractRegistry() deployer_power = TransactingPower(signer=Web3Signer(testerchain.client), account=testerchain.etherbase_account) def deploy_contract(contract_name, *args, **kwargs): return testerchain.deploy_contract(deployer_power, registry, contract_name, *args, **kwargs) token_economics = StandardTokenEconomics( genesis_hours_per_period=StandardTokenEconomics. _default_hours_per_period, hours_per_period=2 * StandardTokenEconomics._default_hours_per_period) token, _ = deploy_contract( 'NuCypherToken', _totalSupplyOfTokens=token_economics.erc20_total_supply) # Deploy Adjudicator mock adjudicator, _ = deploy_contract('AdjudicatorForStakingEscrowMock', token_economics.reward_coefficient) # Deploy old StakingEscrow contract deploy_args = token_economics.staking_deployment_parameters deploy_args = (deploy_args[0], *deploy_args[2:]) escrow_old_library, _ = deploy_contract( 'StakingEscrowOld', token.address, *deploy_args, False # testContract ) escrow_dispatcher, _ = deploy_contract('Dispatcher', escrow_old_library.address) escrow = testerchain.client.get_contract(abi=escrow_old_library.abi, address=escrow_dispatcher.address, ContractFactoryClass=Contract) # Deploy old PolicyManager contract policy_manager_old_library, _ = deploy_contract( contract_name='PolicyManagerOld', _escrow=escrow.address) policy_manager_dispatcher, _ = deploy_contract( 'Dispatcher', policy_manager_old_library.address) policy_manager = testerchain.client.get_contract( abi=policy_manager_old_library.abi, address=policy_manager_dispatcher.address, ContractFactoryClass=Contract) tx = adjudicator.functions.setStakingEscrow(escrow.address).transact() testerchain.wait_for_receipt(tx) tx = escrow.functions.setPolicyManager(policy_manager.address).transact() testerchain.wait_for_receipt(tx) tx = escrow.functions.setAdjudicator(adjudicator.address).transact() testerchain.wait_for_receipt(tx) # Initialize Escrow contract tx = token.functions.approve( escrow.address, token_economics.erc20_reward_supply).transact() testerchain.wait_for_receipt(tx) tx = escrow.functions.initialize(token_economics.erc20_reward_supply, testerchain.etherbase_account).transact() testerchain.wait_for_receipt(tx) # Prepare stakers stakers = (staker1, staker2, staker3, staker4) for staker in stakers: max_stake_size = token_economics.maximum_allowed_locked tx = token.functions.transfer(staker, max_stake_size).transact() testerchain.wait_for_receipt(tx) tx = token.functions.approve(escrow.address, max_stake_size).transact({'from': staker}) testerchain.wait_for_receipt(tx) sub_stakes_1 = 2 duration = token_economics.minimum_locked_periods stake_size = token_economics.minimum_allowed_locked for staker in (staker1, staker3): for i in range(1, sub_stakes_1 + 1): tx = escrow.functions.deposit(staker, stake_size, duration * i).transact({'from': staker}) testerchain.wait_for_receipt(tx) sub_stakes_2 = 24 for staker in (staker2, staker4): for i in range(1, sub_stakes_2 + 1): tx = escrow.functions.deposit(staker, stake_size, duration * i).transact({'from': staker}) testerchain.wait_for_receipt(tx) for staker in stakers: tx = escrow.functions.bondWorker(staker).transact({'from': staker}) testerchain.wait_for_receipt(tx) for i in range(duration): tx = escrow.functions.commitToNextPeriod().transact({'from': staker1}) testerchain.wait_for_receipt(tx) tx = escrow.functions.commitToNextPeriod().transact({'from': staker3}) testerchain.wait_for_receipt(tx) if i % 2 == 0: tx = escrow.functions.commitToNextPeriod().transact( {'from': staker2}) testerchain.wait_for_receipt(tx) tx = escrow.functions.commitToNextPeriod().transact( {'from': staker4}) testerchain.wait_for_receipt(tx) testerchain.time_travel( periods=1, periods_base=token_economics.genesis_seconds_per_period) ########## # Deploy new version of contracts ########## deploy_args = token_economics.staking_deployment_parameters escrow_library, _ = deploy_contract('StakingEscrow', token.address, policy_manager.address, adjudicator.address, NULL_ADDRESS, *deploy_args) escrow = testerchain.client.get_contract(abi=escrow_library.abi, address=escrow_dispatcher.address, ContractFactoryClass=Contract) policy_manager_library, _ = deploy_contract( contract_name='PolicyManager', _escrowDispatcher=escrow.address, _escrowImplementation=escrow_library.address) tx = escrow_dispatcher.functions.upgrade(escrow_library.address).transact() testerchain.wait_for_receipt(tx) tx = policy_manager_dispatcher.functions.upgrade( policy_manager_library.address).transact() testerchain.wait_for_receipt(tx) for staker in (staker1, staker2): downtime_length = escrow.functions.getPastDowntimeLength(staker).call() sub_stakes_length = escrow.functions.getSubStakesLength(staker).call() transact_and_log( f"Migrate with {sub_stakes_length} sub-stakes and {downtime_length} downtimes", escrow.functions.migrate(staker), {'from': staker}) downtime_length = escrow.functions.getPastDowntimeLength(staker).call() sub_stakes_length = escrow.functions.getSubStakesLength(staker).call() transact_and_log( f"Commit after migration with {sub_stakes_length} sub-stakes and {downtime_length} downtimes", escrow.functions.commitToNextPeriod(), {'from': staker}) for staker in (staker3, staker4): downtime_length = escrow.functions.getPastDowntimeLength(staker).call() sub_stakes_length = escrow.functions.getSubStakesLength(staker).call() transact_and_log( f"Commit together with migration with {sub_stakes_length} sub-stakes and {downtime_length} downtimes", escrow.functions.commitToNextPeriod(), {'from': staker}) transact_and_log(f"Dummy migrate call", escrow.functions.migrate(staker1), {'from': staker1}) print("********* All Done! *********")
def acquire_agency(self) -> None: self.token_agent = NucypherTokenAgent(blockchain=self.blockchain) self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain) self.policy_agent = PolicyManagerAgent(blockchain=self.blockchain) self.log.debug("Established connection to nucypher contracts")
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) # Blockchain testerchain = TesterBlockchain.bootstrap_network() web3 = testerchain.w3 # Accounts origin, ursula1, ursula2, ursula3, alice1, *everyone_else = testerchain.client.accounts ursula_with_stamp = mock_ursula(testerchain, ursula1) # Contracts token_agent = NucypherTokenAgent(blockchain=testerchain) staking_agent = StakingEscrowAgent(blockchain=testerchain) policy_agent = PolicyManagerAgent(blockchain=testerchain) adjudicator_agent = AdjudicatorAgent(blockchain=testerchain) # 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 *********") # # Give Ursula and Alice some coins # log.info("Transfer tokens = " + str( token_functions.transfer(ursula1, MIN_ALLOWED_LOCKED * 10).estimateGas({'from': origin}))) tx = token_functions.transfer(ursula1, MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) tx = token_functions.transfer(ursula2, MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) tx = token_functions.transfer(ursula3, MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) # # Ursula and Alice give Escrow rights to transfer # log.info("Approving transfer = " + str( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6).estimateGas({'from': ursula1}))) tx = token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Ursula and Alice transfer some tokens to the escrow and lock them # log.info("First initial deposit tokens = " + str(staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second initial deposit tokens = " + str(staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third initial deposit tokens = " + str(staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) tx = staker_functions.setWorker(ursula1).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.setWorker(ursula2).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.setWorker(ursula3).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Wait 1 period and confirm activity # testerchain.time_travel(periods=1) log.info("First confirm activity = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula1}))) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second confirm activity = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula2}))) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third confirm activity = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula3}))) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) log.info("First mining (1 stake) = " + str(staker_functions.mint().estimateGas({'from': ursula1}))) tx = staker_functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second mining (1 stake) = " + str(staker_functions.mint().estimateGas({'from': ursula2}))) tx = staker_functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third/last mining (1 stake) = " + str(staker_functions.mint().estimateGas({'from': ursula3}))) tx = staker_functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) log.info("First confirm activity again = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula1}))) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second confirm activity again = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula2}))) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third confirm activity again = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula3}))) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Confirm again # testerchain.time_travel(periods=1) log.info("First confirm activity + mint = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula1}))) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second confirm activity + mint = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula2}))) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third confirm activity + mint = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula3}))) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Get locked tokens # log.info("Getting locked tokens = " + str(staker_functions.getLockedTokens(ursula1).estimateGas())) # # Wait 1 period and withdraw tokens # testerchain.time_travel(periods=1) log.info("First withdraw = " + str(staker_functions.withdraw(1).estimateGas({'from': ursula1}))) tx = staker_functions.withdraw(1).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second withdraw = " + str(staker_functions.withdraw(1).estimateGas({'from': ursula2}))) tx = staker_functions.withdraw(1).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third withdraw = " + str(staker_functions.withdraw(1).estimateGas({'from': ursula3}))) tx = staker_functions.withdraw(1).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Confirm activity with re-stake # tx = staker_functions.setReStake(True).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.setReStake(True).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.setReStake(True).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) log.info("First confirm activity + mint with re-stake = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula1}))) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second confirm activity + mint with re-stake = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula2}))) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third confirm activity + mint with re-stake = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula3}))) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) tx = staker_functions.setReStake(False).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.setReStake(False).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.setReStake(False).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Wait 2 periods and confirm activity after downtime # testerchain.time_travel(periods=2) log.info("First confirm activity after downtime = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula1}))) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second confirm activity after downtime = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula2}))) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third confirm activity after downtime = " + str(staker_functions.confirmActivity().estimateGas({'from': ursula3}))) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Ursula and Alice deposit some tokens to the escrow again # log.info("First deposit tokens again = " + str(staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second deposit tokens again = " + str(staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third deposit tokens again = " + str(staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) log.info("First mining again = " + str(staker_functions.mint().estimateGas({'from': ursula1}))) tx = staker_functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second mining again = " + str(staker_functions.mint().estimateGas({'from': ursula2}))) tx = staker_functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third/last mining again = " + str(staker_functions.mint().estimateGas({'from': ursula3}))) tx = staker_functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # 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 log.info("First creating policy (1 node, 10 periods) = " + str(policy_functions.createPolicy(policy_id_1, number_of_periods, 0, [ursula1]).estimateGas( {'from': alice1, 'value': 10000}))) tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 0, [ursula1]).transact( {'from': alice1, 'value': 10000}) testerchain.wait_for_receipt(tx) log.info("Second creating policy (1 node, 10 periods) = " + str(policy_functions.createPolicy(policy_id_2, number_of_periods, 0, [ursula1]).estimateGas( {'from': alice1, 'value': 10000}))) tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 0, [ursula1]).transact( {'from': alice1, 'value': 10000}) testerchain.wait_for_receipt(tx) # # Revoke policy # log.info("Revoking policy = " + str(policy_functions.revokePolicy(policy_id_1).estimateGas({'from': alice1}))) tx = policy_functions.revokePolicy(policy_id_1).transact({'from': alice1}) testerchain.wait_for_receipt(tx) tx = policy_functions.revokePolicy(policy_id_2).transact({'from': alice1}) testerchain.wait_for_receipt(tx) # # Create policy with more periods # 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 log.info("First creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str(policy_functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula2]).estimateGas( {'from': alice1, 'value': 10050}))) tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula2]).transact( {'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) log.info("Second creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str(policy_functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula2]).estimateGas( {'from': alice1, 'value': 10050}))) tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula2]).transact( {'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) log.info("Third creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str(policy_functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1]).estimateGas( {'from': alice1, 'value': 10050}))) tx = policy_functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1]).transact( {'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) # # Mine and revoke policy # testerchain.time_travel(periods=10) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) log.info("First mining after downtime = " + str(staker_functions.mint().estimateGas({'from': ursula1}))) tx = staker_functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second mining after downtime = " + str(staker_functions.mint().estimateGas({'from': ursula2}))) tx = staker_functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=10) log.info("First revoking policy after downtime = " + str(policy_functions.revokePolicy(policy_id_1).estimateGas({'from': alice1}))) tx = policy_functions.revokePolicy(policy_id_1).transact({'from': alice1}) testerchain.wait_for_receipt(tx) log.info("Second revoking policy after downtime = " + str(policy_functions.revokePolicy(policy_id_2).estimateGas({'from': alice1}))) tx = policy_functions.revokePolicy(policy_id_2).transact({'from': alice1}) testerchain.wait_for_receipt(tx) log.info("Second revoking policy after downtime = " + str(policy_functions.revokePolicy(policy_id_3).estimateGas({'from': alice1}))) tx = policy_functions.revokePolicy(policy_id_3).transact({'from': alice1}) testerchain.wait_for_receipt(tx) # # Create policy with multiple 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 log.info("First creating policy (3 nodes, 100 periods, first reward) = " + str(policy_functions .createPolicy(policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3]) .estimateGas({'from': alice1, 'value': 30150}))) tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3]).transact( {'from': alice1, 'value': 30150}) testerchain.wait_for_receipt(tx) log.info("Second creating policy (3 nodes, 100 periods, first reward) = " + str(policy_functions .createPolicy(policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3]) .estimateGas({'from': alice1, 'value': 30150}))) tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3]).transact( {'from': alice1, 'value': 30150}) testerchain.wait_for_receipt(tx) log.info("Third creating policy (2 nodes, 100 periods, first reward) = " + str(policy_functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1, ursula2]).estimateGas( {'from': alice1, 'value': 20100}))) tx = policy_functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1, ursula2]).transact( {'from': alice1, 'value': 20100}) testerchain.wait_for_receipt(tx) for index in range(5): tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) tx = staker_functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Check regular deposit # log.info("First deposit tokens = " + str( staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second deposit tokens = " + str( staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third deposit tokens = " + str( staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3}))) tx = staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # ApproveAndCall # testerchain.time_travel(periods=1) tx = staker_functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) log.info("First approveAndCall = " + str(token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second approveAndCall = " + str(token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third approveAndCall = " + str(token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Locking tokens # testerchain.time_travel(periods=1) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = staker_functions.confirmActivity().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) log.info("First locking tokens = " + str(staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1}))) tx = staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second locking tokens = " + str(staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2}))) tx = staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) log.info("Third locking tokens = " + str(staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3}))) tx = staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # # Divide stake # log.info("First divide stake = " + str( staker_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1}))) tx = staker_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Second divide stake = " + str( staker_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1}))) tx = staker_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) # # Divide almost finished stake # testerchain.time_travel(periods=1) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) log.info("Divide stake (next period is not confirmed) = " + str( staker_functions.divideStake(0, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1}))) tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) log.info("Divide stake (next period is confirmed) = " + str( staker_functions.divideStake(0, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1}))) # # Slashing tests # tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) # # Slashing # slashing_args = generate_args_for_slashing(ursula_with_stamp) log.info("Slash just value = " + str( adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) deposit = staker_functions.stakerInfo(ursula1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(ursula1).call() tx = staker_functions.withdraw(unlocked).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) log.info("First slashing one sub stake and saving old one (" + sub_stakes_length + " sub stakes) = " + str(adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) log.info("Second slashing one sub stake and saving old one (" + sub_stakes_length + " sub stakes) = " + str(adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) log.info("Third slashing one sub stake and saving old one (" + sub_stakes_length + " sub stakes) = " + str(adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) log.info("Slashing two sub stakes and saving old one (" + sub_stakes_length + " sub stakes) = " + str(adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) for index in range(18): tx = staker_functions.confirmActivity().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) tx = staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) deposit = staker_functions.stakerInfo(ursula1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(ursula1, 1).call() tx = staker_functions.withdraw(unlocked).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) log.info("Slashing two sub stakes, shortest and new one (" + sub_stakes_length + " sub stakes) = " + str(adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).call()) slashing_args = generate_args_for_slashing(ursula_with_stamp) log.info("Slashing three sub stakes, two shortest and new one (" + sub_stakes_length + " sub stakes) = " + str(adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) slashing_args = generate_args_for_slashing(ursula_with_stamp, corrupt_cfrag=False) log.info("Evaluating correct CFrag = " + str(adjudicator_functions.evaluateCFrag(*slashing_args).estimateGas({'from': alice1}))) tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) testerchain.wait_for_receipt(tx) print("********* All Done! *********")
def test_nucypher_deploy_contracts(click_runner, mock_allocation_infile, token_economics, registry_filepath): # # Main # command = [ 'contracts', '--registry-outfile', registry_filepath, '--provider', 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 contract_names = tuple(a.registry_contract_name for a in EthereumContractAgent.__subclasses__()) for registry_name in 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(registry_filepath) with open(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 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 # registry = LocalContractRegistry(filepath=registry_filepath) token_agent = NucypherTokenAgent(registry=registry) 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 = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) assert staking_agent.get_current_period() # and at least the others can be instantiated assert PolicyManagerAgent(registry=registry) # This agent wasn't instantiated before, so we have to supply the blockchain blockchain = staking_agent.blockchain assert AdjudicatorAgent(registry=registry)
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 # Accounts origin, ursula1, ursula2, ursula3, alice1, alice2, *everyone_else = testerchain.client.accounts ursula_with_stamp = mock_ursula(testerchain, ursula1) # 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(ursula1, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(ursula2, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(ursula3, 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 * 6), {'from': ursula1}) transact(token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': ursula2}) transact(token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': ursula3}) # # Ursula and Alice transfer some tokens to the escrow and lock them # transact_and_log("Initial deposit tokens, 1st", staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': ursula1}) transact_and_log("Initial deposit tokens, 2nd", staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': ursula2}) transact(staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': ursula3}) transact(staker_functions.setWorker(ursula1), {'from': ursula1}) transact(staker_functions.setWorker(ursula2), {'from': ursula2}) transact(staker_functions.setWorker(ursula3), {'from': ursula3}) transact(staker_functions.setReStake(False), {'from': ursula1}) transact(staker_functions.setReStake(False), {'from': ursula2}) transact(staker_functions.confirmActivity(), {'from': ursula1}) transact(staker_functions.confirmActivity(), {'from': ursula2}) # # Wait 1 period and confirm activity # testerchain.time_travel(periods=1) transact_and_log("Confirm activity, 1st", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity, 2nd", staker_functions.confirmActivity(), {'from': ursula2}) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact_and_log("Mining (1 stake), 1st", staker_functions.mint(), {'from': ursula1}) transact_and_log("Mining (1 stake), 2nd", staker_functions.mint(), {'from': ursula2}) transact_and_log("Confirm activity again, 1st", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity again, 2nd", staker_functions.confirmActivity(), {'from': ursula2}) # # Confirm again # testerchain.time_travel(periods=1) transact_and_log("Confirm activity + mint, 1st", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity + mint, 2nd", staker_functions.confirmActivity(), {'from': ursula2}) # # Get locked tokens # transact_and_log("Getting locked tokens", staker_functions.getLockedTokens(ursula1, 0), {}) # # Wait 1 period and withdraw tokens # testerchain.time_travel(periods=1) transact_and_log("Withdraw", staker_functions.withdraw(1), {'from': ursula1}) # # Confirm activity with re-stake # transact(staker_functions.setReStake(True), {'from': ursula1}) transact(staker_functions.setReStake(True), {'from': ursula2}) transact_and_log("Confirm activity + mint with re-stake, 1st", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity + mint with re-stake, 2nd", staker_functions.confirmActivity(), {'from': ursula2}) transact(staker_functions.setReStake(False), {'from': ursula1}) transact(staker_functions.setReStake(False), {'from': ursula2}) # # Wait 1 period # testerchain.time_travel(periods=1) # # 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(block_identifier='latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log("Creating policy (1 node, 10 periods, pre-confirmed), 1st", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [ursula1]), {'from': alice1, 'value': value}) transact_and_log("Creating policy (1 node, 10 periods, pre-confirmed), 2nd", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [ursula1]), {'from': alice1, 'value': value}) # # Wait 2 periods and confirm activity after downtime # testerchain.time_travel(periods=1) transact_and_log("Confirm activity after downtime, 1st", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity after downtime, 2nd", staker_functions.confirmActivity(), {'from': ursula2}) transact(staker_functions.confirmActivity(), {'from': ursula3}) # # Ursula and Alice deposit some tokens to the escrow again # transact_and_log("Deposit tokens after confirming activity", staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS), {'from': ursula1}) transact(staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS), {'from': ursula2}) # # 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-confirmed 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(block_identifier='latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log("Creating policy (3 nodes, 100 periods, pre-confirmed), 1st", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [ursula1, ursula2, ursula3]), {'from': alice1, 'value': value}) transact_and_log("Creating policy (3 nodes, 100 periods, pre-confirmed), 2nd", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [ursula1, ursula2, ursula3]), {'from': alice1, 'value': value}) value = 2 * number_of_periods * rate transact_and_log("Creating policy (2 nodes, 100 periods, pre-confirmed), 3rd", policy_functions.createPolicy(policy_id_3, alice1, end_timestamp, [ursula1, ursula2]), {'from': alice1, 'value': value}) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact_and_log("Mining with updating reward, 1st", staker_functions.mint(), {'from': ursula1}) transact_and_log("Mining with updating reward, 2nd", staker_functions.mint(), {'from': ursula2}) # # Create policy again without pre-confirmed 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(block_identifier='latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log("Creating policy (1 node, 100 periods), 1st", policy_functions.createPolicy(policy_id_1, alice2, end_timestamp, [ursula2]), {'from': alice1, 'value': value}) testerchain.time_travel(periods=1) current_timestamp = testerchain.w3.eth.getBlock(block_identifier='latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log("Creating policy (1 node, 100 periods), 2nd", policy_functions.createPolicy(policy_id_2, alice2, end_timestamp, [ursula2]), {'from': alice1, 'value': value}) transact_and_log("Creating policy (1 node, 100 periods), 3rd", policy_functions.createPolicy(policy_id_3, alice2, end_timestamp, [ursula1]), {'from': alice1, 'value': value}) # # Mine and revoke policy # testerchain.time_travel(periods=10) transact(staker_functions.confirmActivity(), {'from': ursula1}) testerchain.time_travel(periods=2) transact_and_log("Mining after downtime", staker_functions.mint(), {'from': ursula1}) testerchain.time_travel(periods=10) transact_and_log("Revoking policy after downtime, 1st", policy_functions.revokePolicy(policy_id_1), {'from': alice2}) transact_and_log("Revoking policy after downtime, 2nd", policy_functions.revokePolicy(policy_id_2), {'from': alice2}) transact_and_log("Revoking policy after downtime, 3rd", policy_functions.revokePolicy(policy_id_3), {'from': alice2}) for index in range(5): transact(staker_functions.confirmActivity(), {'from': ursula1}) testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': ursula1}) # # Check regular deposit # transact_and_log("Deposit tokens", staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': ursula1}) # # ApproveAndCall # testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': ursula1}) transact_and_log("ApproveAndCall", token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)), {'from': ursula1}) # # Locking tokens # testerchain.time_travel(periods=1) transact(staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Locking tokens", staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': ursula1}) # # Divide stake # transact_and_log("Divide stake", staker_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2), {'from': ursula1}) transact(staker_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2), {'from': ursula1}) # # Divide almost finished stake # testerchain.time_travel(periods=1) transact(staker_functions.confirmActivity(), {'from': ursula1}) testerchain.time_travel(periods=1) transact(staker_functions.confirmActivity(), {'from': ursula1}) # # Slashing tests # transact(staker_functions.confirmActivity(), {'from': ursula1}) 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(ursula1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(ursula1, 0).call() transact(staker_functions.withdraw(unlocked), {'from': ursula1}) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).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(ursula1).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(ursula1).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(ursula1).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.confirmActivity(), {'from': ursula1}) testerchain.time_travel(periods=1) transact(staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': ursula1}) deposit = staker_functions.stakerInfo(ursula1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(ursula1, 1).call() transact(staker_functions.withdraw(unlocked), {'from': ursula1}) sub_stakes_length = str(staker_functions.getSubStakesLength(ursula1).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(ursula1).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': ursula1}) print("********* All Done! *********")
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, ursula1, ursula2, ursula3, alice1, alice2, *everyone_else = testerchain.client.accounts ursula_with_stamp = mock_ursula(testerchain, ursula1) # 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(ursula1, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(ursula2, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(ursula3, 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 * 6), {'from': ursula1}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': ursula2}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': ursula3}) # # Batch deposit tokens # 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}) # # Ursula and Alice transfer some tokens to the escrow and lock them # transact_and_log( "Initial deposit tokens, first", staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': ursula1}) transact_and_log( "Initial deposit tokens, other", staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': ursula2}) transact( staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS), {'from': ursula3}) transact(staker_functions.setWorker(ursula1), {'from': ursula1}) transact(staker_functions.setWorker(ursula2), {'from': ursula2}) transact(staker_functions.setWorker(ursula3), {'from': ursula3}) transact(staker_functions.setReStake(False), {'from': ursula1}) transact(staker_functions.setReStake(False), {'from': ursula2}) transact(staker_functions.setWindDown(True), {'from': ursula1}) transact(staker_functions.setWindDown(True), {'from': ursula2}) transact(staker_functions.confirmActivity(), {'from': ursula1}) transact(staker_functions.confirmActivity(), {'from': ursula2}) # # Wait 1 period and confirm activity # testerchain.time_travel(periods=1) transact_and_log("Confirm activity, first", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity, other", staker_functions.confirmActivity(), {'from': ursula2}) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact_and_log("Mining (1 stake), first", staker_functions.mint(), {'from': ursula1}) transact_and_log("Mining (1 stake), other", staker_functions.mint(), {'from': ursula2}) transact_and_log("Confirm activity again, first", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity again, other", staker_functions.confirmActivity(), {'from': ursula2}) transact(staker_functions.confirmActivity(), {'from': ursula3}) # # Confirm again # testerchain.time_travel(periods=1) transact_and_log("Confirm activity + mint, first", staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log("Confirm activity + mint, other", staker_functions.confirmActivity(), {'from': ursula2}) # # 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( block_identifier='latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (1 node, 10 periods, pre-confirmed), first", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [ursula1]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (1 node, 10 periods, pre-confirmed), other", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [ursula1]), { 'from': alice1, 'value': value }) # # Get locked tokens # transact_and_log("Getting locked tokens", staker_functions.getLockedTokens(ursula1, 0), {}) # # Wait 1 period and withdraw tokens # testerchain.time_travel(periods=1) transact_and_log("Withdraw", staker_functions.withdraw(1), {'from': ursula1}) # # Confirm activity with re-stake # transact(staker_functions.setReStake(True), {'from': ursula1}) transact(staker_functions.setReStake(True), {'from': ursula2}) # Used to remove spending for first call in a day for mint and confirmActivity transact(staker_functions.confirmActivity(), {'from': ursula3}) transact_and_log("Confirm activity + mint + re-stake", staker_functions.confirmActivity(), {'from': ursula2}) transact_and_log( "Confirm activity + mint + re-stake + first reward + first reward rate", staker_functions.confirmActivity(), {'from': ursula1}) transact(staker_functions.setReStake(False), {'from': ursula1}) transact(staker_functions.setReStake(False), {'from': ursula2}) # # Wait 2 periods and confirm activity after downtime # testerchain.time_travel(periods=2) transact(staker_functions.confirmActivity(), {'from': ursula3}) transact_and_log("Confirm activity after downtime", staker_functions.confirmActivity(), {'from': ursula2}) transact_and_log("Confirm activity after downtime + updating reward", staker_functions.confirmActivity(), {'from': ursula1}) # # Ursula and Alice deposit some tokens to the escrow again # transact_and_log( "Deposit tokens after confirming activity", staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS), {'from': ursula1}) transact( staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS), {'from': ursula2}) # # 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-confirmed 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( block_identifier='latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (3 nodes, 100 periods, pre-confirmed), first", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [ursula1, ursula2, ursula3]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (3 nodes, 100 periods, pre-confirmed), other", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [ursula1, ursula2, ursula3]), { 'from': alice1, 'value': value }) value = 2 * number_of_periods * rate transact_and_log( "Creating policy (2 nodes, 100 periods, pre-confirmed), other", policy_functions.createPolicy(policy_id_3, alice1, end_timestamp, [ursula1, ursula2]), { 'from': alice1, 'value': value }) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': ursula3}) transact_and_log("Last mining + updating reward + updating reward rate", staker_functions.mint(), {'from': ursula1}) transact_and_log("Last mining + first reward + first reward rate", staker_functions.mint(), {'from': ursula2}) # # Create policy again without pre-confirmed 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( block_identifier='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, [ursula2]), { 'from': alice1, 'value': value }) testerchain.time_travel(periods=1) current_timestamp = testerchain.w3.eth.getBlock( block_identifier='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, [ursula2]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (1 node, 100 periods), another node", policy_functions.createPolicy(policy_id_3, alice2, end_timestamp, [ursula1]), { 'from': alice1, 'value': value }) # # Mine and revoke policy # testerchain.time_travel(periods=10) transact(staker_functions.confirmActivity(), {'from': ursula1}) transact(staker_functions.confirmActivity(), {'from': ursula3}) testerchain.time_travel(periods=2) transact(staker_functions.mint(), {'from': ursula3}) transact_and_log("Last mining after downtime + updating reward", staker_functions.mint(), {'from': ursula1}) 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.confirmActivity(), {'from': ursula1}) testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': ursula1}) # # Check regular deposit # transact_and_log( "Deposit tokens", staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': ursula1}) # # ApproveAndCall # testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': ursula1}) transact_and_log( "ApproveAndCall", token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(MIN_LOCKED_PERIODS)), {'from': ursula1}) # # Locking tokens # testerchain.time_travel(periods=1) transact(staker_functions.confirmActivity(), {'from': ursula1}) transact_and_log( "Locking tokens", staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': ursula1}) # # Divide stake # transact_and_log("Divide stake", staker_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2), {'from': ursula1}) transact(staker_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2), {'from': ursula1}) # # Divide almost finished stake # testerchain.time_travel(periods=1) transact(staker_functions.confirmActivity(), {'from': ursula1}) testerchain.time_travel(periods=1) transact(staker_functions.confirmActivity(), {'from': ursula1}) # # Slashing tests # transact(staker_functions.confirmActivity(), {'from': ursula1}) 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(ursula1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(ursula1, 0).call() transact(staker_functions.withdraw(unlocked), {'from': ursula1}) sub_stakes_length = str( staker_functions.getSubStakesLength(ursula1).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(ursula1).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(ursula1).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(ursula1).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.confirmActivity(), {'from': ursula1}) testerchain.time_travel(periods=1) transact(staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS), {'from': ursula1}) deposit = staker_functions.stakerInfo(ursula1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(ursula1, 1).call() transact(staker_functions.withdraw(unlocked), {'from': ursula1}) sub_stakes_length = str( staker_functions.getSubStakesLength(ursula1).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(ursula1).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': ursula1}) print("********* All Done! *********")