def test_collect_policy_reward(testerchain, agency, policy_meta,
                               token_economics):
    token_agent, staking_agent, policy_agent = agency
    agent = policy_agent

    staker = policy_meta.addresses[-1]
    worker = staking_agent.get_worker_from_staker(staker)

    # Mock Powerup consumption (Ursula-Worker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=worker)

    old_eth_balance = token_agent.blockchain.client.get_balance(staker)

    for _ in range(token_economics.minimum_locked_periods):
        _receipt = staking_agent.confirm_activity(worker_address=worker)
        testerchain.time_travel(periods=1)

    # Mock Powerup consumption (Ursula-Staker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=staker)

    receipt = agent.collect_policy_reward(collector_address=staker,
                                          staker_address=staker)
    assert receipt['status'] == 1, "Transaction Rejected"
    assert receipt['logs'][0]['address'] == agent.contract_address
    new_eth_balance = token_agent.blockchain.client.get_balance(staker)
    assert new_eth_balance > old_eth_balance
Example #2
0
def test_staker_collects_staking_reward(testerchain, staker,
                                        blockchain_ursulas, agency,
                                        token_economics,
                                        ursula_decentralized_test_config):
    token_agent, staking_agent, policy_agent = agency

    # Capture the current token balance of the staker
    initial_balance = staker.token_balance
    assert token_agent.get_balance(staker.checksum_address) == initial_balance

    # Mock Powerup consumption (Staker)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=staker.checksum_address)

    staker.initialize_stake(
        amount=NU(token_economics.minimum_allowed_locked,
                  'NuNit'),  # Lock the minimum amount of tokens
        lock_periods=int(token_economics.minimum_locked_periods)
    )  # ... for the fewest number of periods

    # Get an unused address for a new worker
    worker_address = testerchain.unassigned_accounts[-1]
    staker.set_worker(worker_address=worker_address)

    # Create this worker and bond it with the staker
    ursula = make_decentralized_ursulas(
        ursula_config=ursula_decentralized_test_config,
        stakers_addresses=[staker.checksum_address],
        workers_addresses=[worker_address],
        confirm_activity=False,
        blockchain=testerchain).pop()

    # ...wait out the lock period...
    for _ in range(token_economics.minimum_locked_periods):
        testerchain.time_travel(periods=1)
        ursula.confirm_activity()

    # ...wait more...
    testerchain.time_travel(periods=2)

    # Mock Powerup consumption (Staker)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=staker.checksum_address)

    # Profit!
    staker.collect_staking_reward()

    final_balance = token_agent.get_balance(staker.checksum_address)
    assert final_balance > initial_balance
Example #3
0
    def bootstrap_network(cls) -> Tuple['TesterBlockchain', Dict[str, EthereumContractAgent]]:
        """For use with metric testing scripts"""

        testerchain = cls(compiler=SolidityCompiler())
        power = BlockchainPower(blockchain=testerchain, account=testerchain.client.etherbase)
        power.unlock_account(password=INSECURE_DEVELOPMENT_PASSWORD)
        testerchain.transacting_power = power

        origin = testerchain.client.etherbase
        deployer = Deployer(blockchain=testerchain, deployer_address=origin, bare=True)
        _txhashes, agents = deployer.deploy_network_contracts(staker_secret=STAKING_ESCROW_DEPLOYMENT_SECRET,
                                                              policy_secret=POLICY_MANAGER_DEPLOYMENT_SECRET,
                                                              adjudicator_secret=ADJUDICATOR_DEPLOYMENT_SECRET,
                                                              user_escrow_proxy_secret=USER_ESCROW_PROXY_DEPLOYMENT_SECRET)
        return testerchain, agents
def test_collect_policy_reward(testerchain, agent, agency, token_economics):
    _token_agent, staking_agent, policy_agent = agency
    deployer_address, beneficiary_address, author, ursula, *everybody_else = testerchain.client.accounts

    # Mock Powerup consumption (Beneficiary)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=agent.beneficiary)

    _txhash = agent.deposit_as_staker(
        value=token_economics.minimum_allowed_locked,
        periods=token_economics.minimum_locked_periods)

    # User sets a worker in StakingEscrow via UserEscrow
    worker = testerchain.ursula_account(0)
    _receipt = agent.set_worker(worker_address=worker)

    testerchain.time_travel(periods=1)

    # Mock Powerup consumption (Alice)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=author)

    _txhash = policy_agent.create_policy(
        policy_id=os.urandom(16),
        author_address=author,
        value=to_wei(1, 'ether'),
        periods=2,
        initial_reward=0,
        node_addresses=[agent.contract_address])

    # Mock Powerup consumption (Beneficiary-Worker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=worker)

    _txhash = staking_agent.confirm_activity(worker_address=worker)
    testerchain.time_travel(periods=2)
    _txhash = staking_agent.confirm_activity(worker_address=worker)

    old_balance = testerchain.client.get_balance(account=agent.beneficiary)

    # Mock Powerup consumption (Beneficiary)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=agent.beneficiary)

    txhash = agent.collect_policy_reward()
    assert txhash  # TODO
    assert testerchain.client.get_balance(
        account=agent.beneficiary) > old_balance
def test_deposit_tokens(testerchain, agency, token_economics):
    token_agent, staking_agent, _policy_agent = agency

    locked_tokens = token_economics.minimum_allowed_locked * 5

    staker_account = testerchain.unassigned_accounts[0]

    # Mock Powerup consumption (Deployer)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=testerchain.etherbase_account)

    balance = token_agent.get_balance(address=staker_account)
    assert balance == 0

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

    # Mock Powerup consumption (Ursula-Staker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=staker_account)

    #
    # Deposit: The staker deposits tokens in the StakingEscrow contract.
    # Previously, she needs to approve this transfer on the token contract.
    #

    _receipt = token_agent.approve_transfer(
        amount=token_economics.minimum_allowed_locked * 10,  # Approve
        target_address=staking_agent.contract_address,
        sender_address=staker_account)

    receipt = staking_agent.deposit_tokens(
        amount=locked_tokens,
        lock_periods=token_economics.minimum_locked_periods,
        sender_address=staker_account)

    # Check the receipt for the contract address success code
    assert receipt['status'] == 1, "Transaction Rejected"
    assert receipt['logs'][2]['address'] == staking_agent.contract_address

    testerchain.time_travel(periods=1)
    balance = token_agent.get_balance(address=staker_account)
    assert balance == locked_tokens
    assert staking_agent.get_locked_tokens(
        staker_address=staker_account) == locked_tokens
def test_character_blockchain_power(testerchain, three_agents):
    # TODO: Handle multiple providers
    eth_address = testerchain.interface.w3.eth.accounts[0]
    sig_privkey = testerchain.interface.provider.ethereum_tester.backend._key_lookup[
        eth_utils.to_canonical_address(eth_address)]
    sig_pubkey = sig_privkey.public_key

    signer = Character(is_me=True, checksum_address=eth_address)
    signer._crypto_power.consume_power_up(BlockchainPower(testerchain, eth_address))

    # Due to testing backend, the account is already unlocked.
    power = signer._crypto_power.power_ups(BlockchainPower)
    power.is_unlocked = True
    # power.unlock_account('this-is-not-a-secure-password')

    data_to_sign = b'What does Ursula look like?!?'
    sig = power.sign_message(data_to_sign)

    is_verified = verify_eip_191(address=eth_address, message=data_to_sign, signature=sig)
    assert is_verified is True

    # Test a bad address/pubkey pair
    is_verified = verify_eip_191(address=testerchain.interface.w3.eth.accounts[1],
                                 message=data_to_sign,
                                 signature=sig)
    assert is_verified is False

    # Test a signature without unlocking the account
    power.is_unlocked = False
    with pytest.raises(PowerUpError):
        power.sign_message(b'test')

    # Test lockAccount call
    del power
