Beispiel #1
0
    def __init__(self,
                 blockchain: BlockchainInterface,
                 deployer_address: str = None,
                 client_password: str = None,
                 bare: bool = True) -> None:

        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 = PolicyAgent(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}

        blockchain.transacting_power = TransactingPower(
            blockchain=blockchain,
            account=deployer_address,
            password=client_password)
        blockchain.transacting_power.activate()
        self.log = Logger("Deployment-Actor")
Beispiel #2
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)
Beispiel #3
0
class Investigator(NucypherTokenActor):
    """
    Actor that reports incorrect CFrags to the Adjudicator contract.
    In most cases, Bob will act as investigator, but the actor is generic enough than
    anyone can report CFrags.
    """
    def __init__(self, checksum_address: str, *args, **kwargs) -> None:

        super().__init__(checksum_address=checksum_address, *args, **kwargs)

        self.adjudicator_agent = AdjudicatorAgent(blockchain=self.blockchain)

    @save_receipt
    def request_evaluation(self, evidence):
        receipt = self.adjudicator_agent.evaluate_cfrag(
            evidence=evidence, sender_address=self.checksum_address)
        return receipt

    def was_this_evidence_evaluated(self, evidence):
        return self.adjudicator_agent.was_this_evidence_evaluated(
            evidence=evidence)
Beispiel #4
0
def test_adjudicator_deployer(testerchain, token_economics,
                              deployment_progress, test_registry):
    testerchain = testerchain
    origin = testerchain.etherbase_account

    token_deployer = NucypherTokenDeployer(deployer_address=origin,
                                           registry=test_registry)
    token_deployer.deploy()

    stakers_escrow_secret = os.urandom(
        DispatcherDeployer.DISPATCHER_SECRET_LENGTH)
    staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin,
                                                    registry=test_registry)

    staking_escrow_deployer.deploy(secret_hash=keccak(stakers_escrow_secret))
    staking_agent = staking_escrow_deployer.make_agent()  # 2 Staker Escrow

    deployer = AdjudicatorDeployer(deployer_address=origin,
                                   registry=test_registry)
    deployment_receipts = deployer.deploy(secret_hash=os.urandom(
        DispatcherDeployer.DISPATCHER_SECRET_LENGTH),
                                          progress=deployment_progress)

    # deployment steps must match expected number of steps
    assert deployment_progress.num_steps == len(
        deployer.deployment_steps) == len(deployment_receipts) == 3

    for step in deployer.deployment_steps:
        assert deployment_receipts[step]['status'] == 1

    # Create an AdjudicatorAgent instance
    adjudicator_agent = deployer.make_agent()

    # Check default Adjudicator deployment parameters
    assert staking_escrow_deployer.deployer_address != staking_agent.contract_address
    assert adjudicator_agent.staking_escrow_contract == staking_agent.contract_address
    assert adjudicator_agent.hash_algorithm == token_economics.hash_algorithm
    assert adjudicator_agent.base_penalty == token_economics.base_penalty
    assert adjudicator_agent.penalty_history_coefficient == token_economics.penalty_history_coefficient
    assert adjudicator_agent.percentage_penalty_coefficient == token_economics.percentage_penalty_coefficient
    assert adjudicator_agent.reward_coefficient == token_economics.reward_coefficient

    # Retrieve the AdjudicatorAgent singleton
    some_policy_agent = AdjudicatorAgent(registry=test_registry)
    assert adjudicator_agent == some_policy_agent  # __eq__

    # Compare the contract address for equality
    assert adjudicator_agent.contract_address == some_policy_agent.contract_address
Beispiel #5
0
def test_adjudicator_deployer(testerchain, application_economics,
                              deployment_progress, test_registry):

    origin = testerchain.etherbase_account
    tpower = TransactingPower(account=origin,
                              signer=Web3Signer(testerchain.client))

    token_deployer = NucypherTokenDeployer(registry=test_registry)
    token_deployer.deploy(transacting_power=tpower)

    staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)

    staking_escrow_deployer.deploy(transacting_power=tpower)
    staking_agent = staking_escrow_deployer.make_agent()  # 2 Staker Escrow

    deployer = AdjudicatorDeployer(registry=test_registry)
    deployment_receipts = deployer.deploy(progress=deployment_progress,
                                          transacting_power=tpower)

    # deployment steps must match expected number of steps
    assert deployment_progress.num_steps == len(
        deployer.deployment_steps) == len(deployment_receipts) == 2

    for step in deployer.deployment_steps:
        assert deployment_receipts[step]['status'] == 1

    # Create an AdjudicatorAgent instance
    adjudicator_agent = deployer.make_agent()

    # Check default Adjudicator deployment parameters
    assert tpower.account != staking_agent.contract_address
    assert adjudicator_agent.staking_escrow_contract == staking_agent.contract_address
    assert adjudicator_agent.hash_algorithm == application_economics.hash_algorithm
    assert adjudicator_agent.base_penalty == application_economics.base_penalty
    assert adjudicator_agent.penalty_history_coefficient == application_economics.penalty_history_coefficient
    assert adjudicator_agent.percentage_penalty_coefficient == application_economics.percentage_penalty_coefficient
    assert adjudicator_agent.reward_coefficient == application_economics.reward_coefficient

    # Retrieve the AdjudicatorAgent singleton
    some_policy_agent = AdjudicatorAgent(registry=test_registry)
    assert adjudicator_agent == some_policy_agent  # __eq__

    # Compare the contract address for equality
    assert adjudicator_agent.contract_address == some_policy_agent.contract_address
