Merge pull request #899 from cygnusv/eth-accounts

Improve management of ETH test accounts. Test coverage power-up.
pull/948/head
David Núñez 2019-04-17 15:03:43 +02:00 committed by GitHub
commit 788a027a10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 179 additions and 120 deletions

View File

@ -339,7 +339,7 @@ jobs:
- prepare_environment - prepare_environment
- run: - run:
name: Blockchain Interface Tests name: Blockchain Interface Tests
command: pipenv run pytest tests/blockchain/eth/interfaces --cov=nucypher --cov-report xml:reports/coverage.xml command: pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/blockchain/eth/interfaces/*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
agents: agents:
@ -350,7 +350,7 @@ jobs:
- run: - run:
name: Blockchain Agent Tests name: Blockchain Agent Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/blockchain/eth/entities/agents/**/*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/blockchain/eth/entities/agents/**/*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
actors: actors:
@ -361,7 +361,7 @@ jobs:
- run: - run:
name: Blockchain Actor Tests name: Blockchain Actor Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/blockchain/eth/entities/actors/**/*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/blockchain/eth/entities/actors/**/*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
deployers: deployers:
@ -372,7 +372,7 @@ jobs:
- run: - run:
name: Contract Deployer Tests name: Contract Deployer Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/blockchain/eth/entities/deployers/test_*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/blockchain/eth/entities/deployers/test_*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
contracts: contracts:
@ -383,9 +383,7 @@ jobs:
- run: - run:
name: Ethereum Contract Unit Tests name: Ethereum Contract Unit Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/blockchain/eth/contracts/**/**/test_*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/blockchain/eth/contracts/**/test_*.py" | circleci tests split --split-by=timings)
- store_test_results:
path: reports
- capture_test_results - capture_test_results
config: config:
@ -396,7 +394,7 @@ jobs:
- run: - run:
name: Node Configuration Tests name: Node Configuration Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/config/**/test_*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/config/**/test_*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
crypto: crypto:
@ -415,7 +413,7 @@ jobs:
- run: - run:
name: Network Tests name: Network Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/network/**/test_*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/network/**/test_*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
keystore: keystore:
@ -426,7 +424,7 @@ jobs:
- run: - run:
name: Keystore Tests name: Keystore Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/keystore/**/test_*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/keystore/**/test_*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
character: character:
@ -437,7 +435,7 @@ jobs:
- run: - run:
name: Character Tests name: Character Tests
command: | command: |
pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob tests/characters/**/test_*.py | circleci tests split --split-by=timings) pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/characters/**/test_*.py" | circleci tests split --split-by=timings)
- capture_test_results - capture_test_results
learning: learning:
@ -479,9 +477,8 @@ jobs:
- run: - run:
name: Nucypher CLI Tests name: Nucypher CLI Tests
command: | command: |
pipenv run pytest tests/cli --cov=nucypher --cov-report xml:reports/coverage.xml pipenv run pytest --cov=nucypher --cov-report xml:reports/coverage.xml $(circleci tests glob "tests/cli/**/test_*.py" | circleci tests split --split-by=timings)
- store_test_results: # pipenv run pytest $(circleci tests glob tests/cli/**/test_*.py | circleci tests split --split-by=timings) - capture_test_results
path: reports
mypy: mypy:
<<: *python_36_base <<: *python_36_base

View File

@ -87,3 +87,11 @@ MINING_COEFFICIENT = (
MIN_ALLOWED_LOCKED, # Min amount of tokens that can be locked MIN_ALLOWED_LOCKED, # Min amount of tokens that can be locked
MAX_ALLOWED_LOCKED # Max amount of tokens that can be locked MAX_ALLOWED_LOCKED # Max amount of tokens that can be locked
) )
# Testing and development
NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS = 10
NUMBER_OF_ETH_TEST_ACCOUNTS = NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS + 10

View File