Example #7
0
def test_staker_locking_tokens(testerchain, agency, staker, token_economics):
    token_agent, staking_agent, policy_agent = agency

    # Mock Powerup consumption (Ursula-Staker)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=staker.checksum_address)

    assert NU(token_economics.minimum_allowed_locked,
              'NuNit') < staker.token_balance, "Insufficient staker balance"

    staker.initialize_stake(
        amount=NU(token_economics.minimum_allowed_locked,
                  'NuNit'),  # Lock the minimum amount of tokens
        lock_periods=token_economics.minimum_locked_periods)

    # Verify that the escrow is "approved" to receive tokens
    allowance = token_agent.contract.functions.allowance(
        staker.checksum_address, staking_agent.contract_address).call()
    assert 0 == allowance

    # Staking starts after one period
    locked_tokens = staker.locked_tokens()
    assert 0 == locked_tokens

    locked_tokens = staker.locked_tokens(periods=1)
    assert token_economics.minimum_allowed_locked == locked_tokens
def test_collect_staking_reward(agency, testerchain):
    token_agent, staking_agent, _policy_agent = agency

    staker_account, worker_account, *other = testerchain.unassigned_accounts

    # Confirm Activity
    _receipt = staking_agent.confirm_activity(worker_address=worker_account)
    testerchain.time_travel(periods=2)

    # Mock Powerup consumption (Ursula-Staker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=staker_account)

    # Mint
    _receipt = staking_agent.mint(staker_address=staker_account)

    old_balance = token_agent.get_balance(address=staker_account)

    receipt = staking_agent.collect_staking_reward(
        staker_address=staker_account)
    assert receipt['status'] == 1, "Transaction Rejected"
    assert receipt['logs'][-1]['address'] == staking_agent.contract_address

    new_balance = token_agent.get_balance(
        address=staker_account)  # not the shoes
    assert new_balance > old_balance
def test_rapid_deployment(token_economics):
    compiler = SolidityCompiler()
    allocation_registry = InMemoryAllocationRegistry()

    blockchain = _TesterBlockchain(eth_airdrop=False,
                                   test_accounts=4,
                                   compiler=compiler)

    # TODO: #1092 - TransactingPower
    blockchain.transacting_power = BlockchainPower(
        blockchain=blockchain, account=blockchain.etherbase_account)
    deployer_address = blockchain.etherbase_account

    deployer = Deployer(blockchain=blockchain,
                        deployer_address=deployer_address)

    deployer.deploy_network_contracts(
        staker_secret=STAKING_ESCROW_DEPLOYMENT_SECRET,
        policy_secret=POLICY_MANAGER_DEPLOYMENT_SECRET,
        adjudicator_secret=ADJUDICATOR_DEPLOYMENT_SECRET,
        user_escrow_proxy_secret=USER_ESCROW_PROXY_DEPLOYMENT_SECRET)

    all_yall = blockchain.unassigned_accounts
    # Start with some hard-coded cases...
    allocation_data = [{
        'address': all_yall[1],
        'amount': token_economics.maximum_allowed_locked,
        'duration': ONE_YEAR_IN_SECONDS
    }, {
        'address': all_yall[2],
        'amount': token_economics.minimum_allowed_locked,
        'duration': ONE_YEAR_IN_SECONDS * 2
    }, {
        'address': all_yall[3],
        'amount': token_economics.minimum_allowed_locked * 100,
        'duration': ONE_YEAR_IN_SECONDS * 3
    }]

    # Pile on the rest
    for _ in range(NUMBER_OF_ALLOCATIONS_IN_TESTS - len(allocation_data)):
        random_password = ''.join(
            random.SystemRandom().choice(string.ascii_uppercase +
                                         string.digits) for _ in range(16))
        acct = w3.eth.account.create(random_password)
        beneficiary_address = acct.address
        amount = random.randint(token_economics.minimum_allowed_locked,
                                token_economics.maximum_allowed_locked)
        duration = random.randint(
            token_economics.minimum_locked_periods * ONE_YEAR_IN_SECONDS,
            (token_economics.maximum_locked_periods * ONE_YEAR_IN_SECONDS) * 3)
        random_allocation = {
            'address': beneficiary_address,
            'amount': amount,
            'duration': duration
        }
        allocation_data.append(random_allocation)

    deployer.deploy_beneficiary_contracts(
        allocations=allocation_data, allocation_registry=allocation_registry)
Example #10
0
def make_testerchain():

    # Create new blockchain
    testerchain = _TesterBlockchain(eth_airdrop=True, free_transactions=False)

    # Set the deployer address from a freshly created test account
    testerchain.deployer_address = testerchain.etherbase_account
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=testerchain.etherbase_account)
    return testerchain
Example #11
0
def stakers(agency, token_economics):
    token_agent, _staking_agent, _policy_agent = agency
    blockchain = token_agent.blockchain

    # Mock Powerup consumption (Deployer)
    blockchain.transacting_power = BlockchainPower(
        blockchain=blockchain, account=blockchain.etherbase_account)

    token_airdrop(origin=blockchain.etherbase_account,
                  addresses=blockchain.stakers_accounts,
                  token_agent=token_agent,
                  amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)

    stakers = list()
    for index, account in enumerate(blockchain.stakers_accounts):
        staker = Staker(is_me=True,
                        checksum_address=account,
                        blockchain=blockchain)

        # Mock TransactingPower consumption (Ursula-Staker)
        staker.blockchain.transacting_power = BlockchainPower(
            blockchain=staker.blockchain, account=staker.checksum_address)

        min_stake, balance = token_economics.minimum_allowed_locked, staker.token_balance
        amount = random.randint(min_stake, balance)

        # for a random lock duration
        min_locktime, max_locktime = token_economics.minimum_locked_periods, token_economics.maximum_locked_periods
        periods = random.randint(min_locktime, max_locktime)

        staker.initialize_stake(amount=amount, lock_periods=periods)

        # We assume that the staker knows in advance the account of her worker
        worker_address = blockchain.ursula_account(index)
        staker.set_worker(worker_address=worker_address)

        stakers.append(staker)

    # Stake starts next period (or else signature validation will fail)
    blockchain.time_travel(periods=1)

    yield stakers
def test_calculate_refund(testerchain, agency, policy_meta):
    token_agent, staking_agent, policy_agent = agency
    agent = policy_agent

    staker = policy_meta.addresses[-1]
    worker = staking_agent.get_worker_from_staker(staker)

    # Mock Powerup consumption (Ursula-Worker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=worker)

    testerchain.time_travel(hours=9)
    _receipt = staking_agent.confirm_activity(worker_address=worker)

    # Mock Powerup consumption (Alice)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=testerchain.alice_account)

    receipt = agent.calculate_refund(policy_id=policy_meta.policy_id,
                                     author_address=policy_meta.author)
    assert receipt['status'] == 1, "Transaction Rejected"
