Esempio n. 1
0
def blockchain_ursulas(three_agents, ursula_decentralized_test_config):
    token_agent, miner_agent, policy_agent = three_agents
    etherbase, alice, bob, *all_yall = token_agent.blockchain.interface.w3.eth.accounts

    ursula_addresses = all_yall[:NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK]

    token_airdrop(origin=etherbase,
                  addresses=ursula_addresses,
                  token_agent=token_agent,
                  amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)

    # Leave out the last Ursula for manual stake testing
    *all_but_the_last_ursula, the_last_ursula = ursula_addresses

    _ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
                                          ether_addresses=all_but_the_last_ursula,
                                          stake=True)

    # This one is not going to stake
    _non_staking_ursula = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
                                                     ether_addresses=[the_last_ursula],
                                                     stake=False)

    _ursulas.extend(_non_staking_ursula)
    token_agent.blockchain.time_travel(periods=1)
    yield _ursulas
Esempio n. 2
0
def blockchain_ursulas(three_agents, ursula_decentralized_test_config):
    token_agent, miner_agent, policy_agent = three_agents
    blockchain = token_agent.blockchain

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

    # Leave out the last Ursula for manual stake testing
    *all_but_the_last_ursula, the_last_ursula = blockchain.ursulas_accounts

    _ursulas = make_decentralized_ursulas(
        ursula_config=ursula_decentralized_test_config,
        ether_addresses=all_but_the_last_ursula,
        stake=True)

    # This one is not going to stake
    _non_staking_ursula = make_decentralized_ursulas(
        ursula_config=ursula_decentralized_test_config,
        ether_addresses=[the_last_ursula],
        stake=False)

    _ursulas.extend(_non_staking_ursula)
    blockchain.time_travel(periods=1)
    yield _ursulas
Esempio n. 3
0
def blockchain_ursulas(three_agents, ursula_decentralized_test_config):
    token_agent, _miner_agent, _policy_agent = three_agents
    blockchain = token_agent.blockchain

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

    # Leave out the last Ursula for manual stake testing
    *all_but_the_last_ursula, the_last_ursula = blockchain.ursulas_accounts

    _ursulas = make_decentralized_ursulas(
        ursula_config=ursula_decentralized_test_config,
        ether_addresses=all_but_the_last_ursula,
        stake=True)

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

    # Bootstrap the network
    for ursula_to_teach in _ursulas:
        for ursula_to_learn_about in _ursulas:
            ursula_to_teach.remember_node(ursula_to_learn_about)

    # TODO: #1035 - Move non-staking Ursulas to a new fixture
    # This one is not going to stake
    _non_staking_ursula = make_decentralized_ursulas(
        ursula_config=ursula_decentralized_test_config,
        ether_addresses=[the_last_ursula],
        stake=False)

    _ursulas.extend(_non_staking_ursula)
    yield _ursulas