@ -36,6 +36,7 @@ from eth_tester import EthereumTester
from eth_tester import PyEVMBackend from eth_tester import PyEVMBackend
from nucypher.blockchain.eth.registry import EthereumContractRegistry from nucypher.blockchain.eth.registry import EthereumContractRegistry
from nucypher.blockchain.eth.sol.compile import SolidityCompiler from nucypher.blockchain.eth.sol.compile import SolidityCompiler
from nucypher.blockchain.eth.constants import NUMBER_OF_ETH_TEST_ACCOUNTS
class BlockchainInterface: class BlockchainInterface:
@ -67,7 +68,7 @@ class BlockchainInterface:
compiler: SolidityCompiler = None) -> None: compiler: SolidityCompiler = None) -> None:
""" """
A blockchain "network inerface"; The circumflex wraps entirely around the bounds of A blockchain "network interface"; The circumflex wraps entirely around the bounds of
contract operations including compilation, deployment, and execution. contract operations including compilation, deployment, and execution.
Filesystem Configuration Node Client EVM Filesystem Configuration Node Client EVM
@ -234,9 +235,10 @@ class BlockchainInterface:
from nucypher.utilities.sandbox.constants import PYEVM_GAS_LIMIT from nucypher.utilities.sandbox.constants import PYEVM_GAS_LIMIT
genesis_params = PyEVMBackend._generate_genesis_params(overrides={'gas_limit': PYEVM_GAS_LIMIT}) genesis_params = PyEVMBackend._generate_genesis_params(overrides={'gas_limit': PYEVM_GAS_LIMIT})
pyevm_backend = PyEVMBackend(genesis_parameters=genesis_params) pyevm_backend = PyEVMBackend(genesis_parameters=genesis_params)
pyevm_backend.reset_to_genesis(genesis_params=genesis_params,
num_accounts=NUMBER_OF_ETH_TEST_ACCOUNTS)
eth_tester = EthereumTester(backend=pyevm_backend, auto_mine_transactions=True) eth_tester = EthereumTester(backend=pyevm_backend, auto_mine_transactions=True)
provider = EthereumTesterProvider(ethereum_tester=eth_tester) provider = EthereumTesterProvider(ethereum_tester=eth_tester)
elif uri_breakdown.netloc == 'geth': elif uri_breakdown.netloc == 'geth':
# Hardcoded gethdev IPC provider # Hardcoded gethdev IPC provider
provider = IPCProvider(ipc_path='/tmp/geth.ipc', timeout=timeout) provider = IPCProvider(ipc_path='/tmp/geth.ipc', timeout=timeout)
@ -391,7 +393,7 @@ class BlockchainInterface:
def unlock_account(self, address, password, duration): def unlock_account(self, address, password, duration):
if 'tester' in self.provider_uri: if 'tester' in self.provider_uri:
return True # Test accounts are unlocked by default. return True # Test accounts are unlocked by default.
return self.w3.personal.unlockAccount(address, password, duration) return self.w3.geth.personal.unlockAccount(address, password, duration)
class BlockchainDeployerInterface(BlockchainInterface): class BlockchainDeployerInterface(BlockchainInterface):

View File

@ -422,13 +422,6 @@ class NucypherKeyring:
return __key_filepaths return __key_filepaths
def _export_wallet_to_node(self, blockchain, password): # TODO: Deprecate with geth.parity signing EIPs
"""Decrypt the wallet with a password, then import the key to the nodes's keyring over RPC"""
with open(self.__wallet_path, 'rb') as wallet:
data = wallet.read().decode(FILE_ENCODING)
account = Account.decrypt(keyfile_json=data, password=password)
blockchain.interface.w3.personal.importRawKey(private_key=account, password=password)
@unlock_required @unlock_required
def __decrypt_keyfile(self, key_path: str) -> UmbralPrivateKey: def __decrypt_keyfile(self, key_path: str) -> UmbralPrivateKey:
"""Returns plaintext version of decrypting key.""" """Returns plaintext version of decrypting key."""

View File