def test_confirm_activity(agency, testerchain):
    _token_agent, staking_agent, _policy_agent = agency

    staker_account, worker_account, *other = testerchain.unassigned_accounts

    # Mock Powerup consumption (Ursula-Worker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=worker_account)

    receipt = staking_agent.confirm_activity(worker_address=worker_account)
    assert receipt['status'] == 1, "Transaction Rejected"
    assert receipt['logs'][0]['address'] == staking_agent.contract_address
Example #14
0
def testerchain():
    """
    https://github.com/ethereum/eth-tester     # available-backends
    """
    # Create the blockchain
    testerchain = TesterBlockchain(eth_airdrop=True, free_transactions=True)

    # TODO: TransactingPower
    # Mock TransactingPower Consumption
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=testerchain.etherbase_account)
    testerchain.deployer_address = testerchain.etherbase_account
    yield testerchain
    testerchain.disconnect()
def test_approve_transfer(agent, token_economics):
    testerchain = agent.blockchain
    deployer, someone, *everybody_else = testerchain.client.accounts

    # Mock Powerup consumption
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=someone)

    # Approve
    receipt = agent.approve_transfer(
        amount=token_economics.minimum_allowed_locked,
        target_address=agent.contract_address,
        sender_address=someone)

    assert receipt['status'] == 1, "Transaction Rejected"
    assert receipt['logs'][0]['address'] == agent.contract_address
def test_transfer(agent, token_economics):
    testerchain = agent.blockchain
    origin, someone, *everybody_else = testerchain.client.accounts

    # Mock Powerup consumption (Deployer)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=origin)

    old_balance = agent.get_balance(someone)
    receipt = agent.transfer(amount=token_economics.minimum_allowed_locked,
                             target_address=someone,
                             sender_address=origin)

    assert receipt['status'] == 1, "Transaction Rejected"
    assert receipt['logs'][0]['address'] == agent.contract_address

    new_balance = agent.get_balance(someone)
    assert new_balance == old_balance + token_economics.minimum_allowed_locked
Example #17
0
def idle_staker(testerchain, agency):
    token_agent, _staking_agent, _policy_agent = agency

    idle_staker_account = testerchain.unassigned_accounts[-2]

    # Mock Powerup consumption (Deployer)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=testerchain.etherbase_account)

    token_airdrop(origin=testerchain.etherbase_account,
                  addresses=[idle_staker_account],
                  token_agent=token_agent,
                  amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)

    # Prepare idle staker
    idle_staker = Staker(is_me=True,
                         checksum_address=idle_staker_account,
                         blockchain=testerchain)
    yield idle_staker
def test_withdraw_tokens(testerchain, agent, agency, allocation_value):
    token_agent, staking_agent, policy_agent = agency
    deployer_address, beneficiary_address, *everybody_else = testerchain.client.accounts

    # Mock Powerup consumption (Beneficiary)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=agent.beneficiary)

    assert token_agent.get_balance(
        address=agent.contract_address) == agent.unvested_tokens
    with pytest.raises((TransactionFailed, ValueError)):
        agent.withdraw_tokens(value=allocation_value)
    testerchain.time_travel(seconds=TEST_DURATION)

    txhash = agent.withdraw_tokens(value=allocation_value)
    assert txhash  # TODO
    assert token_agent.get_balance(address=agent.contract_address) == 0
    assert token_agent.get_balance(
        address=beneficiary_address) == allocation_value
def test_create_policy(testerchain, agency, token_economics):
    token_agent, staking_agent, policy_agent = agency
    agent = policy_agent

    # Mock Powerup consumption
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=testerchain.alice_account)

    policy_id = os.urandom(16)
    node_addresses = list(staking_agent.sample(quantity=3, duration=1))
    receipt = agent.create_policy(policy_id=policy_id,
                                  author_address=testerchain.alice_account,
                                  value=token_economics.minimum_allowed_locked,
                                  periods=10,
                                  initial_reward=20,
                                  node_addresses=node_addresses)

    assert receipt['status'] == 1, "Transaction Rejected"
    assert receipt['logs'][0]['address'] == agent.contract_address
def agent(testerchain, proxy_deployer, allocation_value) -> UserEscrowAgent:
    deployer_address, beneficiary_address, *everybody_else = testerchain.client.accounts

    # Mock Powerup consumption (Deployer)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=deployer_address)

    # Escrow
    escrow_deployer = UserEscrowDeployer(
        deployer_address=deployer_address,
        blockchain=testerchain,
        allocation_registry=TEST_ALLOCATION_REGISTRY)

    _txhash = escrow_deployer.deploy()

    escrow_deployer.initial_deposit(value=allocation_value,
                                    duration=TEST_DURATION)
    assert escrow_deployer.contract.functions.getLockedTokens().call(
    ) == allocation_value
    escrow_deployer.assign_beneficiary(beneficiary_address=beneficiary_address)
    escrow_deployer.enroll_principal_contract()
    assert escrow_deployer.contract.functions.getLockedTokens().call(
    ) == allocation_value
    _agent = escrow_deployer.make_agent()

    _direct_agent = UserEscrowAgent(
        blockchain=testerchain,
        allocation_registry=TEST_ALLOCATION_REGISTRY,
        beneficiary=beneficiary_address)

    assert _direct_agent == _agent
    assert _direct_agent.contract.abi == _agent.contract.abi
    assert _direct_agent.contract.address == _agent.contract.address
    assert _agent.principal_contract.address == escrow_deployer.contract.address
    assert _agent.principal_contract.abi == escrow_deployer.contract.abi
    assert _direct_agent.contract.abi == escrow_deployer.contract.abi
    assert _direct_agent.contract.address == escrow_deployer.contract.address

    yield _agent
    TEST_ALLOCATION_REGISTRY.clear()
def test_character_blockchain_power(testerchain):
    eth_address = testerchain.interface.w3.eth.accounts[0]
    sig_privkey = testerchain.interface._providers[0].ethereum_tester.backend.\
                  _key_lookup[eth_utils.to_canonical_address(eth_address)]
    sig_pubkey = sig_privkey.public_key

    signer = Character(is_me=True, checksum_address=eth_address)
    signer._crypto_power.consume_power_up(
        BlockchainPower(testerchain, eth_address))

    # Due to testing backend, the account is already unlocked.
    power = signer._crypto_power.power_ups(BlockchainPower)
    power.is_unlocked = True
    #power.unlock_account('this-is-not-a-secure-password')

    data_to_sign = b'What does Ursula look like?!?'
    sig = power.sign_message(data_to_sign)

    is_verified = power.verify_message(eth_address, sig_pubkey.to_bytes(),
                                       data_to_sign, sig)
    assert is_verified == True

    # Test a bad message:
    with pytest.raises(PowerUpError):
        power.verify_message(eth_address, sig_pubkey.to_bytes(),
                             data_to_sign + b'bad', sig)

    # Test a bad address/pubkey pair
    with pytest.raises(ValueError):
        power.verify_message(testerchain.interface.w3.eth.accounts[1],
                             sig_pubkey.to_bytes(), data_to_sign, sig)

    # Test a signature without unlocking the account
    power.is_unlocked = False
    with pytest.raises(PowerUpError):
        power.sign_message(b'test')

    # Test lockAccount call
    del (power)