Esempio n. 4
0
def miner(testerchain, three_agents):
    token_agent, miner_agent, policy_agent = three_agents
    origin, *everybody_else = testerchain.interface.w3.eth.accounts
    token_airdrop(token_agent,
                  origin=testerchain.etherbase_account,
                  addresses=everybody_else,
                  amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
    miner = Miner(checksum_address=everybody_else[0], is_me=True)
    return miner
Esempio n. 5
0
def staker(testerchain, agency):
    token_agent, staking_agent, policy_agent = agency
    origin, staker_account, *everybody_else = testerchain.client.accounts
    token_airdrop(token_agent=token_agent,
                  origin=testerchain.etherbase_account,
                  addresses=[staker_account],
                  amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
    staker = Staker(checksum_address=staker_account, is_me=True, blockchain=testerchain)
    return staker
def test_beneficiary_withdraws_tokens(testerchain, agent, agency,
                                      allocation_value,
                                      mock_transacting_power_activation,
                                      token_economics):
    token_agent, staking_agent, policy_agent = agency
    deployer_address, beneficiary_address, *everybody_else = testerchain.client.accounts

    contract_address = agent.contract_address
    assert token_agent.get_balance(
        address=contract_address
    ) == agent.unvested_tokens == agent.initial_locked_amount

    # Trying to withdraw the tokens now fails, obviously
    initial_amount = token_agent.get_balance(address=contract_address)
    with pytest.raises((TransactionFailed, ValueError)):
        agent.withdraw_tokens(value=initial_amount)

    # Let's deposit some of them (30% of initial amount)
    staked_amount = 3 * initial_amount // 10
    mock_transacting_power_activation(account=agent.beneficiary,
                                      password=INSECURE_DEVELOPMENT_PASSWORD)
    _receipt = agent.deposit_as_staker(
        amount=staked_amount,
        lock_periods=token_economics.minimum_locked_periods)

    # Trying to withdraw the remaining fails too:
    # The locked amount is equal to the initial deposit (100% of the tokens).
    # Since 30% are staked, the locked amount is reduced by that 30% when withdrawing,
    # which results in an effective lock of 70%. However, the contract also has 70%, which means that, effectively,
    # the beneficiary can only withdraw 0 tokens.
    assert agent.available_balance == 0
    with pytest.raises((TransactionFailed, ValueError)):
        agent.withdraw_tokens(value=initial_amount - staked_amount)
    agent.withdraw_tokens(value=0)

    # Now let's assume the contract has more tokens (e.g., coming from staking rewards).
    # The beneficiary should be able to collect this excess.
    mocked_rewards = NU.from_nunits(1000)
    token_airdrop(token_agent=token_agent,
                  amount=mocked_rewards,
                  origin=deployer_address,
                  addresses=[contract_address])
    assert agent.available_balance == mocked_rewards
    agent.withdraw_tokens(value=int(mocked_rewards))

    # Once the lock passes, the beneficiary can withdraw what's left
    testerchain.time_travel(seconds=TEST_LOCK_DURATION_IN_SECONDS)
    receipt = agent.withdraw_tokens(value=initial_amount - staked_amount)
    assert receipt['status'] == 1, "Transaction Rejected"
    assert token_agent.get_balance(address=contract_address) == 0
    assert token_agent.get_balance(
        address=beneficiary_address
    ) == initial_amount - staked_amount + mocked_rewards
Esempio n. 7
0
def funded_blockchain(testerchain, agency, token_economics, test_registry):
    # Who are ya'?
    deployer_address, *everyone_else, staking_participant = testerchain.client.accounts

    # Free ETH!!!
    testerchain.ether_airdrop(amount=DEVELOPMENT_ETH_AIRDROP_AMOUNT)

    # Free Tokens!!!
    token_airdrop(token_agent=NucypherTokenAgent(registry=test_registry),
                  origin=deployer_address,
                  addresses=everyone_else,
                  amount=token_economics.minimum_allowed_locked * 5)

    # HERE YOU GO
    yield testerchain, deployer_address
Esempio n. 8
0
def stakers(testerchain, agency, token_economics):
    token_agent, _staking_agent, _policy_agent = agency
    blockchain = token_agent.blockchain

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

    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
        staker.blockchain.transacting_power = TransactingPower(
            blockchain=blockchain,
            password=INSECURE_DEVELOPMENT_PASSWORD,
            account=account)
        staker.blockchain.transacting_power.activate()

        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 funded_blockchain(deployed_blockchain):

    # Who are ya'?
    blockchain, _deployer_address, registry = deployed_blockchain
    deployer_address, *everyone_else, staking_participant = blockchain.interface.w3.eth.accounts

    # Free ETH!!!
    blockchain.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT)

    # Free Tokens!!!
    token_airdrop(token_agent=NucypherTokenAgent(blockchain=blockchain),
                  origin=_deployer_address,
                  addresses=everyone_else,
                  amount=MIN_ALLOWED_LOCKED * 5)

    # HERE YOU GO
    yield blockchain, _deployer_address
Esempio n. 10
0
def funded_blockchain(deployed_blockchain, token_economics):

    # Who are ya'?
    blockchain, _deployer_address, registry = deployed_blockchain
    deployer_address, *everyone_else, staking_participant = blockchain.interface.w3.eth.accounts

    # Free ETH!!!
    blockchain.ether_airdrop(amount=DEVELOPMENT_ETH_AIRDROP_AMOUNT)

    # Free Tokens!!!
    token_airdrop(token_agent=NucypherTokenAgent(blockchain=blockchain),
                  origin=_deployer_address,
                  addresses=everyone_else,
                  amount=token_economics.minimum_allowed_locked * 5)

    # HERE YOU GO
    yield blockchain, _deployer_address
Esempio n. 11
0
def blockchain_ursulas(three_agents, ursula_decentralized_test_config):
    token_agent, miner_agent, policy_agent = three_agents
    etherbase, alice, bob, *all_yall = token_agent.blockchain.interface.w3.eth.accounts

    ursula_addresses = all_yall[:DEFAULT_NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK]

    token_airdrop(origin=etherbase,
                  addresses=ursula_addresses,
                  token_agent=token_agent,
                  amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)

    _ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
                                          ether_addresses=ursula_addresses,
                                          stake=True)

    token_agent.blockchain.time_travel(periods=1)
    yield _ursulas