Beispiel #6
0
def test_adjudicator_deployer(testerchain, slashing_economics):
    origin = testerchain.etherbase_account

    token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin)
    token_deployer.deploy()

    stakers_escrow_secret = os.urandom(DispatcherDeployer.DISPATCHER_SECRET_LENGTH)
    staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin, blockchain=testerchain)

    staking_escrow_deployer.deploy(secret_hash=keccak(stakers_escrow_secret))
    staking_agent = staking_escrow_deployer.make_agent()  # 2 Staker Escrow

    deployer = AdjudicatorDeployer(deployer_address=origin, blockchain=testerchain)
    deployment_txhashes = deployer.deploy(secret_hash=os.urandom(DispatcherDeployer.DISPATCHER_SECRET_LENGTH))

    assert len(deployment_txhashes) == 3

    for title, txhash in deployment_txhashes.items():
        receipt = testerchain.wait_for_receipt(txhash=txhash)
        assert receipt['status'] == 1, "Transaction Rejected {}:{}".format(title, txhash)

    # Create an AdjudicatorAgent instance
    adjudicator_agent = deployer.make_agent()

    # Check default Adjudicator deployment parameters
    assert adjudicator_agent.staking_escrow_contract == staking_agent.contract_address
    assert adjudicator_agent.hash_algorithm == slashing_economics.hash_algorithm
    assert adjudicator_agent.base_penalty == slashing_economics.base_penalty
    assert adjudicator_agent.penalty_history_coefficient == slashing_economics.penalty_history_coefficient
    assert adjudicator_agent.percentage_penalty_coefficient == slashing_economics.percentage_penalty_coefficient
    assert adjudicator_agent.reward_coefficient == slashing_economics.reward_coefficient

    # Retrieve the AdjudicatorAgent singleton
    some_policy_agent = AdjudicatorAgent()
    assert adjudicator_agent == some_policy_agent  # __eq__

    # Compare the contract address for equality
    assert adjudicator_agent.contract_address == some_policy_agent.contract_address
Beispiel #7
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! *********")
Beispiel #8
0
def test_deploy_ethereum_contracts(testerchain, deployment_progress,
                                   test_registry):
    testerchain = testerchain

    origin, *everybody_else = testerchain.client.accounts

    #
    # Nucypher Token
    #
    token_deployer = NucypherTokenDeployer(registry=test_registry,
                                           deployer_address=origin)
    assert token_deployer.deployer_address == origin

    with pytest.raises(ContractDeployer.ContractDeploymentError):
        assert token_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not token_deployer.is_deployed

    token_deployer.deploy(progress=deployment_progress)
    assert token_deployer.is_deployed
    assert len(token_deployer.contract_address) == 42

    token_agent = NucypherTokenAgent(registry=test_registry)
    assert len(token_agent.contract_address) == 42
    assert token_agent.contract_address == token_deployer.contract_address

    another_token_agent = token_deployer.make_agent()
    assert len(another_token_agent.contract_address) == 42
    assert another_token_agent.contract_address == token_deployer.contract_address == token_agent.contract_address

    #
    # StakingEscrow
    #
    stakers_escrow_secret = os.urandom(
        DispatcherDeployer.DISPATCHER_SECRET_LENGTH)
    staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry,
                                                    deployer_address=origin)
    assert staking_escrow_deployer.deployer_address == origin

    with pytest.raises(ContractDeployer.ContractDeploymentError):
        assert staking_escrow_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not staking_escrow_deployer.is_deployed

    staking_escrow_deployer.deploy(secret_hash=keccak(stakers_escrow_secret),
                                   progress=deployment_progress)
    assert staking_escrow_deployer.is_deployed
    assert len(staking_escrow_deployer.contract_address) == 42

    staking_agent = ContractAgency.get_agent(StakingEscrowAgent,
                                             registry=test_registry)
    assert len(staking_agent.contract_address) == 42
    assert staking_agent.contract_address == staking_escrow_deployer.contract_address

    another_staking_agent = staking_escrow_deployer.make_agent()
    assert len(another_staking_agent.contract_address) == 42
    assert another_staking_agent.contract_address == staking_escrow_deployer.contract_address == staking_agent.contract_address

    #
    # Policy Manager
    #
    policy_manager_secret = os.urandom(
        DispatcherDeployer.DISPATCHER_SECRET_LENGTH)
    policy_manager_deployer = PolicyManagerDeployer(registry=test_registry,
                                                    deployer_address=origin)

    assert policy_manager_deployer.deployer_address == origin

    with pytest.raises(ContractDeployer.ContractDeploymentError):
        assert policy_manager_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not policy_manager_deployer.is_deployed

    policy_manager_deployer.deploy(secret_hash=keccak(policy_manager_secret),
                                   progress=deployment_progress)
    assert policy_manager_deployer.is_deployed
    assert len(policy_manager_deployer.contract_address) == 42

    policy_agent = policy_manager_deployer.make_agent()
    assert len(policy_agent.contract_address) == 42
    assert policy_agent.contract_address == policy_manager_deployer.contract_address

    another_policy_agent = policy_manager_deployer.make_agent()
    assert len(another_policy_agent.contract_address) == 42
    assert another_policy_agent.contract_address == policy_manager_deployer.contract_address == policy_agent.contract_address

    #
    # Adjudicator
    #
    adjudicator_secret = os.urandom(
        DispatcherDeployer.DISPATCHER_SECRET_LENGTH)
    adjudicator_deployer = AdjudicatorDeployer(registry=test_registry,
                                               deployer_address=origin)

    assert adjudicator_deployer.deployer_address == origin

    with pytest.raises(ContractDeployer.ContractDeploymentError):
        assert adjudicator_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not adjudicator_deployer.is_deployed

    adjudicator_deployer.deploy(secret_hash=keccak(adjudicator_secret),
                                progress=deployment_progress)
    assert adjudicator_deployer.is_deployed
    assert len(adjudicator_deployer.contract_address) == 42

    adjudicator_agent = adjudicator_deployer.make_agent()
    assert len(adjudicator_agent.contract_address) == 42
    assert adjudicator_agent.contract_address == adjudicator_deployer.contract_address

    another_adjudicator_agent = AdjudicatorAgent(registry=test_registry)
    assert len(another_adjudicator_agent.contract_address) == 42
    assert another_adjudicator_agent.contract_address == adjudicator_deployer.contract_address == adjudicator_agent.contract_address

    # overall deployment steps must match aggregated individual expected number of steps
    all_deployment_transactions = token_deployer.deployment_steps + staking_escrow_deployer.deployment_steps + \
                                  policy_manager_deployer.deployment_steps + adjudicator_deployer.deployment_steps
    assert deployment_progress.num_steps == len(all_deployment_transactions)
