2019-03-05 20:08:42 +00:00
|
|
|
import os
|
|
|
|
|
|
|
|
import pytest_twisted
|
|
|
|
from twisted.internet import threads
|
2019-03-21 22:51:51 +00:00
|
|
|
from twisted.internet.task import Clock
|
2019-03-05 20:08:42 +00:00
|
|
|
|
2019-05-29 13:53:23 +00:00
|
|
|
from nucypher.blockchain.eth.actors import Staker
|
2019-06-19 18:52:49 +00:00
|
|
|
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
2019-08-14 02:17:08 +00:00
|
|
|
from nucypher.blockchain.eth.registry import BaseContractRegistry, LocalContractRegistry
|
2019-03-21 22:51:51 +00:00
|
|
|
from nucypher.blockchain.eth.token import NU
|
2019-03-21 21:01:30 +00:00
|
|
|
from nucypher.characters.chaotic import Felix
|
2019-03-05 20:08:42 +00:00
|
|
|
from nucypher.cli.main import nucypher_cli
|
|
|
|
from nucypher.config.characters import FelixConfiguration
|
|
|
|
from nucypher.utilities.sandbox.constants import (
|
|
|
|
TEMPORARY_DOMAIN,
|
|
|
|
TEST_PROVIDER_URI,
|
|
|
|
INSECURE_DEVELOPMENT_PASSWORD,
|
|
|
|
MOCK_CUSTOM_INSTALLATION_PATH_2
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest_twisted.inlineCallbacks
|
2019-06-01 10:47:31 +00:00
|
|
|
def test_run_felix(click_runner,
|
|
|
|
testerchain,
|
2019-08-14 02:17:08 +00:00
|
|
|
test_registry,
|
2019-06-19 18:52:49 +00:00
|
|
|
agency,
|
2019-06-01 10:47:31 +00:00
|
|
|
deploy_user_input,
|
|
|
|
mock_primary_registry_filepath):
|
2019-03-21 21:01:56 +00:00
|
|
|
|
2019-03-21 22:51:51 +00:00
|
|
|
clock = Clock()
|
|
|
|
Felix._CLOCK = clock
|
2019-03-21 21:01:56 +00:00
|
|
|
Felix.DISTRIBUTION_INTERVAL = 5 # seconds
|
|
|
|
Felix.DISBURSEMENT_INTERVAL = 0.01 # hours
|
2019-03-21 22:51:51 +00:00
|
|
|
Felix.STAGING_DELAY = 2 # seconds
|
2019-03-05 20:08:42 +00:00
|
|
|
|
2019-03-06 18:15:19 +00:00
|
|
|
# Main thread (Flask)
|
|
|
|
os.environ['NUCYPHER_FELIX_DB_SECRET'] = INSECURE_DEVELOPMENT_PASSWORD
|
|
|
|
|
2019-06-19 23:26:13 +00:00
|
|
|
# Mock live contract registry reads
|
2019-08-14 02:17:08 +00:00
|
|
|
LocalContractRegistry.read = lambda *a, **kw: test_registry.read()
|
2019-06-19 23:26:13 +00:00
|
|
|
|
2019-03-06 18:15:19 +00:00
|
|
|
# Test subproc (Click)
|
|
|
|
envvars = {'NUCYPHER_KEYRING_PASSWORD': INSECURE_DEVELOPMENT_PASSWORD,
|
2019-03-21 21:01:56 +00:00
|
|
|
'NUCYPHER_FELIX_DB_SECRET': INSECURE_DEVELOPMENT_PASSWORD,
|
|
|
|
'FLASK_DEBUG': '1'}
|
2019-03-06 18:15:19 +00:00
|
|
|
|
2019-03-05 22:01:38 +00:00
|
|
|
# Felix creates a system configuration
|
2019-07-23 05:48:09 +00:00
|
|
|
init_args = ('felix', 'init',
|
|
|
|
'--debug',
|
2019-06-19 22:12:06 +00:00
|
|
|
'--registry-filepath', mock_primary_registry_filepath,
|
2019-06-18 23:59:55 +00:00
|
|
|
'--checksum-address', testerchain.client.accounts[0],
|
2019-03-05 21:50:14 +00:00
|
|
|
'--config-root', MOCK_CUSTOM_INSTALLATION_PATH_2,
|
|
|
|
'--network', TEMPORARY_DOMAIN,
|
2019-07-25 04:26:20 +00:00
|
|
|
'--provider', TEST_PROVIDER_URI)
|
2019-03-05 20:08:42 +00:00
|
|
|
|
2019-03-06 18:15:19 +00:00
|
|
|
result = click_runner.invoke(nucypher_cli, init_args, catch_exceptions=False, env=envvars)
|
2019-03-05 20:08:42 +00:00
|
|
|
assert result.exit_code == 0
|
|
|
|
|
2019-06-10 17:44:56 +00:00
|
|
|
configuration_file_location = os.path.join(MOCK_CUSTOM_INSTALLATION_PATH_2, FelixConfiguration.generate_filename())
|
2019-03-05 20:08:42 +00:00
|
|
|
|
2019-03-05 22:01:38 +00:00
|
|
|
# Felix Creates a Database
|
2019-07-23 05:48:09 +00:00
|
|
|
db_args = ('felix', 'createdb',
|
|
|
|
'--debug',
|
2019-03-05 22:01:38 +00:00
|
|
|
'--config-file', configuration_file_location,
|
2019-07-25 04:26:20 +00:00
|
|
|
'--provider', TEST_PROVIDER_URI)
|
2019-03-05 22:01:38 +00:00
|
|
|
|
2019-03-06 18:15:19 +00:00
|
|
|
result = click_runner.invoke(nucypher_cli, db_args, catch_exceptions=False, env=envvars)
|
2019-03-05 22:01:38 +00:00
|
|
|
assert result.exit_code == 0
|
|
|
|
|
|
|
|
# Felix Runs Web Services
|
2019-03-05 20:08:42 +00:00
|
|
|
def run_felix():
|
2019-07-23 05:48:09 +00:00
|
|
|
args = ('felix', 'run',
|
|
|
|
'--debug',
|
2019-03-05 20:08:42 +00:00
|
|
|
'--config-file', configuration_file_location,
|
2019-07-25 04:26:20 +00:00
|
|
|
'--provider', TEST_PROVIDER_URI,
|
2019-08-14 02:17:08 +00:00
|
|
|
'--dry-run')
|
2019-03-05 20:08:42 +00:00
|
|
|
|
2019-06-10 17:44:56 +00:00
|
|
|
run_result = click_runner.invoke(nucypher_cli, args, catch_exceptions=False, env=envvars)
|
|
|
|
assert run_result.exit_code == 0
|
|
|
|
return run_result
|
2019-03-05 20:08:42 +00:00
|
|
|
|
2019-03-06 07:16:49 +00:00
|
|
|
# A (mocked) client requests Felix's services
|
2019-03-06 18:15:19 +00:00
|
|
|
def request_felix_landing_page(_result):
|
2019-03-05 20:08:42 +00:00
|
|
|
|
|
|
|
# Init an equal Felix to the already running one.
|
2019-08-14 02:17:08 +00:00
|
|
|
felix_config = FelixConfiguration.from_configuration_file(filepath=configuration_file_location,
|
|
|
|
registry_filepath=mock_primary_registry_filepath)
|
2019-06-11 01:31:50 +00:00
|
|
|
|
|
|
|
felix_config.attach_keyring()
|
2019-03-05 20:08:42 +00:00
|
|
|
felix_config.keyring.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
|
|
|
|
felix = felix_config.produce()
|
|
|
|
|
|
|
|
# Make a flask app
|
|
|
|
web_app = felix.make_web_app()
|
|
|
|
test_client = web_app.test_client()
|
|
|
|
|
2019-03-05 22:01:38 +00:00
|
|
|
# Load the landing page
|
2019-03-05 20:08:42 +00:00
|
|
|
response = test_client.get('/')
|
2019-03-05 21:50:14 +00:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2019-03-05 22:01:38 +00:00
|
|
|
# Register a new recipient
|
2019-08-21 12:11:39 +00:00
|
|
|
response = test_client.post('/register', data={'address': testerchain.client.accounts[-1]})
|
2019-03-05 21:50:14 +00:00
|
|
|
assert response.status_code == 200
|
2019-03-05 20:08:42 +00:00
|
|
|
|
2019-03-06 07:16:49 +00:00
|
|
|
return
|
|
|
|
|
2019-03-21 22:51:51 +00:00
|
|
|
def time_travel(_result):
|
|
|
|
clock.advance(amount=60)
|
|
|
|
|
2019-04-29 23:50:45 +00:00
|
|
|
# Record starting ether balance
|
2019-06-18 23:59:55 +00:00
|
|
|
recipient = testerchain.client.accounts[-1]
|
2019-05-29 13:53:23 +00:00
|
|
|
staker = Staker(checksum_address=recipient,
|
2019-08-14 02:17:08 +00:00
|
|
|
registry=test_registry,
|
2019-05-29 13:53:23 +00:00
|
|
|
is_me=True)
|
|
|
|
original_eth_balance = staker.eth_balance
|
2019-04-29 23:50:45 +00:00
|
|
|
|
2019-03-05 22:01:38 +00:00
|
|
|
# Run the callbacks
|
2019-03-05 20:08:42 +00:00
|
|
|
d = threads.deferToThread(run_felix)
|
|
|
|
d.addCallback(request_felix_landing_page)
|
2019-03-21 22:51:51 +00:00
|
|
|
d.addCallback(time_travel)
|
|
|
|
|
2019-03-05 20:08:42 +00:00
|
|
|
yield d
|
2019-03-21 22:51:51 +00:00
|
|
|
|
|
|
|
def confirm_airdrop(_results):
|
2019-06-18 23:59:55 +00:00
|
|
|
recipient = testerchain.client.accounts[-1]
|
2019-05-29 13:53:23 +00:00
|
|
|
staker = Staker(checksum_address=recipient,
|
2019-08-14 02:17:08 +00:00
|
|
|
registry=test_registry,
|
2019-05-29 13:53:23 +00:00
|
|
|
is_me=True)
|
2019-03-21 22:51:51 +00:00
|
|
|
|
2019-08-21 10:59:52 +00:00
|
|
|
assert staker.token_balance == NU(45000, 'NU')
|
2019-03-21 22:51:51 +00:00
|
|
|
|
2019-06-19 18:52:49 +00:00
|
|
|
# TODO: Airdrop Testnet Ethers?
|
2019-09-03 18:45:52 +00:00
|
|
|
new_eth_balance = original_eth_balance + testerchain.w3.fromWei(Felix.ETHER_AIRDROP_AMOUNT, 'ether')
|
|
|
|
assert staker.eth_balance == new_eth_balance
|
2019-04-29 23:50:45 +00:00
|
|
|
|
2019-03-21 22:51:51 +00:00
|
|
|
staged_airdrops = Felix._AIRDROP_QUEUE
|
|
|
|
next_airdrop = staged_airdrops[0]
|
|
|
|
next_airdrop.addCallback(confirm_airdrop)
|
|
|
|
yield next_airdrop
|