def test_invalid_workers_tolerance(testerchain, blockchain_ursulas, agency,
                                   idle_staker, token_economics,
                                   ursula_decentralized_test_config):
    #
    # Setup
    #
    lonely_blockchain_learner, blockchain_teacher, unsigned, *the_others = list(
        blockchain_ursulas)
    _, staking_agent, _ = agency

    warnings = []

    def warning_trapper(event):
        if event['log_level'] == LogLevel.warn:
            warnings.append(event)

    # We start with an "idle_staker" (i.e., no tokens in StakingEscrow)
    assert 0 == staking_agent.owned_tokens(idle_staker.checksum_address)

    # Now let's create an active worker for this staker.
    # First, stake something (e.g. the bare minimum)
    amount = token_economics.minimum_allowed_locked
    periods = token_economics.minimum_locked_periods

    # Mock Powerup consumption (Staker)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=idle_staker.checksum_address)

    idle_staker.initialize_stake(amount=amount, lock_periods=periods)

    # Stake starts next period (or else signature validation will fail)
    testerchain.time_travel(periods=1)
    idle_staker.stake_tracker.refresh()

    # We create an active worker node for this staker
    worker = make_ursula_for_staker(
        staker=idle_staker,
        worker_address=testerchain.unassigned_accounts[-1],
        ursula_config=ursula_decentralized_test_config,
        blockchain=testerchain,
        confirm_activity=True,
        ursulas_to_learn_about=None)

    # Since we confirmed activity, we need to advance one period
    testerchain.time_travel(periods=1)

    # The worker is valid and can be verified (even with the force option)
    worker.verify_node(force=True,
                       network_middleware=MockRestMiddleware(),
                       certificate_filepath="quietorl")
    # In particular, we know that it's bonded to a staker who is really staking.
    assert worker._worker_is_bonded_to_staker()
    assert worker._staker_is_really_staking()

    # OK. Now we learn about this worker.
    lonely_blockchain_learner.remember_node(worker)

    # The worker already confirmed one period before. Let's confirm the remaining 29.
    for i in range(29):
        worker.confirm_activity()
        testerchain.time_travel(periods=1)

    # The stake period has ended, and the staker wants her tokens back ("when lambo?").
    # She withdraws up to the last penny (well, last nunit, actually).

    # Mock Powerup consumption (Staker)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=idle_staker.checksum_address)
    idle_staker.mint()
    testerchain.time_travel(periods=1)
    i_want_it_all = staking_agent.owned_tokens(idle_staker.checksum_address)
    idle_staker.withdraw(i_want_it_all)

    # OK...so...the staker is not staking anymore ...
    assert 0 == staking_agent.owned_tokens(idle_staker.checksum_address)

    # ... but the worker node still is "verified" (since we're not forcing on-chain verification)
    worker.verify_node(network_middleware=MockRestMiddleware(),
                       certificate_filepath="quietorl")

    # If we force, on-chain verification, the worker is of course not verified
    with pytest.raises(worker.NotStaking):
        worker.verify_node(force=True,
                           network_middleware=MockRestMiddleware(),
                           certificate_filepath="quietorl")

    # Let's learn from this invalid node
    lonely_blockchain_learner._current_teacher_node = worker
    globalLogPublisher.addObserver(warning_trapper)
    lonely_blockchain_learner.learn_from_teacher_node()
    # lonely_blockchain_learner.remember_node(worker)  # The same problem occurs if we directly try to remember this node
    globalLogPublisher.removeObserver(warning_trapper)

    # TODO: What should we really check here? (#1075)
    assert len(warnings) == 1
    warning = warnings[-1]['log_format']
    assert str(worker) in warning
    assert "no active stakes" in warning  # TODO: Cleanup logging templates
    assert worker not in lonely_blockchain_learner.known_nodes
Example #23
0
    def __init__(self,
                 db_filepath: str,
                 rest_host: str,
                 rest_port: int,
                 crash_on_error: bool = False,
                 economics: TokenEconomics = None,
                 distribute_ether: bool = True,
                 *args,
                 **kwargs):

        # Character
        super().__init__(*args, **kwargs)
        self.log = Logger(f"felix-{self.checksum_address[-6::]}")

        # Network
        self.rest_port = rest_port
        self.rest_host = rest_host
        self.rest_app = NOT_RUNNING
        self.crash_on_error = crash_on_error

        # Database
        self.db_filepath = db_filepath
        self.db = NO_DATABASE_AVAILABLE
        self.db_engine = create_engine(f'sqlite:///{self.db_filepath}',
                                       convert_unicode=True)

        # Blockchain
        blockchain_power = BlockchainPower(blockchain=self.blockchain,
                                           account=self.checksum_address)
        self._crypto_power.consume_power_up(blockchain_power)
        # blockchain_power.unlock_account(password=None)  # TODO: TransactingPower

        self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
        self.reserved_addresses = [
            self.checksum_address, BlockchainInterface.NULL_ADDRESS
        ]

        # Update reserved addresses with deployed contracts
        existing_entries = list(self.blockchain.registry.enrolled_addresses)
        self.reserved_addresses.extend(existing_entries)

        # Distribution
        self.__distributed = 0  # Track NU Output
        self.__airdrop = 0  # Track Batch
        self.__disbursement = 0  # Track Quantity
        self._distribution_task = LoopingCall(f=self.airdrop_tokens)
        self._distribution_task.clock = self._CLOCK
        self.start_time = NOT_RUNNING

        if not economics:
            economics = TokenEconomics()
        self.economics = economics

        self.MAXIMUM_DISBURSEMENT = economics.maximum_allowed_locked
        self.INITIAL_DISBURSEMENT = economics.minimum_allowed_locked

        # Optionally send ether with each token transaction
        self.distribute_ether = distribute_ether

        # Banner
        self.log.info(FELIX_BANNER.format(self.checksum_address))
Example #24
0
def escrow(testerchain):
    # Mock Powerup consumption (Deployer)
    testerchain.transacting_power = BlockchainPower(
        blockchain=testerchain, account=testerchain.etherbase_account)
    escrow, _ = testerchain.deploy_contract('StakingEscrowForAdjudicatorMock')
    return escrow
def test_adjudicator_slashes(agency, testerchain, mock_ursula_reencrypts,
                             token_economics, slashing_economics):

    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 = BlockchainPower(
        blockchain=testerchain, account=testerchain.etherbase_account)

    # 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 = BlockchainPower(blockchain=testerchain,
                                                    account=staker_account)

    # Deposit: The staker deposits tokens in the StakingEscrow contract.
    staker = Staker(checksum_address=staker_account,
                    is_me=True,
                    blockchain=testerchain)
    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()
    bob_account = testerchain.bob_account
    bobby = NucypherTokenActor(blockchain=testerchain,
                               checksum_address=bob_account)
    ursula = mock_ursula(testerchain, worker_account)

    # 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 = BlockchainPower(blockchain=testerchain,
                                                    account=bob_account)
    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 == slashing_economics.base_penalty / slashing_economics.reward_coefficient
    assert staker.locked_tokens(periods=1) < locked_tokens
