2018-06-23 20:48:06 +00:00
|
|
|
import contextlib
|
2018-09-12 12:04:02 +00:00
|
|
|
import datetime
|
2018-08-05 20:09:05 +00:00
|
|
|
import os
|
|
|
|
import tempfile
|
2018-04-12 03:17:39 +00:00
|
|
|
|
2018-06-23 20:48:06 +00:00
|
|
|
import maya
|
|
|
|
import pytest
|
2018-06-29 00:23:42 +00:00
|
|
|
from constant_sorrow import constants
|
2018-06-23 20:48:06 +00:00
|
|
|
from sqlalchemy.engine import create_engine
|
2018-08-11 22:56:27 +00:00
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
from nucypher.blockchain.eth.deployers import PolicyManagerDeployer, NucypherTokenDeployer, MinerEscrowDeployer
|
2018-08-20 02:44:50 +00:00
|
|
|
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
|
|
|
from nucypher.blockchain.eth.registry import TemporaryEthereumContractRegistry
|
2018-08-18 23:24:13 +00:00
|
|
|
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
2018-09-17 18:54:24 +00:00
|
|
|
from nucypher.characters.lawful import Bob
|
|
|
|
from nucypher.config.characters import UrsulaConfiguration, AliceConfiguration
|
|
|
|
from nucypher.config.constants import TEST_CONTRACTS_DIR
|
2018-09-17 21:06:43 +00:00
|
|
|
from nucypher.config.node import NodeConfiguration
|
2018-05-08 19:35:34 +00:00
|
|
|
from nucypher.data_sources import DataSource
|
|
|
|
from nucypher.keystore import keystore
|
|
|
|
from nucypher.keystore.db import Base
|
|
|
|
from nucypher.keystore.keypairs import SigningKeypair
|
2018-09-13 19:32:38 +00:00
|
|
|
from nucypher.utilities.sandbox.blockchain import TesterBlockchain, token_airdrop
|
2018-09-20 00:01:01 +00:00
|
|
|
from nucypher.utilities.sandbox.constants import (DEFAULT_NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK,
|
2018-09-13 19:32:38 +00:00
|
|
|
DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
|
|
|
|
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
|
|
|
from nucypher.utilities.sandbox.ursula import make_federated_ursulas, make_decentralized_ursulas
|
2018-06-29 00:23:42 +00:00
|
|
|
|
2018-09-17 21:06:43 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Temporary
|
|
|
|
#
|
2018-09-16 21:35:17 +00:00
|
|
|
|
2018-09-20 00:01:01 +00:00
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
def tempfile_path():
|
|
|
|
fd, path = tempfile.mkstemp()
|
|
|
|
yield path
|
|
|
|
os.close(fd)
|
|
|
|
os.remove(path)
|
|
|
|
|
|
|
|
|
2018-09-21 16:03:45 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-19 22:25:54 +00:00
|
|
|
def temp_dir_path():
|
2018-09-20 00:01:01 +00:00
|
|
|
temp_dir = tempfile.TemporaryDirectory(prefix='nucypher-test-')
|
2018-09-19 22:25:54 +00:00
|
|
|
yield temp_dir.name
|
|
|
|
temp_dir.cleanup()
|
2018-06-29 00:23:42 +00:00
|
|
|
|
|
|
|
|
2018-09-21 16:03:45 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-19 22:25:54 +00:00
|
|
|
def temp_config_root(temp_dir_path):
|
2018-09-17 18:54:24 +00:00
|
|
|
"""
|
|
|
|
User is responsible for closing the file given at the path.
|
|
|
|
"""
|
2018-09-19 20:21:11 +00:00
|
|
|
default_node_config = NodeConfiguration(temp=True,
|
2018-09-21 16:03:45 +00:00
|
|
|
auto_initialize=False,
|
2018-09-19 22:25:54 +00:00
|
|
|
config_root=temp_dir_path)
|
2018-09-17 21:06:43 +00:00
|
|
|
yield default_node_config.config_root
|
2018-09-21 16:03:45 +00:00
|
|
|
default_node_config.cleanup()
|
2018-09-17 18:54:24 +00:00
|
|
|
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def test_keystore():
|
|
|
|
engine = create_engine('sqlite:///:memory:')
|
|
|
|
Base.metadata.create_all(engine)
|
|
|
|
test_keystore = keystore.KeyStore(engine)
|
|
|
|
yield test_keystore
|
|
|
|
|
|
|
|
|
2018-09-13 19:35:44 +00:00
|
|
|
#
|
|
|
|
# Configuration
|
|
|
|
#
|
|
|
|
|
2018-09-17 18:54:24 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-20 19:52:21 +00:00
|
|
|
def ursula_federated_test_config():
|
2018-09-17 21:06:43 +00:00
|
|
|
|
|
|
|
ursula_config = UrsulaConfiguration(temp=True,
|
2018-09-19 20:36:16 +00:00
|
|
|
auto_initialize=True,
|
2018-09-17 21:06:43 +00:00
|
|
|
is_me=True,
|
|
|
|
always_be_learning=False,
|
2018-09-20 19:52:21 +00:00
|
|
|
abort_on_learning_error=True,
|
2018-09-17 21:06:43 +00:00
|
|
|
federated_only=True)
|
|
|
|
yield ursula_config
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2018-09-20 19:52:21 +00:00
|
|
|
def ursula_decentralized_test_config(three_agents):
|
2018-09-17 21:06:43 +00:00
|
|
|
token_agent, miner_agent, policy_agent = three_agents
|
|
|
|
|
2018-09-17 18:54:24 +00:00
|
|
|
ursula_config = UrsulaConfiguration(temp=True,
|
2018-09-19 20:36:16 +00:00
|
|
|
auto_initialize=True,
|
2018-09-17 21:06:43 +00:00
|
|
|
is_me=True,
|
|
|
|
always_be_learning=False,
|
2018-09-20 19:52:21 +00:00
|
|
|
abort_on_learning_error=True,
|
2018-09-17 21:06:43 +00:00
|
|
|
miner_agent=miner_agent,
|
|
|
|
federated_only=False)
|
2018-09-13 19:35:44 +00:00
|
|
|
yield ursula_config
|
|
|
|
|
|
|
|
|
2018-09-17 21:06:43 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-20 19:52:21 +00:00
|
|
|
def alice_federated_test_config(federated_ursulas):
|
2018-09-17 21:06:43 +00:00
|
|
|
config = AliceConfiguration(temp=True,
|
2018-09-19 20:36:16 +00:00
|
|
|
auto_initialize=True,
|
2018-09-20 19:52:21 +00:00
|
|
|
is_me=True,
|
2018-09-17 21:06:43 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
|
|
|
known_nodes=federated_ursulas,
|
|
|
|
federated_only=True,
|
|
|
|
abort_on_learning_error=True)
|
|
|
|
yield config
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2018-09-20 19:52:21 +00:00
|
|
|
def alice_blockchain_test_config(blockchain_ursulas, three_agents):
|
2018-09-17 21:06:43 +00:00
|
|
|
token_agent, miner_agent, policy_agent = three_agents
|
|
|
|
etherbase, alice_address, bob_address, *everyone_else = token_agent.blockchain.interface.w3.eth.accounts
|
|
|
|
|
|
|
|
config = AliceConfiguration(temp=True,
|
|
|
|
is_me=True,
|
2018-09-19 20:36:16 +00:00
|
|
|
auto_initialize=True,
|
2018-09-17 21:06:43 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
|
|
|
policy_agent=policy_agent,
|
|
|
|
known_nodes=blockchain_ursulas,
|
|
|
|
abort_on_learning_error=True,
|
|
|
|
checksum_address=alice_address)
|
|
|
|
yield config
|
|
|
|
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
#
|
|
|
|
# Policies
|
|
|
|
#
|
2017-11-22 04:19:31 +00:00
|
|
|
|
2017-12-08 04:41:04 +00:00
|
|
|
|
2017-12-15 05:21:09 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-06-30 03:25:36 +00:00
|
|
|
def idle_federated_policy(alice, bob):
|
|
|
|
"""
|
|
|
|
Creates a Policy, in a manner typical of how Alice might do it, with a unique uri (soon to be "label" - see #183)
|
|
|
|
"""
|
2018-09-13 19:35:44 +00:00
|
|
|
n = DEFAULT_NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK
|
2018-06-30 03:25:36 +00:00
|
|
|
random_label = b'label://' + os.urandom(32)
|
|
|
|
policy = alice.create_policy(bob, label=random_label, m=3, n=n, federated=True)
|
|
|
|
return policy
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2018-09-13 19:35:44 +00:00
|
|
|
def enacted_federated_policy(idle_federated_policy, federated_ursulas):
|
2018-06-30 03:25:36 +00:00
|
|
|
# Alice has a policy in mind and knows of enough qualifies Ursulas; she crafts an offer for them.
|
2018-09-07 10:45:30 +00:00
|
|
|
deposit = constants.NON_PAYMENT
|
2018-06-30 03:25:36 +00:00
|
|
|
contract_end_datetime = maya.now() + datetime.timedelta(days=5)
|
|
|
|
network_middleware = MockRestMiddleware()
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
idle_federated_policy.make_arrangements(network_middleware,
|
|
|
|
deposit=deposit,
|
|
|
|
expiration=contract_end_datetime,
|
2018-09-13 19:35:44 +00:00
|
|
|
handpicked_ursulas=federated_ursulas)
|
2018-09-17 18:54:24 +00:00
|
|
|
|
2018-09-16 21:35:17 +00:00
|
|
|
responses = idle_federated_policy.enact(network_middleware) # REST call happens here, as does population of TreasureMap.
|
2018-06-30 03:25:36 +00:00
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
return idle_federated_policy
|
2018-06-30 03:25:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2018-07-10 01:13:29 +00:00
|
|
|
def idle_blockchain_policy(blockchain_alice, bob):
|
2018-06-29 00:23:42 +00:00
|
|
|
"""
|
|
|
|
Creates a Policy, in a manner typical of how Alice might do it, with a unique uri (soon to be "label" - see #183)
|
|
|
|
"""
|
|
|
|
random_label = b'label://' + os.urandom(32)
|
2018-07-10 01:13:29 +00:00
|
|
|
policy = blockchain_alice.create_policy(bob, label=random_label, m=2, n=3)
|
2018-06-29 00:23:42 +00:00
|
|
|
return policy
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2018-09-13 19:35:44 +00:00
|
|
|
def enacted_blockchain_policy(idle_blockchain_policy, blockchain_ursulas):
|
2017-11-22 04:19:31 +00:00
|
|
|
# Alice has a policy in mind and knows of enough qualifies Ursulas; she crafts an offer for them.
|
2018-06-01 01:28:38 +00:00
|
|
|
deposit = constants.NON_PAYMENT(b"0000000")
|
2018-04-07 02:26:13 +00:00
|
|
|
contract_end_datetime = maya.now() + datetime.timedelta(days=5)
|
2018-06-06 08:32:25 +00:00
|
|
|
network_middleware = MockRestMiddleware()
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
idle_blockchain_policy.make_arrangements(network_middleware, deposit=deposit, expiration=contract_end_datetime,
|
2018-09-13 19:35:44 +00:00
|
|
|
ursulas=list(blockchain_ursulas))
|
2018-06-29 00:23:42 +00:00
|
|
|
idle_blockchain_policy.enact(network_middleware) # REST call happens here, as does population of TreasureMap.
|
|
|
|
|
|
|
|
return idle_blockchain_policy
|
2017-11-22 04:19:31 +00:00
|
|
|
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
#
|
|
|
|
# Alice, Bob, and Capsule
|
|
|
|
#
|
2017-12-08 04:41:04 +00:00
|
|
|
|
2017-12-15 05:21:09 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-17 21:06:43 +00:00
|
|
|
def alice(alice_federated_test_config):
|
2018-09-17 18:54:24 +00:00
|
|
|
alice = alice_federated_test_config.produce()
|
|
|
|
return alice
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2018-09-17 21:06:43 +00:00
|
|
|
def blockchain_alice(alice_blockchain_test_config):
|
2018-09-17 18:54:24 +00:00
|
|
|
alice = alice_blockchain_test_config.produce()
|
2018-06-14 00:44:50 +00:00
|
|
|
return alice
|
2017-11-22 04:19:31 +00:00
|
|
|
|
|
|
|
|
2017-12-15 05:21:09 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-06-30 03:25:36 +00:00
|
|
|
def bob():
|
|
|
|
_bob = Bob(network_middleware=MockRestMiddleware(),
|
|
|
|
always_be_learning=False,
|
|
|
|
abort_on_learning_error=True,
|
|
|
|
federated_only=True)
|
2018-06-01 20:34:42 +00:00
|
|
|
return _bob
|
2017-11-22 04:19:31 +00:00
|
|
|
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def capsule_side_channel(enacted_federated_policy):
|
|
|
|
signing_keypair = SigningKeypair()
|
|
|
|
data_source = DataSource(policy_pubkey_enc=enacted_federated_policy.public_key,
|
|
|
|
signing_keypair=signing_keypair)
|
|
|
|
message_kit, _signature = data_source.encapsulate_single_message(b"Welcome to the flippering.")
|
|
|
|
return message_kit, data_source
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Ursulas
|
|
|
|
#
|
|
|
|
|
2018-06-23 03:27:15 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-17 21:06:43 +00:00
|
|
|
def federated_ursulas(ursula_federated_test_config):
|
2018-09-17 18:54:24 +00:00
|
|
|
_ursulas = None
|
2018-06-23 20:48:06 +00:00
|
|
|
try:
|
2018-09-17 21:06:43 +00:00
|
|
|
_ursulas = make_federated_ursulas(ursula_config=ursula_federated_test_config,
|
|
|
|
quantity=DEFAULT_NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK)
|
2018-06-23 20:48:06 +00:00
|
|
|
yield _ursulas
|
|
|
|
finally:
|
2018-09-17 18:54:24 +00:00
|
|
|
if _ursulas:
|
|
|
|
# Remove the DBs that have been sprayed hither and yon.
|
|
|
|
with contextlib.suppress(FileNotFoundError):
|
2018-09-19 23:26:15 +00:00
|
|
|
for ursula in _ursulas:
|
|
|
|
os.remove(ursula.datastore.engine.engine.url.database)
|
2017-12-08 04:41:26 +00:00
|
|
|
|
|
|
|
|
2018-02-13 20:28:39 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-17 21:06:43 +00:00
|
|
|
def blockchain_ursulas(three_agents, ursula_decentralized_test_config):
|
2018-09-13 19:35:44 +00:00
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
token_agent, miner_agent, policy_agent = three_agents
|
|
|
|
etherbase, alice, bob, *all_yall = token_agent.blockchain.interface.w3.eth.accounts
|
2018-02-13 20:22:26 +00:00
|
|
|
|
2018-09-13 19:35:44 +00:00
|
|
|
ursula_addresses = all_yall[:DEFAULT_NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK]
|
2018-02-19 23:20:40 +00:00
|
|
|
|
2018-09-13 19:35:44 +00:00
|
|
|
token_airdrop(origin=etherbase,
|
|
|
|
addresses=ursula_addresses,
|
|
|
|
token_agent=token_agent,
|
|
|
|
amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
|
2018-02-19 23:20:40 +00:00
|
|
|
|
2018-09-17 21:06:43 +00:00
|
|
|
_ursulas = None
|
2018-06-29 00:23:42 +00:00
|
|
|
try:
|
2018-09-17 21:06:43 +00:00
|
|
|
_ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
|
|
|
|
ether_addresses=ursula_addresses,
|
|
|
|
stake=True)
|
2018-06-29 00:23:42 +00:00
|
|
|
yield _ursulas
|
|
|
|
finally:
|
2018-09-17 21:06:43 +00:00
|
|
|
if _ursulas:
|
|
|
|
# Remove the DBs that have been sprayed hither and yon.
|
|
|
|
with contextlib.suppress(FileNotFoundError):
|
2018-09-19 23:26:15 +00:00
|
|
|
for ursula in _ursulas:
|
|
|
|
os.remove(ursula.datastore.engine.engine.url.database)
|
2018-06-29 00:23:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Blockchain
|
|
|
|
#
|
|
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
|
|
|
def solidity_compiler():
|
|
|
|
"""Doing this more than once per session will result in slower test run times."""
|
2018-09-12 14:19:41 +00:00
|
|
|
compiler = SolidityCompiler(test_contract_dir=TEST_CONTRACTS_DIR)
|
2018-06-29 00:23:42 +00:00
|
|
|
yield compiler
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def testerchain(solidity_compiler):
|
2018-04-13 00:24:55 +00:00
|
|
|
"""
|
2018-06-29 00:23:42 +00:00
|
|
|
https: // github.com / ethereum / eth - tester # available-backends
|
2018-04-13 00:24:55 +00:00
|
|
|
"""
|
2018-06-29 00:23:42 +00:00
|
|
|
|
|
|
|
temp_registrar = TemporaryEthereumContractRegistry()
|
|
|
|
|
|
|
|
# Use the the custom provider and registrar to init an interface
|
2018-08-18 23:24:13 +00:00
|
|
|
|
2018-08-29 14:51:00 +00:00
|
|
|
deployer_interface = BlockchainDeployerInterface(compiler=solidity_compiler, # freshly recompile if not None
|
|
|
|
registry=temp_registrar,
|
|
|
|
provider_uri='pyevm://tester')
|
2018-06-29 00:23:42 +00:00
|
|
|
|
|
|
|
# Create the blockchain
|
2018-09-13 19:32:38 +00:00
|
|
|
testerchain = TesterBlockchain(interface=deployer_interface,
|
|
|
|
test_accounts=DEFAULT_NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK,
|
|
|
|
airdrop=False)
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
origin, *everyone = testerchain.interface.w3.eth.accounts
|
2018-08-29 14:51:00 +00:00
|
|
|
deployer_interface.deployer_address = origin # Set the deployer address from a freshly created test account
|
2018-06-29 00:23:42 +00:00
|
|
|
|
|
|
|
yield testerchain
|
|
|
|
testerchain.sever_connection()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def three_agents(testerchain):
|
|
|
|
"""
|
|
|
|
Musketeers, if you will.
|
|
|
|
Launch the big three contracts on provided chain,
|
|
|
|
make agents for each and return them.
|
|
|
|
"""
|
|
|
|
|
|
|
|
"""Launch all Nucypher ethereum contracts"""
|
|
|
|
origin, *everybody_else = testerchain.interface.w3.eth.accounts
|
|
|
|
|
|
|
|
token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin)
|
|
|
|
token_deployer.arm()
|
|
|
|
token_deployer.deploy()
|
|
|
|
|
|
|
|
token_agent = token_deployer.make_agent()
|
|
|
|
|
2018-07-18 14:38:52 +00:00
|
|
|
miners_escrow_secret = os.urandom(constants.DISPATCHER_SECRET_LENGTH)
|
|
|
|
miner_escrow_deployer = MinerEscrowDeployer(
|
|
|
|
token_agent=token_agent,
|
|
|
|
deployer_address=origin,
|
|
|
|
secret_hash=testerchain.interface.w3.sha3(miners_escrow_secret))
|
2018-06-29 00:23:42 +00:00
|
|
|
miner_escrow_deployer.arm()
|
|
|
|
miner_escrow_deployer.deploy()
|
|
|
|
|
|
|
|
miner_agent = miner_escrow_deployer.make_agent()
|
|
|
|
|
2018-07-18 14:38:52 +00:00
|
|
|
policy_manager_secret = os.urandom(constants.DISPATCHER_SECRET_LENGTH)
|
|
|
|
policy_manager_deployer = PolicyManagerDeployer(
|
|
|
|
miner_agent=miner_agent,
|
|
|
|
deployer_address=origin,
|
|
|
|
secret_hash=testerchain.interface.w3.sha3(policy_manager_secret))
|
2018-06-29 00:23:42 +00:00
|
|
|
policy_manager_deployer.arm()
|
|
|
|
policy_manager_deployer.deploy()
|
|
|
|
|
|
|
|
policy_agent = policy_manager_deployer.make_agent()
|
|
|
|
|
|
|
|
return token_agent, miner_agent, policy_agent
|