@ -18,27 +18,24 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import os import os
from functools import partial from functools import partial
from twisted.logger import Logger
from constant_sorrow.constants import NO_BLOCKCHAIN_AVAILABLE
from typing import List, Tuple, Dict from typing import List, Tuple, Dict
from twisted.logger import Logger
from web3 import Web3
from web3.middleware import geth_poa_middleware
from constant_sorrow.constants import NO_BLOCKCHAIN_AVAILABLE
from nucypher.blockchain.eth import constants
from nucypher.blockchain.eth.actors import Deployer from nucypher.blockchain.eth.actors import Deployer
from nucypher.blockchain.eth.agents import NucypherTokenAgent, MinerAgent, PolicyAgent, EthereumContractAgent from nucypher.blockchain.eth.agents import EthereumContractAgent
from nucypher.blockchain.eth.chains import Blockchain
from nucypher.blockchain.eth.constants import DISPATCHER_SECRET_LENGTH from nucypher.blockchain.eth.constants import DISPATCHER_SECRET_LENGTH
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
from nucypher.blockchain.eth.registry import InMemoryEthereumContractRegistry from nucypher.blockchain.eth.registry import InMemoryEthereumContractRegistry
from nucypher.blockchain.eth.sol.compile import SolidityCompiler from nucypher.blockchain.eth.sol.compile import SolidityCompiler
from nucypher.config.constants import CONTRACT_ROOT from nucypher.config.constants import CONTRACT_ROOT
from umbral.keys import UmbralPrivateKey from nucypher.utilities.sandbox.constants import TESTING_ETH_AIRDROP_AMOUNT
from web3.middleware import geth_poa_middleware
from nucypher.blockchain.eth import constants
from nucypher.blockchain.eth.chains import Blockchain
from nucypher.utilities.sandbox.constants import (DEVELOPMENT_ETH_AIRDROP_AMOUNT,
NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK,
INSECURE_DEVELOPMENT_PASSWORD)
def token_airdrop(token_agent, amount: int, origin: str, addresses: List[str]): def token_airdrop(token_agent, amount: int, origin: str, addresses: List[str]):
@ -64,7 +61,14 @@ class TesterBlockchain(Blockchain):
_PROVIDER_URI = 'tester://pyevm' _PROVIDER_URI = 'tester://pyevm'
_instance = NO_BLOCKCHAIN_AVAILABLE _instance = NO_BLOCKCHAIN_AVAILABLE
_test_account_cache = list() _test_account_cache = list()
_default_test_accounts = 10
_default_test_accounts = constants.NUMBER_OF_ETH_TEST_ACCOUNTS
_ETHERBASE = 0
_ALICE = 1
_BOB = 2
_FIRST_URSULA = 5
_ursulas_range = range(constants.NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS)
def __init__(self, test_accounts=None, poa=True, airdrop=False, *args, **kwargs): def __init__(self, test_accounts=None, poa=True, airdrop=False, *args, **kwargs):
if test_accounts is None: if test_accounts is None:
@ -75,20 +79,15 @@ class TesterBlockchain(Blockchain):
self.attach_middleware(w3=self.interface.w3, poa=poa) self.attach_middleware(w3=self.interface.w3, poa=poa)
# Generate additional ethereum accounts for testing # Generate additional ethereum accounts for testing
population = test_accounts if test_accounts is not None else NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK population = test_accounts
enough_accounts = len(self.interface.w3.eth.accounts) >= population enough_accounts = len(self.interface.w3.eth.accounts) >= population
if test_accounts is not None and not enough_accounts: if not enough_accounts:
accounts_to_make = population - len(self.interface.w3.eth.accounts) accounts_to_make = population - len(self.interface.w3.eth.accounts)
test_accounts = test_accounts if test_accounts is not None else population
self.__generate_insecure_unlocked_accounts(quantity=accounts_to_make) self.__generate_insecure_unlocked_accounts(quantity=accounts_to_make)
assert test_accounts == len(self.interface.w3.eth.accounts) assert test_accounts == len(self.interface.w3.eth.accounts)
if airdrop is True: # ETH for everyone! if airdrop is True: # ETH for everyone!
self.ether_airdrop(amount=DEVELOPMENT_ETH_AIRDROP_AMOUNT) self.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT)
@staticmethod @staticmethod
def free_gas_price_strategy(w3, transaction_params=None): def free_gas_price_strategy(w3, transaction_params=None):
@ -114,14 +113,9 @@ class TesterBlockchain(Blockchain):
Generate additional unlocked accounts transferring a balance to each account on creation. Generate additional unlocked accounts transferring a balance to each account on creation.
""" """
addresses = list() addresses = list()
insecure_password = INSECURE_DEVELOPMENT_PASSWORD
for _ in range(quantity): for _ in range(quantity):
privkey = '0x' + os.urandom(32).hex()
umbral_priv_key = UmbralPrivateKey.gen_key() address = self.interface.provider.ethereum_tester.add_account(privkey)
address = self.interface.w3.personal.importRawKey(private_key=umbral_priv_key.to_bytes(),
passphrase=insecure_password)
assert self.interface.unlock_account(address, password=insecure_password, duration=None), 'Failed to unlock {}'.format(address)
addresses.append(address) addresses.append(address)
self._test_account_cache.append(address) self._test_account_cache.append(address)
self.log.info('Generated new insecure account {}'.format(address)) self.log.info('Generated new insecure account {}'.format(address))
@ -141,7 +135,8 @@ class TesterBlockchain(Blockchain):
_receipt = self.wait_for_receipt(txhash) _receipt = self.wait_for_receipt(txhash)
tx_hashes.append(txhash) tx_hashes.append(txhash)
self.log.info("Airdropped {} ETH {} -> {}".format(amount, tx['from'], tx['to'])) eth_amount = Web3().fromWei(amount, 'ether')
self.log.info("Airdropped {} ETH {} -> {}".format(eth_amount, tx['from'], tx['to']))
return tx_hashes return tx_hashes
@ -194,3 +189,30 @@ class TesterBlockchain(Blockchain):
_txhashes, agents = deployer.deploy_network_contracts(miner_secret=random_deployment_secret(), _txhashes, agents = deployer.deploy_network_contracts(miner_secret=random_deployment_secret(),
policy_secret=random_deployment_secret()) policy_secret=random_deployment_secret())
return testerchain, agents return testerchain, agents
@property
def etherbase_account(self):
return self.interface.w3.eth.accounts[self._ETHERBASE]
@property
def alice_account(self):
return self.interface.w3.eth.accounts[self._ALICE]
@property
def bob_account(self):
return self.interface.w3.eth.accounts[self._BOB]
def ursula_account(self, index):
if index not in self._ursulas_range:
raise ValueError(f"Ursula index must be lower than {constants.NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS}")
return self.interface.w3.eth.accounts[index + self._FIRST_URSULA]
@property
def ursulas_accounts(self):
return [self.ursula_account(i) for i in self._ursulas_range]
@property
def unassigned_accounts(self):
assigned_accounts = set(self.ursulas_accounts + [self.etherbase_account, self.alice_account, self.bob_account])
accounts = set(self.interface.w3.eth.accounts)
return list(accounts.difference(assigned_accounts))