Example #26
0
    def __init__(
            self,

            # Ursula
            rest_host: str,
            rest_port: int,
            certificate: Certificate = None,
            certificate_filepath: str = None,
            tls_private_key=None,  # TODO: Derive from keyring
            db_name: str = None,
            db_filepath: str = None,
            is_me: bool = True,
            interface_signature=None,
            timestamp=None,

            # Blockchain
            miner_agent=None,
            checksum_address: str = None,

            # Character
            passphrase: str = None,
            abort_on_learning_error: bool = False,
            federated_only: bool = False,
            start_learning_now: bool = None,
            crypto_power=None,
            tls_curve: EllipticCurve = None,
            known_nodes: Iterable = None,
            **character_kwargs) -> None:

        #
        # Character
        #
        self._work_orders = list()
        Character.__init__(self,
                           is_me=is_me,
                           checksum_address=checksum_address,
                           start_learning_now=start_learning_now,
                           federated_only=federated_only,
                           crypto_power=crypto_power,
                           abort_on_learning_error=abort_on_learning_error,
                           known_nodes=known_nodes,
                           **character_kwargs)

        #
        # Self-Ursula
        #
        if is_me is True:  # TODO: 340
            self._stored_treasure_maps = dict()

            if not federated_only:
                Miner.__init__(self,
                               is_me=is_me,
                               miner_agent=miner_agent,
                               checksum_address=checksum_address)

                # Access staking node via node's transacting keys
                blockchain_power = BlockchainPower(
                    blockchain=self.blockchain,
                    account=self.checksum_public_address)
                self._crypto_power.consume_power_up(blockchain_power)

                # Use blockchain power to substantiate stamp
                self.substantiate_stamp(passphrase=passphrase)

        #
        # ProxyRESTServer and TLSHostingPower
        #
        if not crypto_power or (TLSHostingPower
                                not in crypto_power._power_ups):
            # TODO: Maybe we want _power_ups to be public after all?
            # We'll hook all the TLS stuff up unless the crypto_power was already passed.

            #
            # Self-Ursula
            #
            if is_me:
                self.suspicious_activities_witnessed = {
                    'vladimirs': [],
                    'bad_treasure_maps': []
                }

                #
                # REST Server
                #
                rest_routes = ProxyRESTRoutes(
                    db_name=db_name,
                    db_filepath=db_filepath,
                    network_middleware=self.network_middleware,
                    federated_only=self.federated_only,  # TODO: 466
                    treasure_map_tracker=self.treasure_maps,
                    node_tracker=self.known_nodes,
                    node_bytes_caster=self.__bytes__,
                    work_order_tracker=self._work_orders,
                    node_recorder=self.remember_node,
                    stamp=self.stamp,
                    verifier=self.verify_from,
                    suspicious_activity_tracker=self.
                    suspicious_activities_witnessed,
                    certificate_dir=self.known_certificates_dir,
                )

                rest_server = ProxyRESTServer(
                    rest_host=rest_host,
                    rest_port=rest_port,
                    routes=rest_routes,
                )
                self.rest_url = rest_server.rest_url
                self.datastore = rest_routes.datastore  # TODO: Maybe organize this better?

                #
                # TLSHostingPower
                #
                tls_hosting_keypair = HostingKeypair(
                    curve=tls_curve,
                    host=rest_host,
                    certificate=certificate,
                    certificate_filepath=certificate_filepath,
                    private_key=tls_private_key)

                tls_hosting_power = TLSHostingPower(
                    rest_server=rest_server, keypair=tls_hosting_keypair)

            #
            # Stranger-Ursula
            #
            else:

                # REST Server
                # Unless the caller passed a crypto power,
                # we'll make our own TLSHostingPower for this stranger.
                rest_server = ProxyRESTServer(rest_host=rest_host,
                                              rest_port=rest_port)

                #
                # TLSHostingPower
                #
                if certificate or certificate_filepath:
                    tls_hosting_power = TLSHostingPower(
                        rest_server=rest_server,
                        certificate_filepath=certificate_filepath,
                        certificate=certificate)
                else:
                    tls_hosting_keypair = HostingKeypair(
                        curve=tls_curve,
                        host=rest_host,
                        certificate_filepath=certificate_filepath)
                    tls_hosting_power = TLSHostingPower(
                        rest_server=rest_server, keypair=tls_hosting_keypair)

            # OK - Now we have a ProxyRestServer and a TLSHostingPower for some Ursula
            self._crypto_power.consume_power_up(tls_hosting_power)  # Consume!

        else:
            self.log.info(
                "Not adhering rest_server; Using the one on crypto_power.")

        #
        # Verifiable Node
        #
        certificate_filepath = self._crypto_power.power_ups(
            TLSHostingPower).keypair.certificate_filepath
        certificate = self._crypto_power.power_ups(
            TLSHostingPower).keypair.certificate
        VerifiableNode.__init__(self,
                                certificate=certificate,
                                certificate_filepath=certificate_filepath,
                                interface_signature=interface_signature,
                                timestamp=timestamp)

        #
        # Logging
        #
        if is_me:
            message = "Initialized Self {} | {}".format(
                self.__class__.__name__, self.checksum_public_address)
            self.log.info(message)
        else:
            message = "Initialized Stranger {} | {}".format(
                self.__class__.__name__, self.checksum_public_address)
            self.log.debug(message)
def test_deposit_and_withdraw_as_staker(testerchain, agent, agency,
                                        allocation_value, token_economics):
    token_agent, staking_agent, policy_agent = agency

    assert staking_agent.get_locked_tokens(
        staker_address=agent.contract_address) == 0
    assert staking_agent.get_locked_tokens(
        staker_address=agent.contract_address, periods=1) == 0
    assert agent.unvested_tokens == allocation_value
    assert token_agent.get_balance(
        address=agent.contract_address) == allocation_value

    # Mock Powerup consumption (Beneficiary)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=agent.beneficiary)

    # Move the tokens to the StakingEscrow
    receipt = agent.deposit_as_staker(
        value=token_economics.minimum_allowed_locked,
        periods=token_economics.minimum_locked_periods)
    assert receipt  # TODO

    # User sets a worker in StakingEscrow via UserEscrow
    worker = testerchain.ursula_account(0)
    _receipt = agent.set_worker(worker_address=worker)

    assert token_agent.get_balance(
        address=agent.contract_address
    ) == allocation_value - token_economics.minimum_allowed_locked
    assert agent.unvested_tokens == allocation_value
    assert staking_agent.get_locked_tokens(
        staker_address=agent.contract_address) == 0
    assert staking_agent.get_locked_tokens(
        staker_address=agent.contract_address,
        periods=1) == token_economics.minimum_allowed_locked
    assert staking_agent.get_locked_tokens(
        staker_address=agent.contract_address,
        periods=token_economics.minimum_locked_periods
    ) == token_economics.minimum_allowed_locked
    assert staking_agent.get_locked_tokens(
        staker_address=agent.contract_address,
        periods=token_economics.minimum_locked_periods + 1) == 0

    # Mock Powerup consumption (Beneficiary-Worker)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=worker)

    for _ in range(token_economics.minimum_locked_periods):
        staking_agent.confirm_activity(worker_address=worker)
        testerchain.time_travel(periods=1)
    testerchain.time_travel(periods=1)

    # Mock Powerup consumption (Beneficiary)
    testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
                                                    account=agent.beneficiary)

    agent.mint()

    assert staking_agent.get_locked_tokens(
        staker_address=agent.contract_address) == 0
    assert token_agent.get_balance(
        address=agent.contract_address
    ) == allocation_value - token_economics.minimum_allowed_locked
    txhash = agent.withdraw_as_staker(
        value=token_economics.minimum_allowed_locked)
    assert txhash  # TODO
    assert token_agent.get_balance(
        address=agent.contract_address) == allocation_value

    # Release worker
    _txhash = agent.set_worker(worker_address=BlockchainInterface.NULL_ADDRESS)

    txhash = agent.withdraw_as_staker(value=staking_agent.owned_tokens(
        address=agent.contract_address))
    assert txhash
    assert token_agent.get_balance(
        address=agent.contract_address) > allocation_value