Esempio n. 12
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 = TransactingPower(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
Esempio n. 13
0
def test_stake_in_idle_network(testerchain, token_economics, test_registry):

    # Let's fund a staker first
    token_agent = NucypherTokenAgent(registry=test_registry)
    token_airdrop(origin=testerchain.etherbase_account,
                  addresses=testerchain.stakers_accounts,
                  token_agent=token_agent,
                  amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
    account = testerchain.stakers_accounts[0]
    staker = Staker(is_me=True, checksum_address=account, registry=test_registry)

    # Mock TransactingPower consumption
    staker.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=staker.checksum_address)
    staker.transacting_power.activate()

    # Since StakingEscrow hasn't been activated yet, trying to deposit must fail
    amount = token_economics.minimum_allowed_locked
    periods = token_economics.minimum_locked_periods
    with pytest.raises((TransactionFailed, ValueError)):
        staker.initialize_stake(amount=amount, lock_periods=periods)
Esempio n. 14
0
def simulate(config, action, nodes, federated_only, geth):
    """
    Simulate the nucypher blockchain network

    Arguments
    ==========

    action - Which action to perform; The choices are:
           - start: Start a multi-process nucypher network simulation
           - stop: Stop a running simulation gracefully

    Options
    ========

    --nodes - The quantity of nodes (processes) to execute during the simulation
    --duration = The number of periods to run the simulation before termination

    """
    if action == 'start':

        #
        # Blockchain Connection
        #
        if not federated_only:
            if geth:
                test_provider_uri = "ipc:///tmp/geth.ipc"
            else:
                test_provider_uri = "pyevm://tester"

            simulation_registry = TemporaryEthereumContractRegistry()
            simulation_interface = BlockchainDeployerInterface(provider_uri=test_provider_uri,
                                                               registry=simulation_registry,
                                                               compiler=SolidityCompiler())

            blockchain = TesterBlockchain(interface=simulation_interface, test_accounts=nodes, airdrop=False)

            accounts = blockchain.interface.w3.eth.accounts
            origin, *everyone_else = accounts

            # Set the deployer address from the freshly created test account
            simulation_interface.deployer_address = origin

            #
            # Blockchain Action
            #
            blockchain.ether_airdrop(amount=DEVELOPMENT_ETH_AIRDROP_AMOUNT)

            click.confirm("Deploy all nucypher contracts to {}?".format(test_provider_uri), abort=True)
            click.echo("Bootstrapping simulated blockchain network")

            # Deploy contracts
            token_deployer = NucypherTokenDeployer(blockchain=blockchain, deployer_address=origin)
            token_deployer.arm()
            token_deployer.deploy()
            token_agent = token_deployer.make_agent()

            miners_escrow_secret = os.urandom(DISPATCHER_SECRET_LENGTH)
            miner_escrow_deployer = MinerEscrowDeployer(token_agent=token_agent,
                                                        deployer_address=origin,
                                                        secret_hash=miners_escrow_secret)
            miner_escrow_deployer.arm()
            miner_escrow_deployer.deploy()
            miner_agent = miner_escrow_deployer.make_agent()

            policy_manager_secret = os.urandom(DISPATCHER_SECRET_LENGTH)
            policy_manager_deployer = PolicyManagerDeployer(miner_agent=miner_agent,
                                                            deployer_address=origin,
                                                            secret_hash=policy_manager_secret)
            policy_manager_deployer.arm()
            policy_manager_deployer.deploy()
            policy_agent = policy_manager_deployer.make_agent()

            airdrop_amount = DEVELOPMENT_TOKEN_AIRDROP_AMOUNT
            click.echo("Airdropping tokens {} to {} addresses".format(airdrop_amount, len(everyone_else)))
            _receipts = token_airdrop(token_agent=token_agent,
                                      origin=origin,
                                      addresses=everyone_else,
                                      amount=airdrop_amount)

            # Commit the current state of deployment to a registry file.
            click.echo("Writing filesystem registry")
            _sim_registry_name = blockchain.interface.registry.commit(filepath=DEFAULT_SIMULATION_REGISTRY_FILEPATH)

        click.echo("Ready to run swarm.")

        #
        # Swarm
        #

        # Select a port range to use on localhost for sim servers

        if not federated_only:
            sim_addresses = everyone_else
        else:
            sim_addresses = NotImplemented

        start_port = 8787
        counter = 0
        for sim_port_number, sim_address in enumerate(sim_addresses, start=start_port):

            #
            # Parse ursula parameters
            #

            rest_port = sim_port_number
            db_name = 'sim-{}'.format(rest_port)

            cli_exec = os.path.join(BASE_DIR, 'cli', 'main.py')
            python_exec = 'python'

            proc_params = '''
            python3 {} run_ursula --rest-port {} --db-name {}
            '''.format(python_exec, cli_exec, rest_port, db_name).split()

            if federated_only:
                proc_params.append('--federated-only')

            else:
                token_agent = NucypherTokenAgent(blockchain=blockchain)
                miner_agent = MinerAgent(token_agent=token_agent)
                miner = Miner(miner_agent=miner_agent, checksum_address=sim_address)

                # stake a random amount
                min_stake, balance = MIN_ALLOWED_LOCKED, miner.token_balance
                value = random.randint(min_stake, balance)

                # for a random lock duration
                min_locktime, max_locktime = MIN_LOCKED_PERIODS, MAX_MINTING_PERIODS
                periods = random.randint(min_locktime, max_locktime)

                miner.initialize_stake(amount=value, lock_periods=periods)
                click.echo("{} Initialized new stake: {} tokens for {} periods".format(sim_address, value, periods))

                proc_params.extend('--checksum-address {}'.format(sim_address).split())

            # Spawn
            click.echo("Spawning node #{}".format(counter+1))
            processProtocol = UrsulaProcessProtocol(command=proc_params)
            cli_exec = os.path.join(BASE_DIR, 'cli', 'main.py')
            ursula_proc = reactor.spawnProcess(processProtocol, cli_exec, proc_params)

            #
            # post-spawnProcess
            #

            # Start with some basic status data, then build on it

            rest_uri = "http://{}:{}".format('localhost', rest_port)

            sim_data = "Started simulated Ursula | ReST {}".format(rest_uri)
            rest_uri = "{host}:{port}".format(host='localhost', port=str(sim_port_number))
            sim_data.format(rest_uri)

            # if not federated_only:
            #     stake_infos = tuple(config.miner_agent.get_all_stakes(miner_address=sim_address))
            #     sim_data += '| ETH address {}'.format(sim_address)
            #     sim_data += '| {} Active stakes '.format(len(stake_infos))

            click.echo(sim_data)
            counter += 1

        click.echo("Starting the reactor")
        click.confirm("Start the reactor?", abort=True)
        try:
            reactor.run()
        finally:

            if not federated_only:
                click.echo("Removing simulation registry")
                os.remove(DEFAULT_SIMULATION_REGISTRY_FILEPATH)

            click.echo("Stopping simulated Ursula processes")
            for process in config.sim_processes:
                os.kill(process.pid, 9)
                click.echo("Killed {}".format(process))

            click.echo("Simulation completed")

    elif action == 'stop':
        # Kill the simulated ursulas
        for process in config.ursula_processes:
            process.transport.signalProcess('KILL')

    elif action == 'status':

        if not config.simulation_running:
            status_message = "Simulation not running."
        else:

            ursula_processes = len(config.ursula_processes)

            status_message = """
            
            | Node Swarm Simulation Status |
            
            Simulation processes .............. {}
            
            """.format(ursula_processes)

        click.echo(status_message)

    elif action == 'demo':
        """Run the finnegans wake demo"""
        demo_exec = os.path.join(BASE_DIR, 'cli', 'demos', 'finnegans-wake-demo.py')
        process_args = [sys.executable, demo_exec]

        if federated_only:
            process_args.append('--federated-only')

        subprocess.run(process_args, stdout=subprocess.PIPE)