Beispiel #9
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)
Beispiel #10
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)
Beispiel #11
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! *********")
Beispiel #12
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! *********")
def test_deploy_ethereum_contracts(testerchain,
                                   deployment_progress,
                                   test_registry):

    origin, *everybody_else = testerchain.client.accounts
    tpower = TransactingPower(account=origin,
                              signer=Web3Signer(testerchain.client))

    #
    # Nucypher Token
    #
    token_deployer = NucypherTokenDeployer(registry=test_registry)

    with pytest.raises(BaseContractDeployer.ContractDeploymentError):
        assert token_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not token_deployer.is_deployed()

    token_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
    assert token_deployer.is_deployed()
    assert len(token_deployer.contract_address) == 42

    token_agent = NucypherTokenAgent(registry=test_registry)
    assert len(token_agent.contract_address) == 42
    assert token_agent.contract_address == token_deployer.contract_address

    another_token_agent = token_deployer.make_agent()
    assert len(another_token_agent.contract_address) == 42
    assert another_token_agent.contract_address == token_deployer.contract_address == token_agent.contract_address

    #
    # StakingEscrowStub
    #
    staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)

    with pytest.raises(BaseContractDeployer.ContractDeploymentError):
        assert staking_escrow_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not staking_escrow_deployer.is_deployed()

    staking_escrow_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
    assert not staking_escrow_deployer.is_deployed()
    assert len(staking_escrow_deployer.contract_address) == 42


    #
    # Policy Manager
    #
    policy_manager_deployer = PolicyManagerDeployer(registry=test_registry)

    with pytest.raises(BaseContractDeployer.ContractDeploymentError):
        assert policy_manager_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not policy_manager_deployer.is_deployed()

    policy_manager_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
    assert policy_manager_deployer.is_deployed()
    assert len(policy_manager_deployer.contract_address) == 42

    policy_agent = policy_manager_deployer.make_agent()
    assert len(policy_agent.contract_address) == 42
    assert policy_agent.contract_address == policy_manager_deployer.contract_address

    another_policy_agent = policy_manager_deployer.make_agent()
    assert len(another_policy_agent.contract_address) == 42
    assert another_policy_agent.contract_address == policy_manager_deployer.contract_address == policy_agent.contract_address


    #
    # Adjudicator
    #
    adjudicator_deployer = AdjudicatorDeployer(registry=test_registry)

    with pytest.raises(BaseContractDeployer.ContractDeploymentError):
        assert adjudicator_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not adjudicator_deployer.is_deployed()

    adjudicator_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
    assert adjudicator_deployer.is_deployed()
    assert len(adjudicator_deployer.contract_address) == 42

    adjudicator_agent = adjudicator_deployer.make_agent()
    assert len(adjudicator_agent.contract_address) == 42
    assert adjudicator_agent.contract_address == adjudicator_deployer.contract_address

    another_adjudicator_agent = AdjudicatorAgent(registry=test_registry)
    assert len(another_adjudicator_agent.contract_address) == 42
    assert another_adjudicator_agent.contract_address == adjudicator_deployer.contract_address == adjudicator_agent.contract_address

    # StakingEscrow
    staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)

    with pytest.raises(BaseContractDeployer.ContractDeploymentError):
        assert staking_escrow_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
    assert not staking_escrow_deployer.is_deployed()

    staking_escrow_deployer.deploy(progress=deployment_progress,
                                   deployment_mode=constants.FULL,
                                   transacting_power=tpower)
    assert staking_escrow_deployer.is_deployed()
    assert len(staking_escrow_deployer.contract_address) == 42

    staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
    assert len(staking_agent.contract_address) == 42
    assert staking_agent.contract_address == staking_escrow_deployer.contract_address

    another_staking_agent = staking_escrow_deployer.make_agent()
    assert len(another_staking_agent.contract_address) == 42
    assert another_staking_agent.contract_address == staking_escrow_deployer.contract_address == staking_agent.contract_address

    # overall deployment steps must match aggregated individual expected number of steps
    all_deployment_transactions = token_deployer.deployment_steps + staking_escrow_deployer.init_steps + \
                                  staking_escrow_deployer.deployment_steps + \
                                  policy_manager_deployer.deployment_steps + adjudicator_deployer.deployment_steps
    assert deployment_progress.num_steps == len(all_deployment_transactions)