View File

@ -26,7 +26,12 @@ from string import digits, ascii_uppercase
from web3 import Web3 from web3 import Web3
from nucypher.blockchain.eth.constants import DISPATCHER_SECRET_LENGTH, NUNITS_PER_TOKEN from nucypher.blockchain.eth.constants import (
DISPATCHER_SECRET_LENGTH,
NUNITS_PER_TOKEN,
NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS
)
from nucypher.config.characters import UrsulaConfiguration from nucypher.config.characters import UrsulaConfiguration
from nucypher.config.constants import BASE_DIR from nucypher.config.constants import BASE_DIR
@ -57,7 +62,7 @@ MOCK_URSULA_STARTING_PORT = select_test_port()
MOCK_KNOWN_URSULAS_CACHE = {} MOCK_KNOWN_URSULAS_CACHE = {}
NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK = 10 NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK = NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS
# #
@ -66,9 +71,7 @@ NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK = 10
TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts') TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts')
DEVELOPMENT_TOKEN_AIRDROP_AMOUNT = 1000000 * int(NUNITS_PER_TOKEN) DEVELOPMENT_TOKEN_AIRDROP_AMOUNT = 1_000_000 * int(NUNITS_PER_TOKEN)
DEVELOPMENT_ETH_AIRDROP_AMOUNT = 10 ** 6 * 10 ** 18 # wei -> ether
MINERS_ESCROW_DEPLOYMENT_SECRET = os.urandom(DISPATCHER_SECRET_LENGTH) MINERS_ESCROW_DEPLOYMENT_SECRET = os.urandom(DISPATCHER_SECRET_LENGTH)
@ -78,7 +81,7 @@ INSECURE_DEVELOPMENT_PASSWORD = ''.join(SystemRandom().choice(ascii_uppercase +
MAX_TEST_SEEDER_ENTRIES = 20 MAX_TEST_SEEDER_ENTRIES = 20
TESTING_ETH_AIRDROP_AMOUNT = int(Web3().fromWei(100, 'ether')) TESTING_ETH_AIRDROP_AMOUNT = int(Web3().toWei(100, 'ether'))
# #

View File

@ -39,14 +39,11 @@ def test_rapid_deployment():
interface = BlockchainDeployerInterface(compiler=compiler, interface = BlockchainDeployerInterface(compiler=compiler,
registry=registry, registry=registry,
provider_uri='tester://pyevm') provider_uri='tester://pyevm')
blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=4) blockchain = TesterBlockchain(interface=interface, airdrop=True, test_accounts=4)
blockchain.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT) deployer_address = blockchain.etherbase_account
origin, *everyone = blockchain.interface.w3.eth.accounts
deployer = Deployer(blockchain=blockchain, deployer = Deployer(blockchain=blockchain,
deployer_address=origin) deployer_address=deployer_address)
deployer_address, *all_yall = deployer.blockchain.interface.w3.eth.accounts
# The Big Three (+ Dispatchers) # The Big Three (+ Dispatchers)
deployer.deploy_network_contracts(miner_secret=os.urandom(32), deployer.deploy_network_contracts(miner_secret=os.urandom(32),
@ -58,6 +55,7 @@ def test_rapid_deployment():
# Deploy User Escrow # Deploy User Escrow
total_allocations = 100 total_allocations = 100
all_yall = blockchain.unassigned_accounts
# Start with some hard-coded cases... # Start with some hard-coded cases...
allocation_data = [{'address': all_yall[1], 'amount': MAX_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS}, allocation_data = [{'address': all_yall[1], 'amount': MAX_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS},
{'address': all_yall[2], 'amount': MIN_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS*2}, {'address': all_yall[2], 'amount': MIN_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS*2},

View File

@ -25,7 +25,6 @@ from nucypher.utilities.sandbox.constants import TESTING_ETH_AIRDROP_AMOUNT
@pytest.fixture(scope='module') @pytest.fixture(scope='module')
def author(testerchain, three_agents): def author(testerchain, three_agents):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
token_agent.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT)
_origin, ursula, alice, *everybody_else = testerchain.interface.w3.eth.accounts _origin, ursula, alice, *everybody_else = testerchain.interface.w3.eth.accounts
author = PolicyAuthor(checksum_address=alice) author = PolicyAuthor(checksum_address=alice)
return author return author

View File

@ -29,32 +29,30 @@ MockPolicyMetadata = collections.namedtuple('MockPolicyMetadata', 'policy_id aut
@pytest.mark.usefixtures('blockchain_ursulas') @pytest.mark.usefixtures('blockchain_ursulas')
def policy_meta(testerchain, three_agents): def policy_meta(testerchain, three_agents):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
origin, someone, *everybody_else = testerchain.interface.w3.eth.accounts
agent = policy_agent agent = policy_agent
_policy_id = os.urandom(16) _policy_id = os.urandom(16)
node_addresses = list(miner_agent.sample(quantity=3, duration=1)) node_addresses = list(miner_agent.sample(quantity=3, duration=1))
_txhash = agent.create_policy(policy_id=_policy_id, _txhash = agent.create_policy(policy_id=_policy_id,
author_address=someone, author_address=testerchain.alice_account,
value=MIN_ALLOWED_LOCKED, value=MIN_ALLOWED_LOCKED,
periods=10, periods=10,
initial_reward=20, initial_reward=20,
node_addresses=node_addresses) node_addresses=node_addresses)
return MockPolicyMetadata(_policy_id, someone, node_addresses) return MockPolicyMetadata(_policy_id, testerchain.alice_account, node_addresses)
@pytest.mark.slow() @pytest.mark.slow()
@pytest.mark.usefixtures('blockchain_ursulas') @pytest.mark.usefixtures('blockchain_ursulas')
def test_create_policy(testerchain, three_agents): def test_create_policy(testerchain, three_agents):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
origin, someone, *everybody_else = testerchain.interface.w3.eth.accounts
agent = policy_agent agent = policy_agent
policy_id = os.urandom(16) policy_id = os.urandom(16)
node_addresses = list(miner_agent.sample(quantity=3, duration=1)) node_addresses = list(miner_agent.sample(quantity=3, duration=1))
txhash = agent.create_policy(policy_id=policy_id, txhash = agent.create_policy(policy_id=policy_id,
author_address=someone, author_address=testerchain.alice_account,
value=MIN_ALLOWED_LOCKED, value=MIN_ALLOWED_LOCKED,
periods=10, periods=10,
initial_reward=20, initial_reward=20,

View File

@ -28,7 +28,7 @@ from nucypher.blockchain.eth.deployers import UserEscrowDeployer, UserEscrowProx
def user_escrow_proxy(three_agents): def user_escrow_proxy(three_agents):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
testerchain = policy_agent.blockchain testerchain = policy_agent.blockchain
deployer, alice, bob, *all_yall = testerchain.interface.w3.eth.accounts deployer = testerchain.etherbase_account
escrow_proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer, escrow_proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer,
secret_hash=os.urandom(32)) secret_hash=os.urandom(32))
@ -44,7 +44,7 @@ def user_escrow_proxy(three_agents):
def test_deploy_and_allocate(three_agents, user_escrow_proxy): def test_deploy_and_allocate(three_agents, user_escrow_proxy):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
testerchain = policy_agent.blockchain testerchain = policy_agent.blockchain
origin, alice, bob, *all_yall = testerchain.interface.w3.eth.accounts origin = testerchain.etherbase_account
deployments = dict() deployments = dict()
allocation = MIN_ALLOWED_LOCKED * 1 allocation = MIN_ALLOWED_LOCKED * 1
@ -82,7 +82,7 @@ def test_deploy_and_allocate(three_agents, user_escrow_proxy):
assert receipt['status'] == 1, "Transaction Rejected {}".format(deposit_txhash) assert receipt['status'] == 1, "Transaction Rejected {}".format(deposit_txhash)
deposit_txhashes[address] = deposit_txhash deposit_txhashes[address] = deposit_txhash
beneficiary = random.choice(all_yall) beneficiary = random.choice(testerchain.unassigned_accounts)
assignment_txhash = deployer.assign_beneficiary(beneficiary) assignment_txhash = deployer.assign_beneficiary(beneficiary)
receipt = testerchain.wait_for_receipt(txhash=assignment_txhash) receipt = testerchain.wait_for_receipt(txhash=assignment_txhash)
assert receipt['status'] == 1, "Transaction Rejected {}".format(assignment_txhash) assert receipt['status'] == 1, "Transaction Rejected {}".format(assignment_txhash)

View File

@ -22,7 +22,7 @@ from nucypher.blockchain.eth.interfaces import EthereumContractRegistry
def test_token_deployer_and_agent(testerchain): def test_token_deployer_and_agent(testerchain):
origin, *everybody_else = testerchain.interface.w3.eth.accounts origin = testerchain.etherbase_account
# Trying to get token from blockchain before it's been published fails # Trying to get token from blockchain before it's been published fails
with pytest.raises(EthereumContractRegistry.UnknownContract): with pytest.raises(EthereumContractRegistry.UnknownContract):

View File

@ -23,7 +23,7 @@ from nucypher.blockchain.eth.deployers import UserEscrowDeployer, UserEscrowProx
def user_escrow_proxy(three_agents): def user_escrow_proxy(three_agents):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
testerchain = policy_agent.blockchain testerchain = policy_agent.blockchain
deployer, alice, bob, *all_yall = testerchain.interface.w3.eth.accounts deployer = testerchain.etherbase_account
escrow_proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer, escrow_proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer,
secret_hash=os.urandom(32)) secret_hash=os.urandom(32))
@ -37,7 +37,7 @@ def user_escrow_proxy(three_agents):
@pytest.mark.usesfixtures('three_agents') @pytest.mark.usesfixtures('three_agents')
def test_user_escrow_deployer(three_agents, testerchain): def test_user_escrow_deployer(three_agents, testerchain):
deployer, alice, bob, *all_yall = testerchain.interface.w3.eth.accounts deployer = testerchain.etherbase_account
escrow_proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer, escrow_proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer,
secret_hash=os.urandom(32)) secret_hash=os.urandom(32))
@ -56,7 +56,7 @@ def test_user_escrow_deployer(three_agents, testerchain):
@pytest.mark.slow() @pytest.mark.slow()
@pytest.mark.usesfixtures(['user_escrow_proxy', 'three_agents']) @pytest.mark.usesfixtures(['user_escrow_proxy', 'three_agents'])
def test_deploy_multiple(testerchain): def test_deploy_multiple(testerchain):
deployer, alice, bob, *all_yall = testerchain.interface.w3.eth.accounts deployer = testerchain.etherbase_account
number_of_deployments = 100 number_of_deployments = 100
for index in range(number_of_deployments): for index in range(number_of_deployments):