Example #28
0
    def __init__(self,

                 # Ursula
                 rest_host: str,
                 rest_port: int,
                 certificate: Certificate = None,  # TODO: from_certificate classmethod instead, use only filepath..?
                 certificate_filepath: str = None,
                 db_name: str = None,  # TODO: deprecate db_name, use only filepath.?
                 db_filepath: str = None,
                 is_me: bool = True,
                 interface_signature=None,

                 # Blockchain
                 miner_agent=None,
                 checksum_address: str = None,
                 registry_filepath: str = None,

                 # Character
                 abort_on_learning_error: bool = False,
                 federated_only: bool = False,
                 start_learning_now: bool = None,
                 crypto_power=None,
                 tls_curve: EllipticCurve = None,
                 tls_private_key=None,  # TODO: config here. #361
                 known_nodes: Iterable = None,

                 **character_kwargs
                 ) -> None:

        self._work_orders = []

        Character.__init__(self,
                           is_me=is_me,
                           checksum_address=checksum_address,
                           start_learning_now=start_learning_now,
                           federated_only=federated_only,
                           crypto_power=crypto_power,
                           abort_on_learning_error=abort_on_learning_error,
                           known_nodes=known_nodes,
                           **character_kwargs)

        if not federated_only:
            Miner.__init__(self,
                           is_me=is_me,
                           miner_agent=miner_agent,
                           checksum_address=checksum_address,
                           registry_filepath=registry_filepath)

            blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_public_address)
            self._crypto_power.consume_power_up(blockchain_power)

        if is_me is True:
            # TODO: 340
            self._stored_treasure_maps = {}
            if not federated_only:
                self.substantiate_stamp()

        if not crypto_power or (TLSHostingPower not in crypto_power._power_ups):
            # TODO: Maybe we want _power_ups to be public after all?
            # We'll hook all the TLS stuff up unless the crypto_power was already passed.

            if is_me:
                self.suspicious_activities_witnessed = {'vladimirs': [], 'bad_treasure_maps': []}

                rest_routes = ProxyRESTRoutes(
                    db_name=db_name,
                    db_filepath=db_filepath,
                    network_middleware=self.network_middleware,
                    federated_only=self.federated_only,
                    treasure_map_tracker=self.treasure_maps,
                    node_tracker=self.known_nodes,
                    node_bytes_caster=self.__bytes__,
                    work_order_tracker=self._work_orders,
                    node_recorder=self.remember_node,
                    stamp=self.stamp,
                    verifier=self.verify_from,
                    suspicious_activity_tracker=self.suspicious_activities_witnessed,
                    certificate_dir=self.known_certificates_dir,
                )

                rest_server = ProxyRESTServer(
                    rest_host=rest_host,
                    rest_port=rest_port,
                    routes=rest_routes,
                )
                self.rest_url = rest_server.rest_url
                self.datastore = rest_routes.datastore  # TODO: Maybe organize this better?

                tls_hosting_keypair = HostingKeypair(
                    common_name=self.checksum_public_address,
                    private_key=tls_private_key,
                    curve=tls_curve,
                    host=rest_host,
                    certificate=certificate,
                    certificate_dir=self.known_certificates_dir)

                tls_hosting_power = TLSHostingPower(rest_server=rest_server,
                                                    keypair=tls_hosting_keypair)

            else:
                # Unless the caller passed a crypto power, we'll make our own TLSHostingPower for this stranger.
                rest_server = ProxyRESTServer(
                    rest_host=rest_host,
                    rest_port=rest_port
                )
                if certificate or certificate_filepath:
                    tls_hosting_power = TLSHostingPower(rest_server=rest_server,
                                                        certificate_filepath=certificate_filepath,
                                                        certificate=certificate,
                                                        certificate_dir=self.known_certificates_dir,
                                                        common_name=self.checksum_public_address,)
                else:
                    tls_hosting_keypair = HostingKeypair(
                        common_name=self.checksum_public_address,
                        curve=tls_curve,
                        host=rest_host,
                        certificate_filepath=certificate_filepath,
                        certificate_dir=self.known_certificates_dir)

                    tls_hosting_power = TLSHostingPower(rest_server=rest_server,
                                                        keypair=tls_hosting_keypair)

            self._crypto_power.consume_power_up(tls_hosting_power)  # Make this work for not me for certificate to work

        else:
            self.log.info("Not adhering rest_server; we'll use the one on crypto_power..")

        certificate_filepath = self._crypto_power.power_ups(TLSHostingPower).keypair.certificate_filepath
        certificate = self._crypto_power.power_ups(TLSHostingPower).keypair.certificate
        # VerifiableNode.from_tls_hosting_power(tls_hosting_power=self._crypto_power.power_ups(TLSHostingPower))  # TODO: use classmethod
        VerifiableNode.__init__(self,
                                certificate=certificate,
                                certificate_filepath=certificate_filepath,
                                interface_signature=interface_signature)

        if is_me:
            message = "Initialized Self {} | {}".format(self.__class__.__name__, self.checksum_public_address)
            self.log.info(message)
        else:
            message = "Initialized Stranger {} | {}".format(self.__class__.__name__, self.checksum_public_address)
            self.log.debug(message)