Beispiel #14
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, agents = 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 = PolicyAgent(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 *********")

    #
    # Pre deposit tokens
    #
    tx = token_functions.approve(staking_agent.contract_address,
                                 MIN_ALLOWED_LOCKED * 5).transact(
                                     {'from': origin})
    testerchain.wait_for_receipt(tx)
    log.info("Pre-deposit tokens for 5 owners = " + str(
        staker_functions.preDeposit(everyone_else[0:5], [MIN_ALLOWED_LOCKED] *
                                    5, [MIN_LOCKED_PERIODS] *
                                    5).estimateGas({'from': origin})))

    #
    # Give Ursula and Alice some coins
    #
    log.info("Transfer tokens = " + str(
        token_functions.transfer(ursula1, MIN_ALLOWED_LOCKED *
                                 10).estimateGas({'from': origin})))
    tx = token_functions.transfer(ursula1, MIN_ALLOWED_LOCKED * 10).transact(
        {'from': origin})
    testerchain.wait_for_receipt(tx)
    tx = token_functions.transfer(ursula2, MIN_ALLOWED_LOCKED * 10).transact(
        {'from': origin})
    testerchain.wait_for_receipt(tx)
    tx = token_functions.transfer(ursula3, MIN_ALLOWED_LOCKED * 10).transact(
        {'from': origin})
    testerchain.wait_for_receipt(tx)

    #
    # Ursula and Alice give Escrow rights to transfer
    #
    log.info("Approving transfer = " + str(
        token_functions.approve(staking_agent.contract_address,
                                MIN_ALLOWED_LOCKED *
                                6).estimateGas({'from': ursula1})))
    tx = token_functions.approve(staking_agent.contract_address,
                                 MIN_ALLOWED_LOCKED * 6).transact(
                                     {'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = token_functions.approve(staking_agent.contract_address,
                                 MIN_ALLOWED_LOCKED * 6).transact(
                                     {'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = token_functions.approve(staking_agent.contract_address,
                                 MIN_ALLOWED_LOCKED * 6).transact(
                                     {'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Ursula and Alice transfer some tokens to the escrow and lock them
    #
    log.info("First initial deposit tokens = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula1})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second initial deposit tokens = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula2})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third initial deposit tokens = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula3})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    tx = staker_functions.setWorker(ursula1).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.setWorker(ursula2).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.setWorker(ursula3).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.confirmActivity().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Wait 1 period and confirm activity
    #
    testerchain.time_travel(periods=1)
    log.info(
        "First confirm activity = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula1})))
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Second confirm activity = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula2})))
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Third confirm activity = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula3})))
    tx = staker_functions.confirmActivity().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Wait 1 period and mint tokens
    #
    testerchain.time_travel(periods=1)
    log.info("First mining (1 stake) = " +
             str(staker_functions.mint().estimateGas({'from': ursula1})))
    tx = staker_functions.mint().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second mining (1 stake) = " +
             str(staker_functions.mint().estimateGas({'from': ursula2})))
    tx = staker_functions.mint().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third/last mining (1 stake) = " +
             str(staker_functions.mint().estimateGas({'from': ursula3})))
    tx = staker_functions.mint().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    log.info(
        "First confirm activity again = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula1})))
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Second confirm activity again = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula2})))
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Third confirm activity again = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula3})))
    tx = staker_functions.confirmActivity().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Confirm again
    #
    testerchain.time_travel(periods=1)
    log.info(
        "First confirm activity + mint = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula1})))
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Second confirm activity + mint = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula2})))
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Third confirm activity + mint = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula3})))
    tx = staker_functions.confirmActivity().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Get locked tokens
    #
    log.info("Getting locked tokens = " +
             str(staker_functions.getLockedTokens(ursula1).estimateGas()))

    #
    # Wait 1 period and withdraw tokens
    #
    testerchain.time_travel(periods=1)
    log.info("First withdraw = " +
             str(staker_functions.withdraw(1).estimateGas({'from': ursula1})))
    tx = staker_functions.withdraw(1).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second withdraw = " +
             str(staker_functions.withdraw(1).estimateGas({'from': ursula2})))
    tx = staker_functions.withdraw(1).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third withdraw = " +
             str(staker_functions.withdraw(1).estimateGas({'from': ursula3})))
    tx = staker_functions.withdraw(1).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Confirm activity with re-stake
    #
    tx = staker_functions.setReStake(True).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.setReStake(True).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.setReStake(True).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    log.info(
        "First confirm activity + mint with re-stake = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula1})))
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Second confirm activity + mint with re-stake  = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula2})))
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Third confirm activity + mint with re-stake  = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula3})))
    tx = staker_functions.confirmActivity().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    tx = staker_functions.setReStake(False).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.setReStake(False).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.setReStake(False).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Wait 2 periods and confirm activity after downtime
    #
    testerchain.time_travel(periods=2)
    log.info(
        "First confirm activity after downtime = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula1})))
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Second confirm activity after downtime  = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula2})))
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info(
        "Third confirm activity after downtime  = " +
        str(staker_functions.confirmActivity().estimateGas({'from': ursula3})))
    tx = staker_functions.confirmActivity().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Ursula and Alice deposit some tokens to the escrow again
    #
    log.info("First deposit tokens again = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula1})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second deposit tokens again = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula2})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third deposit tokens again = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula3})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Wait 1 period and mint tokens
    #
    testerchain.time_travel(periods=1)
    log.info("First mining again = " +
             str(staker_functions.mint().estimateGas({'from': ursula1})))
    tx = staker_functions.mint().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second mining again = " +
             str(staker_functions.mint().estimateGas({'from': ursula2})))
    tx = staker_functions.mint().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third/last mining again = " +
             str(staker_functions.mint().estimateGas({'from': ursula3})))
    tx = staker_functions.mint().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Create policy
    #
    policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    number_of_periods = 10
    log.info("First creating policy (1 node, 10 periods) = " + str(
        policy_functions.createPolicy(policy_id_1, number_of_periods, 0,
                                      [ursula1]).estimateGas({
                                          'from': alice1,
                                          'value': 10000
                                      })))
    tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 0,
                                       [ursula1]).transact({
                                           'from': alice1,
                                           'value': 10000
                                       })
    testerchain.wait_for_receipt(tx)
    log.info("Second creating policy (1 node, 10 periods) = " + str(
        policy_functions.createPolicy(policy_id_2, number_of_periods, 0,
                                      [ursula1]).estimateGas({
                                          'from': alice1,
                                          'value': 10000
                                      })))
    tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 0,
                                       [ursula1]).transact({
                                           'from': alice1,
                                           'value': 10000
                                       })
    testerchain.wait_for_receipt(tx)

    #
    # Revoke policy
    #
    log.info("Revoking policy = " + str(
        policy_functions.revokePolicy(policy_id_1).estimateGas(
            {'from': alice1})))
    tx = policy_functions.revokePolicy(policy_id_1).transact({'from': alice1})
    testerchain.wait_for_receipt(tx)
    tx = policy_functions.revokePolicy(policy_id_2).transact({'from': alice1})
    testerchain.wait_for_receipt(tx)

    #
    # Create policy with more periods
    #
    policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    policy_id_3 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    number_of_periods = 100
    log.info(
        "First creating policy (1 node, " + str(number_of_periods) +
        " periods, first reward) = " + str(
            policy_functions.createPolicy(policy_id_1, number_of_periods, 50,
                                          [ursula2]).estimateGas({
                                              'from': alice1,
                                              'value': 10050
                                          })))
    tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 50,
                                       [ursula2]).transact({
                                           'from': alice1,
                                           'value': 10050
                                       })
    testerchain.wait_for_receipt(tx)
    testerchain.time_travel(periods=1)
    log.info(
        "Second creating policy (1 node, " + str(number_of_periods) +
        " periods, first reward) = " + str(
            policy_functions.createPolicy(policy_id_2, number_of_periods, 50,
                                          [ursula2]).estimateGas({
                                              'from': alice1,
                                              'value': 10050
                                          })))
    tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 50,
                                       [ursula2]).transact({
                                           'from': alice1,
                                           'value': 10050
                                       })
    testerchain.wait_for_receipt(tx)
    log.info(
        "Third creating policy (1 node, " + str(number_of_periods) +
        " periods, first reward) = " + str(
            policy_functions.createPolicy(policy_id_3, number_of_periods, 50,
                                          [ursula1]).estimateGas({
                                              'from': alice1,
                                              'value': 10050
                                          })))
    tx = policy_functions.createPolicy(policy_id_3, number_of_periods, 50,
                                       [ursula1]).transact({
                                           'from': alice1,
                                           'value': 10050
                                       })
    testerchain.wait_for_receipt(tx)

    #
    # Mine and revoke policy
    #
    testerchain.time_travel(periods=10)
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)

    testerchain.time_travel(periods=1)
    log.info("First mining after downtime = " +
             str(staker_functions.mint().estimateGas({'from': ursula1})))
    tx = staker_functions.mint().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second mining after downtime = " +
             str(staker_functions.mint().estimateGas({'from': ursula2})))
    tx = staker_functions.mint().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)

    testerchain.time_travel(periods=10)
    log.info("First revoking policy after downtime = " + str(
        policy_functions.revokePolicy(policy_id_1).estimateGas(
            {'from': alice1})))
    tx = policy_functions.revokePolicy(policy_id_1).transact({'from': alice1})
    testerchain.wait_for_receipt(tx)
    log.info("Second revoking policy after downtime = " + str(
        policy_functions.revokePolicy(policy_id_2).estimateGas(
            {'from': alice1})))
    tx = policy_functions.revokePolicy(policy_id_2).transact({'from': alice1})
    testerchain.wait_for_receipt(tx)
    log.info("Second revoking policy after downtime = " + str(
        policy_functions.revokePolicy(policy_id_3).estimateGas(
            {'from': alice1})))
    tx = policy_functions.revokePolicy(policy_id_3).transact({'from': alice1})
    testerchain.wait_for_receipt(tx)

    #
    # Create policy with multiple nodes
    #
    policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    policy_id_3 = os.urandom(int(Policy.POLICY_ID_LENGTH))
    number_of_periods = 100
    log.info("First creating policy (3 nodes, 100 periods, first reward) = " +
             str(
                 policy_functions.createPolicy(
                     policy_id_1, number_of_periods, 50,
                     [ursula1, ursula2, ursula3]).estimateGas({
                         'from': alice1,
                         'value': 30150
                     })))
    tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 50,
                                       [ursula1, ursula2, ursula3]).transact({
                                           'from':
                                           alice1,
                                           'value':
                                           30150
                                       })
    testerchain.wait_for_receipt(tx)
    log.info("Second creating policy (3 nodes, 100 periods, first reward) = " +
             str(
                 policy_functions.createPolicy(
                     policy_id_2, number_of_periods, 50,
                     [ursula1, ursula2, ursula3]).estimateGas({
                         'from': alice1,
                         'value': 30150
                     })))
    tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 50,
                                       [ursula1, ursula2, ursula3]).transact({
                                           'from':
                                           alice1,
                                           'value':
                                           30150
                                       })
    testerchain.wait_for_receipt(tx)
    log.info("Third creating policy (2 nodes, 100 periods, first reward) = " +
             str(
                 policy_functions.createPolicy(
                     policy_id_3, number_of_periods, 50,
                     [ursula1, ursula2]).estimateGas({
                         'from': alice1,
                         'value': 20100
                     })))
    tx = policy_functions.createPolicy(policy_id_3, number_of_periods, 50,
                                       [ursula1, ursula2]).transact({
                                           'from':
                                           alice1,
                                           'value':
                                           20100
                                       })
    testerchain.wait_for_receipt(tx)

    for index in range(5):
        tx = staker_functions.confirmActivity().transact({'from': ursula1})
        testerchain.wait_for_receipt(tx)
        tx = staker_functions.confirmActivity().transact({'from': ursula2})
        testerchain.wait_for_receipt(tx)
        tx = staker_functions.confirmActivity().transact({'from': ursula3})
        testerchain.wait_for_receipt(tx)
        testerchain.time_travel(periods=1)

    tx = staker_functions.mint().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.mint().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.mint().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Check regular deposit
    #
    log.info("First deposit tokens = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula1})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second deposit tokens = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula2})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third deposit tokens = " + str(
        staker_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula3})))
    tx = staker_functions.deposit(
        MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # ApproveAndCall
    #
    testerchain.time_travel(periods=1)

    tx = staker_functions.mint().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.mint().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.mint().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    log.info("First approveAndCall = " + str(
        token_functions.approveAndCall(
            staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2,
            web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1})))
    tx = token_functions.approveAndCall(
        staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2,
        web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second approveAndCall = " + str(
        token_functions.approveAndCall(
            staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2,
            web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2})))
    tx = token_functions.approveAndCall(
        staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2,
        web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third approveAndCall = " + str(
        token_functions.approveAndCall(
            staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2,
            web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3})))
    tx = token_functions.approveAndCall(
        staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2,
        web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Locking tokens
    #
    testerchain.time_travel(periods=1)

    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.confirmActivity().transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    tx = staker_functions.confirmActivity().transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    log.info("First locking tokens = " + str(
        staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula1})))
    tx = staker_functions.lock(MIN_ALLOWED_LOCKED,
                               MIN_LOCKED_PERIODS).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second locking tokens = " + str(
        staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula2})))
    tx = staker_functions.lock(MIN_ALLOWED_LOCKED,
                               MIN_LOCKED_PERIODS).transact({'from': ursula2})
    testerchain.wait_for_receipt(tx)
    log.info("Third locking tokens = " + str(
        staker_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).
        estimateGas({'from': ursula3})))
    tx = staker_functions.lock(MIN_ALLOWED_LOCKED,
                               MIN_LOCKED_PERIODS).transact({'from': ursula3})
    testerchain.wait_for_receipt(tx)

    #
    # Divide stake
    #
    log.info("First divide stake = " + str(
        staker_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2).estimateGas(
            {'from': ursula1})))
    tx = staker_functions.divideStake(1, MIN_ALLOWED_LOCKED,
                                      2).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Second divide stake = " + str(
        staker_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2).estimateGas(
            {'from': ursula1})))
    tx = staker_functions.divideStake(3, MIN_ALLOWED_LOCKED,
                                      2).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)

    #
    # Divide almost finished stake
    #
    testerchain.time_travel(periods=1)
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    testerchain.time_travel(periods=1)
    log.info("Divide stake (next period is not confirmed) = " + str(
        staker_functions.divideStake(0, MIN_ALLOWED_LOCKED, 2).estimateGas(
            {'from': ursula1})))
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    log.info("Divide stake (next period is confirmed) = " + str(
        staker_functions.divideStake(0, MIN_ALLOWED_LOCKED, 2).estimateGas(
            {'from': ursula1})))

    #
    # Slashing tests
    #
    tx = staker_functions.confirmActivity().transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    testerchain.time_travel(periods=1)

    #
    # Slashing
    #
    slashing_args = generate_args_for_slashing(ursula_with_stamp)
    log.info("Slash just value = " + str(
        adjudicator_functions.evaluateCFrag(
            *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    deposit = staker_functions.stakerInfo(ursula1).call()[0]
    unlocked = deposit - staker_functions.getLockedTokens(ursula1).call()
    tx = staker_functions.withdraw(unlocked).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)

    sub_stakes_length = str(
        staker_functions.getSubStakesLength(ursula1).call())
    slashing_args = generate_args_for_slashing(ursula_with_stamp)
    log.info("First slashing one sub stake and saving old one (" +
             sub_stakes_length + " sub stakes) = " + str(
                 adjudicator_functions.evaluateCFrag(
                     *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    sub_stakes_length = str(
        staker_functions.getSubStakesLength(ursula1).call())
    slashing_args = generate_args_for_slashing(ursula_with_stamp)
    log.info("Second slashing one sub stake and saving old one (" +
             sub_stakes_length + " sub stakes) = " + str(
                 adjudicator_functions.evaluateCFrag(
                     *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    sub_stakes_length = str(
        staker_functions.getSubStakesLength(ursula1).call())
    slashing_args = generate_args_for_slashing(ursula_with_stamp)
    log.info("Third slashing one sub stake and saving old one (" +
             sub_stakes_length + " sub stakes) = " + str(
                 adjudicator_functions.evaluateCFrag(
                     *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    sub_stakes_length = str(
        staker_functions.getSubStakesLength(ursula1).call())
    slashing_args = generate_args_for_slashing(ursula_with_stamp)
    log.info("Slashing two sub stakes and saving old one (" +
             sub_stakes_length + " sub stakes) = " + str(
                 adjudicator_functions.evaluateCFrag(
                     *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    for index in range(18):
        tx = staker_functions.confirmActivity().transact({'from': ursula1})
        testerchain.wait_for_receipt(tx)
        testerchain.time_travel(periods=1)

    tx = staker_functions.lock(MIN_ALLOWED_LOCKED,
                               MIN_LOCKED_PERIODS).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)
    deposit = staker_functions.stakerInfo(ursula1).call()[0]
    unlocked = deposit - staker_functions.getLockedTokens(ursula1, 1).call()
    tx = staker_functions.withdraw(unlocked).transact({'from': ursula1})
    testerchain.wait_for_receipt(tx)

    sub_stakes_length = str(
        staker_functions.getSubStakesLength(ursula1).call())
    slashing_args = generate_args_for_slashing(ursula_with_stamp)
    log.info("Slashing two sub stakes, shortest and new one (" +
             sub_stakes_length + " sub stakes) = " + str(
                 adjudicator_functions.evaluateCFrag(
                     *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    sub_stakes_length = str(
        staker_functions.getSubStakesLength(ursula1).call())
    slashing_args = generate_args_for_slashing(ursula_with_stamp)
    log.info("Slashing three sub stakes, two shortest and new one (" +
             sub_stakes_length + " sub stakes) = " + str(
                 adjudicator_functions.evaluateCFrag(
                     *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    slashing_args = generate_args_for_slashing(ursula_with_stamp,
                                               corrupt_cfrag=False)
    log.info("Evaluating correct CFrag = " + str(
        adjudicator_functions.evaluateCFrag(
            *slashing_args).estimateGas({'from': alice1})))
    tx = adjudicator_functions.evaluateCFrag(*slashing_args).transact(
        {'from': alice1})
    testerchain.wait_for_receipt(tx)

    print("********* All Done! *********")
def test_adjudicator_slashes(
        agency,
        testerchain,
        #mock_ursula_reencrypts,
        token_economics,
        test_registry,
        mocker):

    staker_account = testerchain.staker_account(0)
    worker_account = testerchain.ursula_account(0)

    ##### STAKING ESCROW STUFF #####

    token_agent = ContractAgency.get_agent(NucypherTokenAgent,
                                           registry=test_registry)
    staking_agent = ContractAgency.get_agent(StakingEscrowAgent,
                                             registry=test_registry)

    locked_tokens = token_economics.minimum_allowed_locked * 5

    # The staker receives an initial amount of tokens
    tpower = TransactingPower(account=testerchain.etherbase_account,
                              signer=Web3Signer(testerchain.client))
    _txhash = token_agent.transfer(amount=locked_tokens,
                                   target_address=staker_account,
                                   transacting_power=tpower)

    # Deposit: The staker deposits tokens in the StakingEscrow contract.
    tpower = TransactingPower(account=staker_account,
                              signer=Web3Signer(testerchain.client))
    staker = Staker(domain=TEMPORARY_DOMAIN,
                    registry=test_registry,
                    transacting_power=tpower)

    staker.initialize_stake(
        amount=NU(locked_tokens, 'NuNit'),
        lock_periods=token_economics.minimum_locked_periods)
    assert staker.locked_tokens(periods=1) == locked_tokens

    # The staker hasn't bond a worker yet
    assert NULL_ADDRESS == staking_agent.get_worker_from_staker(
        staker_address=staker_account)

    _txhash = staking_agent.bond_worker(transacting_power=tpower,
                                        worker_address=worker_account)

    assert worker_account == staking_agent.get_worker_from_staker(
        staker_address=staker_account)
    assert staker_account == staking_agent.get_staker_from_worker(
        worker_address=worker_account)

    ###### END OF STAKING ESCROW STUFF ####

    adjudicator_agent = AdjudicatorAgent(registry=test_registry)
    bob_account = testerchain.bob_account
    bobby = NucypherTokenActor(checksum_address=bob_account,
                               domain=TEMPORARY_DOMAIN,
                               registry=test_registry)
    ursula = mock_ursula(testerchain, worker_account, mocker=mocker)

    # Let's create a bad cfrag
    evidence = mock_ursula_reencrypts(ursula, corrupt_cfrag=True)

    assert not adjudicator_agent.was_this_evidence_evaluated(evidence)
    bobby_old_balance = bobby.token_balance
    bob_tpower = TransactingPower(account=bob_account,
                                  signer=Web3Signer(testerchain.client))

    adjudicator_agent.evaluate_cfrag(evidence=evidence,
                                     transacting_power=bob_tpower)

    assert adjudicator_agent.was_this_evidence_evaluated(evidence)
    investigator_reward = bobby.token_balance - bobby_old_balance

    assert investigator_reward > 0
    assert investigator_reward == token_economics.base_penalty / token_economics.reward_coefficient
    assert staker.locked_tokens(periods=1) < locked_tokens
Beispiel #16
0
    def __init__(self, checksum_address: str, *args, **kwargs) -> None:

        super().__init__(checksum_address=checksum_address, *args, **kwargs)

        self.adjudicator_agent = AdjudicatorAgent(blockchain=self.blockchain)
Beispiel #17
0
def test_adjudicator_slashes(agency, testerchain, mock_ursula_reencrypts,
                             token_economics, test_registry, mocker):

    staker_account = testerchain.staker_account(0)
    worker_account = testerchain.ursula_account(0)

    ##### STAKING ESCROW STUFF #####

    token_agent, staking_agent, _policy_agent = agency

    locked_tokens = token_economics.minimum_allowed_locked * 5

    # Mock Powerup consumption (Deployer)
    testerchain.transacting_power = TransactingPower(
        password=INSECURE_DEVELOPMENT_PASSWORD,
        account=testerchain.etherbase_account)
    testerchain.transacting_power.activate()

    # The staker receives an initial amount of tokens
    _txhash = token_agent.transfer(
        amount=locked_tokens,
        target_address=staker_account,
        sender_address=testerchain.etherbase_account)

    # Mock Powerup consumption (Staker)
    testerchain.transacting_power = TransactingPower(
        password=INSECURE_DEVELOPMENT_PASSWORD, account=staker_account)
    testerchain.transacting_power.activate()

    # Deposit: The staker deposits tokens in the StakingEscrow contract.
    staker = Staker(checksum_address=staker_account,
                    is_me=True,
                    registry=test_registry)
    staker.initialize_stake(
        amount=NU(locked_tokens, 'NuNit'),
        lock_periods=token_economics.minimum_locked_periods)
    assert staker.locked_tokens(periods=1) == locked_tokens

    # The staker hasn't set a worker yet
    assert BlockchainInterface.NULL_ADDRESS == staking_agent.get_worker_from_staker(
        staker_address=staker_account)

    _txhash = staking_agent.set_worker(staker_address=staker_account,
                                       worker_address=worker_account)

    assert worker_account == staking_agent.get_worker_from_staker(
        staker_address=staker_account)
    assert staker_account == staking_agent.get_staker_from_worker(
        worker_address=worker_account)

    ###### END OF STAKING ESCROW STUFF ####

    adjudicator_agent = AdjudicatorAgent(registry=test_registry)
    bob_account = testerchain.bob_account
    bobby = NucypherTokenActor(checksum_address=bob_account,
                               registry=test_registry)
    ursula = mock_ursula(testerchain, worker_account, mocker=mocker)

    # Let's create a bad cfrag
    evidence = mock_ursula_reencrypts(ursula, corrupt_cfrag=True)

    assert not adjudicator_agent.was_this_evidence_evaluated(evidence)
    bobby_old_balance = bobby.token_balance

    # Mock Powerup consumption (Bob)
    testerchain.transacting_power = TransactingPower(
        password=INSECURE_DEVELOPMENT_PASSWORD, account=bob_account)
    testerchain.transacting_power.activate()

    adjudicator_agent.evaluate_cfrag(evidence=evidence,
                                     sender_address=bob_account)

    assert adjudicator_agent.was_this_evidence_evaluated(evidence)
    investigator_reward = bobby.token_balance - bobby_old_balance

    assert investigator_reward > 0
    assert investigator_reward == token_economics.base_penalty / token_economics.reward_coefficient
    assert staker.locked_tokens(periods=1) < locked_tokens