예제 #1
0
파일: actors.py 프로젝트: vepkenez/nucypher
 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
예제 #2
0
파일: actors.py 프로젝트: vepkenez/nucypher
    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()
예제 #3
0
파일: actors.py 프로젝트: vepkenez/nucypher
    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()
예제 #4
0
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)
예제 #5
0
 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(
     )
예제 #6
0
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
예제 #7
0
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
예제 #9
0
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
예제 #10
0
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
예제 #11
0
 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)
예제 #12
0
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)
예제 #13
0
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! *********")
예제 #14
0
 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")
예제 #15
0
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! *********")
예제 #16
0
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)
예제 #17
0
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! *********")
예제 #18
0
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! *********")