Example #29
0
    def __init__(
            self,

            # Ursula
            rest_host: str,
            rest_port: int,
            domains: Set = (
                GLOBAL_DOMAIN,
            ),  # For now, serving and learning domains will be the same.
            certificate: Certificate = None,
            certificate_filepath: str = None,
            db_filepath: str = None,
            is_me: bool = True,
            interface_signature=None,
            timestamp=None,

            # Blockchain
            identity_evidence: bytes = constants.NOT_SIGNED,
            checksum_public_address: str = None,

            # Character
            password: str = None,
            abort_on_learning_error: bool = False,
            federated_only: bool = False,
            start_learning_now: bool = None,
            crypto_power=None,
            tls_curve: EllipticCurve = None,
            known_nodes: Iterable = None,
            **character_kwargs) -> None:

        #
        # Character
        #
        self._work_orders = list()
        Character.__init__(self,
                           is_me=is_me,
                           checksum_public_address=checksum_public_address,
                           start_learning_now=start_learning_now,
                           federated_only=federated_only,
                           crypto_power=crypto_power,
                           abort_on_learning_error=abort_on_learning_error,
                           known_nodes=known_nodes,
                           domains=domains,
                           **character_kwargs)

        #
        # Self-Ursula
        #
        if is_me is True:  # TODO: 340
            self._stored_treasure_maps = dict()

            #
            # Staking Ursula
            #
            if not federated_only:
                Miner.__init__(self,
                               is_me=is_me,
                               checksum_address=checksum_public_address)

                # Access staking node via node's transacting keys  TODO: Better handle ephemeral staking self ursula
                blockchain_power = BlockchainPower(
                    blockchain=self.blockchain,
                    account=self.checksum_public_address)
                self._crypto_power.consume_power_up(blockchain_power)

                # Use blockchain power to substantiate stamp, instead of signing key
                self.substantiate_stamp(
                    password=password)  # TODO: Derive from keyring

        #
        # ProxyRESTServer and TLSHostingPower # TODO: Maybe we want _power_ups to be public after all?
        #
        if not crypto_power or (TLSHostingPower
                                not in crypto_power._power_ups):

            #
            # Ephemeral Self-Ursula
            #
            if is_me:
                self.suspicious_activities_witnessed = {
                    'vladimirs': [],
                    'bad_treasure_maps': []
                }

                #
                # REST Server (Ephemeral Self-Ursula)
                #
                rest_app, datastore = make_rest_app(
                    db_filepath=db_filepath,
                    network_middleware=self.network_middleware,
                    federated_only=self.federated_only,  # TODO: 466
                    treasure_map_tracker=self.treasure_maps,
                    node_tracker=self.known_nodes,
                    node_bytes_caster=self.__bytes__,
                    work_order_tracker=self._work_orders,
                    node_recorder=self.remember_node,
                    stamp=self.stamp,
                    verifier=self.verify_from,
                    suspicious_activity_tracker=self.
                    suspicious_activities_witnessed,
                    serving_domains=domains,
                )

                #
                # TLSHostingPower (Ephemeral Self-Ursula)
                #
                tls_hosting_keypair = HostingKeypair(
                    curve=tls_curve,
                    host=rest_host,
                    checksum_public_address=self.checksum_public_address)
                tls_hosting_power = TLSHostingPower(
                    keypair=tls_hosting_keypair, host=rest_host)
                self.rest_server = ProxyRESTServer(
                    rest_host=rest_host,
                    rest_port=rest_port,
                    rest_app=rest_app,
                    datastore=datastore,
                    hosting_power=tls_hosting_power)

            #
            # Stranger-Ursula
            #
            else:

                # TLSHostingPower
                if certificate or certificate_filepath:
                    tls_hosting_power = TLSHostingPower(
                        host=rest_host,
                        public_certificate_filepath=certificate_filepath,
                        public_certificate=certificate)
                else:
                    tls_hosting_keypair = HostingKeypair(
                        curve=tls_curve,
                        host=rest_host,
                        generate_certificate=False)
                    tls_hosting_power = TLSHostingPower(
                        host=rest_host, keypair=tls_hosting_keypair)

                # REST Server
                # Unless the caller passed a crypto power we'll make our own TLSHostingPower for this stranger.
                self.rest_server = ProxyRESTServer(
                    rest_host=rest_host,
                    rest_port=rest_port,
                    hosting_power=tls_hosting_power)

            #
            # OK - Now we have a ProxyRestServer and a TLSHostingPower for some Ursula
            #
            self._crypto_power.consume_power_up(tls_hosting_power)  # Consume!

        #
        # Verifiable Node
        #
        certificate_filepath = self._crypto_power.power_ups(
            TLSHostingPower).keypair.certificate_filepath
        certificate = self._crypto_power.power_ups(
            TLSHostingPower).keypair.certificate
        Teacher.__init__(
            self,
            domains=domains,
            certificate=certificate,
            certificate_filepath=certificate_filepath,
            interface_signature=interface_signature,
            timestamp=timestamp,
            identity_evidence=identity_evidence,
            substantiate_immediately=is_me and not federated_only,
        )

        #
        # Logging / Updating
        #
        if is_me:
            self.known_nodes.record_fleet_state(
                additional_nodes_to_track=[self])
            message = "THIS IS YOU: {}: {}".format(self.__class__.__name__,
                                                   self)
            self.log.info(message)
        else:
            message = "Initialized Stranger {} | {}".format(
                self.__class__.__name__, self)
            self.log.debug(message)