View File

@ -14,11 +14,68 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>. along with nucypher. If not, see <https://www.gnu.org/licenses/>.
""" """
import pytest
from nucypher.blockchain.eth.constants import (NUMBER_OF_ETH_TEST_ACCOUNTS,
NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS)
from nucypher.utilities.sandbox.constants import TESTING_ETH_AIRDROP_AMOUNT
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
from nucypher.blockchain.eth.registry import InMemoryEthereumContractRegistry
from nucypher.utilities.sandbox.blockchain import TesterBlockchain
def test_testerchain_creation(testerchain): @pytest.fixture()
# Ensure we are testing on the correct network... def another_testerchain(solidity_compiler):
assert 'tester' in testerchain.interface.provider_uri memory_registry = InMemoryEthereumContractRegistry()
deployer_interface = BlockchainDeployerInterface(compiler=solidity_compiler,
registry=memory_registry,
provider_uri='tester://pyevm')
testerchain = TesterBlockchain(interface=deployer_interface,
test_accounts=2*NUMBER_OF_ETH_TEST_ACCOUNTS,
airdrop=True)
deployer_interface.deployer_address = testerchain.etherbase_account
yield testerchain
testerchain.sever_connection()
# ... and that there are already some blocks mined
assert testerchain.interface.w3.eth.blockNumber >= 0 def test_testerchain_creation(testerchain, another_testerchain):
chains = (testerchain, another_testerchain)
for testerchain in chains:
# Ensure we are testing on the correct network...
assert 'tester' in testerchain.interface.provider_uri
# ... and that there are already some blocks mined
assert testerchain.interface.w3.eth.blockNumber > 0
# Check that we have enough test accounts
assert len(testerchain.interface.w3.eth.accounts) >= NUMBER_OF_ETH_TEST_ACCOUNTS
# Check that distinguished accounts are assigned
etherbase = testerchain.etherbase_account
assert etherbase == testerchain.interface.w3.eth.accounts[0]
alice = testerchain.alice_account
assert alice == testerchain.interface.w3.eth.accounts[1]
bob = testerchain.bob_account
assert bob == testerchain.interface.w3.eth.accounts[2]
ursulas = [testerchain.ursula_account(i) for i in range(NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS)]
assert ursulas == testerchain.ursulas_accounts
# Check that the remaining accounts are different from the previous ones:
assert set([etherbase, alice, bob] + ursulas).isdisjoint(set(testerchain.unassigned_accounts))
# Check that accounts are funded
for account in testerchain.interface.w3.eth.accounts:
assert testerchain.interface.w3.eth.getBalance(account) >= TESTING_ETH_AIRDROP_AMOUNT
# Check that accounts can send transactions
for account in testerchain.interface.w3.eth.accounts:
tx = {'to': etherbase, 'from': account, 'value': 100}
txhash = testerchain.interface.w3.eth.sendTransaction(tx)
_receipt = testerchain.wait_for_receipt(txhash)

View File

@ -97,9 +97,7 @@ def custom_filepath_2():
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
def deployed_blockchain(): def deployed_blockchain():
#
# Interface # Interface
#
compiler = SolidityCompiler() compiler = SolidityCompiler()
registry = InMemoryEthereumContractRegistry() registry = InMemoryEthereumContractRegistry()
allocation_registry = InMemoryAllocationRegistry() allocation_registry = InMemoryAllocationRegistry()
@ -107,20 +105,13 @@ def deployed_blockchain():
registry=registry, registry=registry,
provider_uri=TEST_PROVIDER_URI) provider_uri=TEST_PROVIDER_URI)
#
# Blockchain # Blockchain
# blockchain = TesterBlockchain(interface=interface, airdrop=True, test_accounts=5, poa=True)
blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=5, poa=True) deployer_address = blockchain.etherbase_account
blockchain.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT)
origin, *everyone = blockchain.interface.w3.eth.accounts
# # Deployer
# Delpoyer
#
deployer = Deployer(blockchain=blockchain, deployer = Deployer(blockchain=blockchain,
deployer_address=origin) deployer_address=deployer_address)
deployer_address, *all_yall = deployer.blockchain.interface.w3.eth.accounts
# The Big Three (+ Dispatchers) # The Big Three (+ Dispatchers)
deployer.deploy_network_contracts(miner_secret=os.urandom(32), deployer.deploy_network_contracts(miner_secret=os.urandom(32),
@ -130,6 +121,7 @@ def deployed_blockchain():
deployer.deploy_escrow_proxy(secret=os.urandom(32)) deployer.deploy_escrow_proxy(secret=os.urandom(32))
# Start with some hard-coded cases... # Start with some hard-coded cases...
all_yall = blockchain.unassigned_accounts
allocation_data = [{'address': all_yall[1], 'amount': MAX_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS}] allocation_data = [{'address': all_yall[1], 'amount': MAX_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS}]
deployer.deploy_beneficiary_contracts(allocations=allocation_data, allocation_registry=allocation_registry) deployer.deploy_beneficiary_contracts(allocations=allocation_data, allocation_registry=allocation_registry)

View File

@ -149,12 +149,10 @@ def alice_federated_test_config(federated_ursulas):
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def alice_blockchain_test_config(blockchain_ursulas, three_agents): def alice_blockchain_test_config(blockchain_ursulas, three_agents):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
etherbase, alice_address, bob_address, *everyone_else = token_agent.blockchain.interface.w3.eth.accounts
config = AliceConfiguration(dev_mode=True, config = AliceConfiguration(dev_mode=True,
is_me=True, is_me=True,
provider_uri="tester://pyevm", provider_uri="tester://pyevm",
checksum_public_address=alice_address, checksum_public_address=token_agent.blockchain.alice_account,
network_middleware=MockRestMiddleware(), network_middleware=MockRestMiddleware(),
known_nodes=blockchain_ursulas, known_nodes=blockchain_ursulas,
abort_on_learning_error=True, abort_on_learning_error=True,
@ -181,11 +179,9 @@ def bob_federated_test_config():
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def bob_blockchain_test_config(blockchain_ursulas, three_agents): def bob_blockchain_test_config(blockchain_ursulas, three_agents):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
etherbase, alice_address, bob_address, *everyone_else = token_agent.blockchain.interface.w3.eth.accounts
config = BobConfiguration(dev_mode=True, config = BobConfiguration(dev_mode=True,
provider_uri="tester://pyevm", provider_uri="tester://pyevm",
checksum_public_address=bob_address, checksum_public_address=token_agent.blockchain.bob_account,
network_middleware=MockRestMiddleware(), network_middleware=MockRestMiddleware(),
known_nodes=blockchain_ursulas, known_nodes=blockchain_ursulas,
start_learning_now=False, start_learning_now=False,
@ -314,10 +310,10 @@ def federated_ursulas(ursula_federated_test_config):
quantity=NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK) quantity=NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK)
yield _ursulas yield _ursulas
#
# Blokchain
#
#
# Blockchain
#
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
@ -341,13 +337,9 @@ def testerchain(solidity_compiler):
provider_uri='tester://pyevm') provider_uri='tester://pyevm')
# Create the blockchain # Create the blockchain
testerchain = TesterBlockchain(interface=deployer_interface, testerchain = TesterBlockchain(interface=deployer_interface, airdrop=True)
test_accounts=NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK,
airdrop=False)
origin, *everyone = testerchain.interface.w3.eth.accounts deployer_interface.deployer_address = testerchain.etherbase_account # Set the deployer address from a freshly created test account
deployer_interface.deployer_address = origin # Set the deployer address from a freshly created test account
testerchain.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT)
yield testerchain yield testerchain
testerchain.sever_connection() testerchain.sever_connection()
@ -362,7 +354,7 @@ def three_agents(testerchain):
""" """
"""Launch all Nucypher ethereum contracts""" """Launch all Nucypher ethereum contracts"""
origin, *everybody_else = testerchain.interface.w3.eth.accounts origin = testerchain.etherbase_account
token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin) token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin)
@ -394,17 +386,15 @@ def three_agents(testerchain):
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def blockchain_ursulas(three_agents, ursula_decentralized_test_config): def blockchain_ursulas(three_agents, ursula_decentralized_test_config):
token_agent, miner_agent, policy_agent = three_agents token_agent, miner_agent, policy_agent = three_agents
etherbase, alice, bob, *all_yall = token_agent.blockchain.interface.w3.eth.accounts blockchain = token_agent.blockchain
ursula_addresses = all_yall[:NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK] token_airdrop(origin=blockchain.etherbase_account,
addresses=blockchain.ursulas_accounts,
token_airdrop(origin=etherbase,
addresses=ursula_addresses,
token_agent=token_agent, token_agent=token_agent,
amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT) amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
# Leave out the last Ursula for manual stake testing # Leave out the last Ursula for manual stake testing
*all_but_the_last_ursula, the_last_ursula = ursula_addresses *all_but_the_last_ursula, the_last_ursula = blockchain.ursulas_accounts
_ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config, _ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
ether_addresses=all_but_the_last_ursula, ether_addresses=all_but_the_last_ursula,
@ -416,6 +406,6 @@ def blockchain_ursulas(three_agents, ursula_decentralized_test_config):
stake=False) stake=False)
_ursulas.extend(_non_staking_ursula) _ursulas.extend(_non_staking_ursula)
token_agent.blockchain.time_travel(periods=1) blockchain.time_travel(periods=1)
yield _ursulas yield _ursulas