Example #30
0
def deploy(click_config, action, poa, provider_uri, geth, enode,
           deployer_address, contract_name, allocation_infile,
           allocation_outfile, registry_infile, registry_outfile, no_compile,
           amount, recipient_address, config_root, sync, force):
    """Manage contract and registry deployment"""

    ETH_NODE = None

    #
    # Validate
    #

    # Ensure config root exists, because we need a default place to put output files.
    config_root = config_root or DEFAULT_CONFIG_ROOT
    if not os.path.exists(config_root):
        os.makedirs(config_root)

    #
    # Connect to Blockchain
    #

    if geth:
        # Spawn geth child process
        ETH_NODE = NuCypherGethDevnetProcess(config_root=config_root)
        ETH_NODE.ensure_account_exists(password=click_config.get_password(
            confirm=True))
        ETH_NODE.start()  # TODO: Graceful shutdown
        provider_uri = ETH_NODE.provider_uri

    # Establish a contract registry from disk if specified
    registry, registry_filepath = None, (registry_outfile or registry_infile)
    if registry_filepath is not None:
        registry = EthereumContractRegistry(
            registry_filepath=registry_filepath)

    # Deployment-tuned blockchain connection
    blockchain = BlockchainDeployerInterface(provider_uri=provider_uri,
                                             poa=poa,
                                             registry=registry,
                                             compiler=SolidityCompiler(),
                                             fetch_registry=False,
                                             sync_now=sync)

    #
    # Deployment Actor
    #

    if not deployer_address:
        for index, address in enumerate(blockchain.client.accounts):
            click.secho(f"{index} --- {address}")
        choices = click.IntRange(0, len(blockchain.client.accounts))
        deployer_address_index = click.prompt("Select deployer address",
                                              default=0,
                                              type=choices)
        deployer_address = blockchain.client.accounts[deployer_address_index]

    # Verify Address
    if not force:
        click.confirm("Selected {} - Continue?".format(deployer_address),
                      abort=True)

    # TODO: Integrate with Deployer Actor (Character)
    blockchain.transacting_power = BlockchainPower(blockchain=blockchain,
                                                   account=deployer_address)
    deployer = Deployer(blockchain=blockchain,
                        deployer_address=deployer_address)

    # Verify ETH Balance
    click.secho(f"\n\nDeployer ETH balance: {deployer.eth_balance}")
    if deployer.eth_balance == 0:
        click.secho("Deployer address has no ETH.", fg='red', bold=True)
        raise click.Abort()

    if not blockchain.client.is_local:
        # (~ dev mode; Assume accounts are already unlocked)
        password = click.prompt("Enter ETH node password", hide_input=True)
        blockchain.client.unlockAccount(deployer_address, password)

    # Add ETH Bootnode or Peer
    if enode:
        if geth:
            blockchain.w3.geth.admin.addPeer(enode)
            click.secho(f"Added ethereum peer {enode}")
        else:
            raise NotImplemented  # TODO: other backends

    #
    # Action switch
    #

    if action == 'upgrade':
        if not contract_name:
            raise click.BadArgumentUsage(
                message="--contract-name is required when using --upgrade")
        existing_secret = click.prompt(
            'Enter existing contract upgrade secret', hide_input=True)
        new_secret = click.prompt('Enter new contract upgrade secret',
                                  hide_input=True,
                                  confirmation_prompt=True)
        deployer.upgrade_contract(contract_name=contract_name,
                                  existing_plaintext_secret=existing_secret,
                                  new_plaintext_secret=new_secret)

    elif action == 'rollback':
        existing_secret = click.prompt(
            'Enter existing contract upgrade secret', hide_input=True)
        new_secret = click.prompt('Enter new contract upgrade secret',
                                  hide_input=True,
                                  confirmation_prompt=True)
        deployer.rollback_contract(contract_name=contract_name,
                                   existing_plaintext_secret=existing_secret,
                                   new_plaintext_secret=new_secret)

    elif action == "contracts":

        registry_filepath = deployer.blockchain.registry.filepath
        if os.path.isfile(registry_filepath):
            click.secho(
                f"\nThere is an existing contract registry at {registry_filepath}.\n"
                f"Did you mean 'nucypher-deploy upgrade'?\n",
                fg='yellow')
            click.confirm(
                "Optionally, destroy existing local registry and continue?",
                abort=True)
            click.confirm(
                f"Confirm deletion of contract registry '{registry_filepath}'?",
                abort=True)
            os.remove(registry_filepath)

        #
        # Deploy Single Contract
        #

        if contract_name:
            # TODO: Handle secret collection for single contract deployment

            try:
                deployer_func = deployer.deployers[contract_name]
            except KeyError:
                message = f"No such contract {contract_name}. Available contracts are {deployer.deployers.keys()}"
                click.secho(message, fg='red', bold=True)
                raise click.Abort()
            else:
                # Deploy single contract
                _txs, _agent = deployer_func()

            # TODO: Painting for single contract deployment
            if ETH_NODE:
                ETH_NODE.stop()
            return

        #
        # Stage Deployment
        #

        # Track tx hashes, and new agents
        __deployment_transactions = dict()
        __deployment_agents = dict()

        secrets = click_config.collect_deployment_secrets()
        click.clear()
        click.secho(NU_BANNER)

        w3 = deployer.blockchain.w3
        click.secho(f"Current Time ........ {maya.now().iso8601()}")
        click.secho(
            f"Web3 Provider ....... {deployer.blockchain.provider_uri}")
        click.secho(
            f"Block ............... {deployer.blockchain.client.block_number}")
        click.secho(
            f"Gas Price ........... {deployer.blockchain.client.gas_price}")

        click.secho(f"Deployer Address .... {deployer.checksum_address}")
        click.secho(f"ETH ................. {deployer.eth_balance}")
        click.secho(
            f"Chain ID ............ {deployer.blockchain.client.chain_id}")
        click.secho(
            f"Chain Name .......... {deployer.blockchain.client.chain_name}")

        # Ask - Last chance to gracefully abort
        if not force:
            click.secho(
                "\nDeployment successfully staged. Take a deep breath. \n",
                fg='green')
            if click.prompt("Type 'DEPLOY' to continue") != 'DEPLOY':
                raise click.Abort()

        # Delay - Last chance to crash and abort
        click.secho(f"Starting deployment in 3 seconds...", fg='red')
        time.sleep(1)
        click.secho(f"2...", fg='yellow')
        time.sleep(1)
        click.secho(f"1...", fg='green')
        time.sleep(1)
        click.secho(f"Deploying...", bold=True)

        #
        # DEPLOY < -------
        #

        txhashes, deployers = deployer.deploy_network_contracts(
            staker_secret=secrets.staker_secret,
            policy_secret=secrets.policy_secret,
            adjudicator_secret=secrets.adjudicator_secret,
            user_escrow_proxy_secret=secrets.escrow_proxy_secret)

        # Success
        __deployment_transactions.update(txhashes)

        #
        # Paint
        #

        total_gas_used = 0  # TODO: may be faulty
        for contract_name, transactions in __deployment_transactions.items():

            # Paint heading
            heading = '\n{} ({})'.format(
                contract_name, deployers[contract_name].contract_address)
            click.secho(heading, bold=True)
            click.echo('*' * (42 + 3 + len(contract_name)))

            for tx_name, txhash in transactions.items():

                # Wait for inclusion in the blockchain
                receipt = deployer.blockchain.w3.eth.waitForTransactionReceipt(
                    txhash)
                click.secho("OK", fg='green', nl=False, bold=True)

                # Accumulate gas
                total_gas_used += int(receipt['gasUsed'])

                # Paint
                click.secho(" | {}".format(tx_name), fg='yellow', nl=False)
                click.secho(" | {}".format(txhash.hex()),
                            fg='yellow',
                            nl=False)
                click.secho(" ({} gas)".format(receipt['cumulativeGasUsed']))
                click.secho("Block #{} | {}\n".format(
                    receipt['blockNumber'], receipt['blockHash'].hex()))

        # Paint outfile paths
        click.secho(
            "Cumulative Gas Consumption: {} gas".format(total_gas_used),
            bold=True,
            fg='blue')
        registry_outfile = deployer.blockchain.registry.filepath
        click.secho('Generated registry {}'.format(registry_outfile),
                    bold=True,
                    fg='blue')

        # Save transaction metadata
        receipts_filepath = deployer.save_deployment_receipts(
            transactions=__deployment_transactions)
        click.secho(f"Saved deployment receipts to {receipts_filepath}",
                    fg='blue',
                    bold=True)

    elif action == "allocations":
        if not allocation_infile:
            allocation_infile = click.prompt("Enter allocation data filepath")
        click.confirm("Continue deploying and allocating?", abort=True)
        deployer.deploy_beneficiaries_from_file(
            allocation_data_filepath=allocation_infile,
            allocation_outfile=allocation_outfile)

    elif action == "transfer":
        token_agent = NucypherTokenAgent(blockchain=blockchain)
        click.confirm(
            f"Transfer {amount} from {token_agent.contract_address} to {recipient_address}?",
            abort=True)
        txhash = token_agent.transfer(
            amount=amount,
            sender_address=token_agent.contract_address,
            target_address=recipient_address)
        click.secho(f"OK | {txhash}")

    elif action == "destroy-registry":
        registry_filepath = deployer.blockchain.registry.filepath
        click.confirm(
            f"Are you absolutely sure you want to destroy the contract registry at {registry_filepath}?",
            abort=True)
        os.remove(registry_filepath)
        click.secho(f"Successfully destroyed {registry_filepath}", fg='red')

    else:
        raise click.BadArgumentUsage(message=f"Unknown action '{action}'")

    if ETH_NODE:
        ETH_NODE.stop()