2018-11-04 19:23:11 +00:00
|
|
|
"""
|
|
|
|
This file is part of nucypher.
|
|
|
|
|
|
|
|
nucypher is free software: you can redistribute it and/or modify
|
2019-03-05 02:50:11 +00:00
|
|
|
it under the terms of the GNU Affero General Public License as published by
|
2018-11-04 19:23:11 +00:00
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
nucypher is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2019-03-05 02:50:11 +00:00
|
|
|
GNU Affero General Public License for more details.
|
2018-11-04 19:23:11 +00:00
|
|
|
|
2019-03-05 02:50:11 +00:00
|
|
|
You should have received a copy of the GNU Affero General Public License
|
2018-11-04 19:23:11 +00:00
|
|
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
"""
|
2018-11-22 18:31:04 +00:00
|
|
|
|
2019-04-17 23:51:08 +00:00
|
|
|
import datetime
|
2019-08-15 03:29:24 +00:00
|
|
|
import json
|
2018-08-05 20:09:05 +00:00
|
|
|
import os
|
2019-06-11 00:19:21 +00:00
|
|
|
import random
|
2018-08-05 20:09:05 +00:00
|
|
|
import tempfile
|
2020-01-18 18:39:21 +00:00
|
|
|
from typing import Union
|
2018-11-22 18:31:04 +00:00
|
|
|
|
2018-06-23 20:48:06 +00:00
|
|
|
import maya
|
|
|
|
import pytest
|
2019-10-13 21:55:43 +00:00
|
|
|
from eth_utils import to_checksum_address
|
2018-06-23 20:48:06 +00:00
|
|
|
from sqlalchemy.engine import create_engine
|
2019-08-03 22:08:29 +00:00
|
|
|
from twisted.logger import Logger
|
2019-05-13 08:27:50 +00:00
|
|
|
from umbral import pre
|
|
|
|
from umbral.curvebn import CurveBN
|
|
|
|
from umbral.keys import UmbralPrivateKey
|
|
|
|
from umbral.signing import Signer
|
2019-06-04 15:34:02 +00:00
|
|
|
from web3 import Web3
|
2019-05-13 08:27:50 +00:00
|
|
|
|
2020-01-12 21:57:09 +00:00
|
|
|
from nucypher.blockchain.economics import StandardTokenEconomics
|
2019-12-03 02:27:06 +00:00
|
|
|
from nucypher.blockchain.eth.actors import Staker, StakeHolder
|
2019-08-12 07:15:43 +00:00
|
|
|
from nucypher.blockchain.eth.agents import NucypherTokenAgent
|
2019-05-31 16:15:47 +00:00
|
|
|
from nucypher.blockchain.eth.clients import NuCypherGethDevProcess
|
2020-01-18 18:39:21 +00:00
|
|
|
from nucypher.blockchain.eth.constants import PREALLOCATION_ESCROW_CONTRACT_NAME
|
2019-04-29 11:24:31 +00:00
|
|
|
from nucypher.blockchain.eth.deployers import (NucypherTokenDeployer,
|
2019-05-29 14:15:18 +00:00
|
|
|
StakingEscrowDeployer,
|
2019-04-29 11:24:31 +00:00
|
|
|
PolicyManagerDeployer,
|
2019-11-27 19:08:33 +00:00
|
|
|
AdjudicatorDeployer,
|
2019-12-27 02:57:26 +00:00
|
|
|
StakingInterfaceDeployer,
|
|
|
|
WorklockDeployer
|
2020-01-12 21:57:09 +00:00
|
|
|
)
|
2019-08-12 07:15:43 +00:00
|
|
|
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
2019-12-27 02:57:26 +00:00
|
|
|
from nucypher.blockchain.eth.networks import NetworksInventory
|
2020-01-18 18:39:21 +00:00
|
|
|
from nucypher.blockchain.eth.registry import (
|
|
|
|
InMemoryContractRegistry,
|
|
|
|
RegistrySourceManager,
|
|
|
|
BaseContractRegistry,
|
2020-01-17 02:45:50 +00:00
|
|
|
LocalContractRegistry,
|
2020-01-18 18:39:21 +00:00
|
|
|
IndividualAllocationRegistry,
|
|
|
|
CanonicalRegistrySource
|
|
|
|
)
|
2018-08-18 23:24:13 +00:00
|
|
|
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
2019-04-29 11:24:31 +00:00
|
|
|
from nucypher.blockchain.eth.token import NU
|
2019-12-03 02:27:06 +00:00
|
|
|
from nucypher.characters.lawful import Enrico, Bob
|
2019-11-14 02:51:50 +00:00
|
|
|
from nucypher.config.characters import AliceConfiguration
|
2019-09-01 02:09:08 +00:00
|
|
|
from nucypher.config.characters import (
|
|
|
|
UrsulaConfiguration,
|
|
|
|
BobConfiguration,
|
2019-08-15 03:29:24 +00:00
|
|
|
StakeHolderConfiguration
|
2019-09-01 02:09:08 +00:00
|
|
|
)
|
2019-06-20 17:13:13 +00:00
|
|
|
from nucypher.crypto.powers import TransactingPower
|
2019-05-13 08:27:50 +00:00
|
|
|
from nucypher.crypto.utils import canonical_address_from_umbral_key
|
2018-05-08 19:35:34 +00:00
|
|
|
from nucypher.keystore import keystore
|
|
|
|
from nucypher.keystore.db import Base
|
2019-08-14 02:17:08 +00:00
|
|
|
from nucypher.policy.collections import IndisputableEvidence, WorkOrder
|
2019-11-14 02:51:50 +00:00
|
|
|
from nucypher.utilities.logging import GlobalLoggerSettings
|
2019-03-04 22:10:12 +00:00
|
|
|
from nucypher.utilities.sandbox.blockchain import token_airdrop, TesterBlockchain
|
2019-09-01 02:09:08 +00:00
|
|
|
from nucypher.utilities.sandbox.constants import (
|
2020-01-17 02:45:50 +00:00
|
|
|
BASE_TEMP_PREFIX,
|
|
|
|
BASE_TEMP_DIR,
|
|
|
|
DATETIME_FORMAT,
|
2019-09-01 02:09:08 +00:00
|
|
|
DEVELOPMENT_ETH_AIRDROP_AMOUNT,
|
|
|
|
DEVELOPMENT_TOKEN_AIRDROP_AMOUNT,
|
2019-09-10 09:11:17 +00:00
|
|
|
MIN_STAKE_FOR_TESTS,
|
|
|
|
BONUS_TOKENS_FOR_TESTS,
|
2019-09-01 02:09:08 +00:00
|
|
|
MOCK_POLICY_DEFAULT_M,
|
|
|
|
MOCK_URSULA_STARTING_PORT,
|
2020-01-17 02:45:50 +00:00
|
|
|
MOCK_REGISTRY_FILEPATH,
|
2019-09-01 02:09:08 +00:00
|
|
|
NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK,
|
|
|
|
TEMPORARY_DOMAIN,
|
|
|
|
TEST_PROVIDER_URI,
|
|
|
|
INSECURE_DEVELOPMENT_PASSWORD,
|
|
|
|
TEST_GAS_LIMIT,
|
2019-09-10 09:11:17 +00:00
|
|
|
INSECURE_DEPLOYMENT_SECRET_HASH,
|
2019-09-01 02:09:08 +00:00
|
|
|
)
|
2018-09-13 19:32:38 +00:00
|
|
|
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
2019-11-14 03:09:18 +00:00
|
|
|
from nucypher.utilities.sandbox.middleware import MockRestMiddlewareForLargeFleetTests
|
2019-02-16 18:57:44 +00:00
|
|
|
from nucypher.utilities.sandbox.policy import generate_random_label
|
2019-11-14 02:51:50 +00:00
|
|
|
from nucypher.utilities.sandbox.ursula import make_decentralized_ursulas
|
|
|
|
from nucypher.utilities.sandbox.ursula import make_federated_ursulas
|
|
|
|
from tests.performance_mocks import mock_cert_storage, mock_cert_loading, mock_rest_app_creation, mock_cert_generation, \
|
2019-11-20 04:55:54 +00:00
|
|
|
mock_secret_source, mock_remember_node, mock_verify_node, mock_record_fleet_state, mock_message_verification, \
|
|
|
|
mock_keep_learning
|
2019-04-29 11:24:31 +00:00
|
|
|
|
2019-08-03 22:08:29 +00:00
|
|
|
test_logger = Logger("test-logger")
|
2020-02-18 12:32:05 +00:00
|
|
|
MIN_REWARD_RATE_RANGE = (5, 10, 15)
|
2018-09-17 21:06:43 +00:00
|
|
|
|
2019-11-14 02:51:50 +00:00
|
|
|
|
2018-09-17 21:06:43 +00:00
|
|
|
#
|
|
|
|
# Temporary
|
|
|
|
#
|
2018-09-16 21:35:17 +00:00
|
|
|
|
2019-09-01 02:09:08 +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
|
|
|
|
|
|
|
|
|
|
|
@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-10-29 00:37:37 +00:00
|
|
|
@pytest.fixture(scope='function')
|
|
|
|
def certificates_tempdir():
|
|
|
|
custom_filepath = '/tmp/nucypher-test-certificates-'
|
|
|
|
cert_tmpdir = tempfile.TemporaryDirectory(prefix=custom_filepath)
|
|
|
|
yield cert_tmpdir.name
|
|
|
|
cert_tmpdir.cleanup()
|
|
|
|
|
|
|
|
|
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-11-22 18:31:04 +00:00
|
|
|
ursula_config = UrsulaConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
2018-12-03 02:47:14 +00:00
|
|
|
rest_port=MOCK_URSULA_STARTING_PORT,
|
2018-09-22 22:44:37 +00:00
|
|
|
start_learning_now=False,
|
2018-09-20 19:52:21 +00:00
|
|
|
abort_on_learning_error=True,
|
2018-10-02 15:33:53 +00:00
|
|
|
federated_only=True,
|
2018-09-26 21:42:33 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
2018-10-08 18:22:28 +00:00
|
|
|
save_metadata=False,
|
2019-09-17 05:13:52 +00:00
|
|
|
reload_metadata=False,)
|
2018-09-17 21:06:43 +00:00
|
|
|
yield ursula_config
|
2018-09-24 20:59:38 +00:00
|
|
|
ursula_config.cleanup()
|
2018-09-17 21:06:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-08-14 02:17:08 +00:00
|
|
|
def ursula_decentralized_test_config(test_registry):
|
2018-11-22 18:31:04 +00:00
|
|
|
ursula_config = UrsulaConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
2019-04-30 10:07:36 +00:00
|
|
|
provider_uri=TEST_PROVIDER_URI,
|
2018-12-03 02:47:14 +00:00
|
|
|
rest_port=MOCK_URSULA_STARTING_PORT,
|
2018-09-22 22:44:37 +00:00
|
|
|
start_learning_now=False,
|
2018-09-20 19:52:21 +00:00
|
|
|
abort_on_learning_error=True,
|
2018-10-02 15:33:53 +00:00
|
|
|
federated_only=False,
|
2018-09-26 21:42:33 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
2018-10-08 18:22:28 +00:00
|
|
|
save_metadata=False,
|
2019-08-14 02:17:08 +00:00
|
|
|
reload_metadata=False,
|
|
|
|
registry=test_registry)
|
2018-09-13 19:35:44 +00:00
|
|
|
yield ursula_config
|
2018-09-24 20:59:38 +00:00
|
|
|
ursula_config.cleanup()
|
2018-09-13 19:35:44 +00:00
|
|
|
|
|
|
|
|
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-11-22 18:31:04 +00:00
|
|
|
config = AliceConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
2018-09-17 21:06:43 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
|
|
|
known_nodes=federated_ursulas,
|
|
|
|
federated_only=True,
|
2018-09-26 21:42:33 +00:00
|
|
|
abort_on_learning_error=True,
|
2018-10-08 18:22:28 +00:00
|
|
|
save_metadata=False,
|
2019-09-17 05:13:52 +00:00
|
|
|
reload_metadata=False,)
|
2018-09-17 21:06:43 +00:00
|
|
|
yield config
|
2018-09-24 20:59:38 +00:00
|
|
|
config.cleanup()
|
2018-09-17 21:06:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-08-14 02:17:08 +00:00
|
|
|
def alice_blockchain_test_config(blockchain_ursulas, testerchain, test_registry):
|
2018-11-22 18:31:04 +00:00
|
|
|
config = AliceConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
2019-04-30 10:07:36 +00:00
|
|
|
provider_uri=TEST_PROVIDER_URI,
|
2019-06-04 15:46:26 +00:00
|
|
|
checksum_address=testerchain.alice_account,
|
2018-09-17 21:06:43 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
2019-06-12 23:19:30 +00:00
|
|
|
known_nodes=blockchain_ursulas,
|
2018-09-17 21:06:43 +00:00
|
|
|
abort_on_learning_error=True,
|
2018-10-08 18:22:28 +00:00
|
|
|
save_metadata=False,
|
2019-08-14 02:17:08 +00:00
|
|
|
reload_metadata=False,
|
|
|
|
registry=test_registry)
|
2018-09-17 21:06:43 +00:00
|
|
|
yield config
|
2018-09-24 20:59:38 +00:00
|
|
|
config.cleanup()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def bob_federated_test_config():
|
2018-11-22 18:31:04 +00:00
|
|
|
config = BobConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
2018-09-24 20:59:38 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
|
|
|
start_learning_now=False,
|
|
|
|
abort_on_learning_error=True,
|
2018-09-26 21:42:33 +00:00
|
|
|
federated_only=True,
|
2018-10-08 18:22:28 +00:00
|
|
|
save_metadata=False,
|
2019-09-17 05:13:52 +00:00
|
|
|
reload_metadata=False,)
|
2018-09-24 20:59:38 +00:00
|
|
|
yield config
|
|
|
|
config.cleanup()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-08-14 02:17:08 +00:00
|
|
|
def bob_blockchain_test_config(blockchain_ursulas, testerchain, test_registry):
|
2018-11-22 18:31:04 +00:00
|
|
|
config = BobConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
2019-04-30 10:07:36 +00:00
|
|
|
provider_uri=TEST_PROVIDER_URI,
|
2019-06-04 15:46:26 +00:00
|
|
|
checksum_address=testerchain.bob_account,
|
2018-09-24 20:59:38 +00:00
|
|
|
network_middleware=MockRestMiddleware(),
|
2019-06-12 23:19:30 +00:00
|
|
|
known_nodes=blockchain_ursulas,
|
2018-09-24 20:59:38 +00:00
|
|
|
start_learning_now=False,
|
|
|
|
abort_on_learning_error=True,
|
2018-09-26 21:42:33 +00:00
|
|
|
federated_only=False,
|
2018-10-08 18:22:28 +00:00
|
|
|
save_metadata=False,
|
2019-08-14 02:17:08 +00:00
|
|
|
reload_metadata=False,
|
|
|
|
registry=test_registry)
|
2018-09-24 20:59:38 +00:00
|
|
|
yield config
|
|
|
|
config.cleanup()
|
2018-09-17 21:06:43 +00:00
|
|
|
|
2019-02-13 05:42:12 +00:00
|
|
|
|
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-09-24 20:59:38 +00:00
|
|
|
def idle_federated_policy(federated_alice, federated_bob):
|
2018-06-30 03:25:36 +00:00
|
|
|
"""
|
2018-10-28 22:15:16 +00:00
|
|
|
Creates a Policy, in a manner typical of how Alice might do it, with a unique label
|
2018-06-30 03:25:36 +00:00
|
|
|
"""
|
2019-02-10 19:56:43 +00:00
|
|
|
m = MOCK_POLICY_DEFAULT_M
|
2018-11-22 18:31:04 +00:00
|
|
|
n = NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK
|
2019-02-16 18:57:44 +00:00
|
|
|
random_label = generate_random_label()
|
2019-03-04 22:54:27 +00:00
|
|
|
policy = federated_alice.create_policy(federated_bob,
|
|
|
|
label=random_label,
|
|
|
|
m=m,
|
|
|
|
n=n,
|
2019-06-04 15:47:47 +00:00
|
|
|
expiration=maya.now() + datetime.timedelta(days=5))
|
2018-06-30 03:25:36 +00:00
|
|
|
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.
|
|
|
|
network_middleware = MockRestMiddleware()
|
|
|
|
|
2019-08-14 02:17:08 +00:00
|
|
|
idle_federated_policy.make_arrangements(network_middleware, handpicked_ursulas=federated_ursulas)
|
2018-09-17 18:54:24 +00:00
|
|
|
|
2019-06-10 23:04:12 +00:00
|
|
|
# REST call happens here, as does population of TreasureMap.
|
|
|
|
responses = idle_federated_policy.enact(network_middleware)
|
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")
|
2019-11-18 12:40:57 +00:00
|
|
|
def idle_blockchain_policy(testerchain, blockchain_alice, blockchain_bob, token_economics):
|
2018-06-29 00:23:42 +00:00
|
|
|
"""
|
2018-10-28 22:15:16 +00:00
|
|
|
Creates a Policy, in a manner typical of how Alice might do it, with a unique label
|
2018-06-29 00:23:42 +00:00
|
|
|
"""
|
2019-02-16 18:57:44 +00:00
|
|
|
random_label = generate_random_label()
|
2019-09-28 07:10:14 +00:00
|
|
|
days = token_economics.minimum_locked_periods // 2
|
2019-11-18 12:40:57 +00:00
|
|
|
now = testerchain.w3.eth.getBlock(block_identifier='latest').timestamp
|
2019-11-18 13:35:22 +00:00
|
|
|
expiration = maya.MayaDT(now).add(days=days-1)
|
2019-11-18 12:40:57 +00:00
|
|
|
n = 3
|
|
|
|
m = 2
|
2019-03-05 00:53:11 +00:00
|
|
|
policy = blockchain_alice.create_policy(blockchain_bob,
|
|
|
|
label=random_label,
|
2019-11-18 12:40:57 +00:00
|
|
|
m=m, n=n,
|
|
|
|
value=n * days * 100,
|
2019-03-05 00:53:11 +00:00
|
|
|
expiration=expiration)
|
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):
|
2019-02-14 08:23:48 +00:00
|
|
|
# Alice has a policy in mind and knows of enough qualified Ursulas; she crafts an offer for them.
|
2019-09-28 07:10:14 +00:00
|
|
|
|
|
|
|
# value and expiration were set when creating idle_blockchain_policy already
|
|
|
|
# cannot set them again
|
|
|
|
# deposit = NON_PAYMENT(b"0000000")
|
|
|
|
# contract_end_datetime = maya.now() + datetime.timedelta(days=5)
|
2018-06-06 08:32:25 +00:00
|
|
|
network_middleware = MockRestMiddleware()
|
|
|
|
|
2019-09-28 23:57:54 +00:00
|
|
|
idle_blockchain_policy.make_arrangements(
|
2019-11-14 02:51:50 +00:00
|
|
|
network_middleware, handpicked_ursulas=list(blockchain_ursulas))
|
2018-06-29 00:23:42 +00:00
|
|
|
|
2018-09-24 20:59:38 +00:00
|
|
|
idle_blockchain_policy.enact(network_middleware) # REST call happens here, as does population of TreasureMap.
|
2018-06-29 00:23:42 +00:00
|
|
|
return idle_blockchain_policy
|
2017-11-22 04:19:31 +00:00
|
|
|
|
|
|
|
|
2018-09-24 20:59:38 +00:00
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def capsule_side_channel(enacted_federated_policy):
|
2019-04-01 18:23:45 +00:00
|
|
|
class _CapsuleSideChannel:
|
|
|
|
def __init__(self):
|
2019-07-03 23:55:12 +00:00
|
|
|
self.reset()
|
2019-04-01 18:23:45 +00:00
|
|
|
|
|
|
|
def __call__(self):
|
2019-07-03 20:51:58 +00:00
|
|
|
message = "Welcome to flippering number {}.".format(len(self.messages)).encode()
|
2019-08-18 09:23:56 +00:00
|
|
|
message_kit, _signature = self.enrico.encrypt_message(message)
|
|
|
|
self.messages.append((message_kit, self.enrico))
|
2019-08-22 08:34:22 +00:00
|
|
|
if self.plaintext_passthrough:
|
|
|
|
self.plaintexts.append(message)
|
2019-08-18 09:23:56 +00:00
|
|
|
return message_kit
|
2019-09-29 05:19:53 +00:00
|
|
|
|
2019-08-22 08:34:22 +00:00
|
|
|
def reset(self, plaintext_passthrough=False):
|
2019-08-18 09:23:56 +00:00
|
|
|
self.enrico = Enrico(policy_encrypting_key=enacted_federated_policy.public_key)
|
2019-09-29 05:19:53 +00:00
|
|
|
self.messages = []
|
2019-08-22 08:34:22 +00:00
|
|
|
self.plaintexts = []
|
|
|
|
self.plaintext_passthrough = plaintext_passthrough
|
2019-08-18 10:32:58 +00:00
|
|
|
return self(), self.enrico
|
2019-09-29 05:19:53 +00:00
|
|
|
|
|
|
|
return _CapsuleSideChannel()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def capsule_side_channel_blockchain(enacted_blockchain_policy):
|
|
|
|
class _CapsuleSideChannel:
|
|
|
|
def __init__(self):
|
|
|
|
self.reset()
|
|
|
|
|
|
|
|
def __call__(self):
|
|
|
|
message = "Welcome to flippering number {}.".format(len(self.messages)).encode()
|
2020-02-16 00:58:48 +00:00
|
|
|
message_kit, _signature = self.enrico.encrypt_message(message)
|
|
|
|
self.messages.append((message_kit, self.enrico))
|
|
|
|
if self.plaintext_passthrough:
|
|
|
|
self.plaintexts.append(message)
|
|
|
|
return message_kit
|
2019-04-01 18:23:45 +00:00
|
|
|
|
2020-02-16 00:58:48 +00:00
|
|
|
def reset(self, plaintext_passthrough=False):
|
|
|
|
self.enrico = Enrico(policy_encrypting_key=enacted_blockchain_policy.public_key)
|
2019-07-03 23:55:12 +00:00
|
|
|
self.messages = []
|
2020-02-16 00:58:48 +00:00
|
|
|
self.plaintexts = []
|
|
|
|
self.plaintext_passthrough = plaintext_passthrough
|
|
|
|
return self(), self.enrico
|
2019-07-03 23:55:12 +00:00
|
|
|
|
2019-04-01 18:23:45 +00:00
|
|
|
return _CapsuleSideChannel()
|
2018-09-24 20:59:38 +00:00
|
|
|
|
|
|
|
|
2019-02-16 20:36:08 +00:00
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def random_policy_label():
|
|
|
|
yield generate_random_label()
|
|
|
|
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
#
|
2018-09-24 20:59:38 +00:00
|
|
|
# Alice, Bob, and Ursula
|
2018-06-29 00:23:42 +00:00
|
|
|
#
|
2017-12-08 04:41:04 +00:00
|
|
|
|
2017-12-15 05:21:09 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2018-09-24 20:59:38 +00:00
|
|
|
def federated_alice(alice_federated_test_config):
|
|
|
|
_alice = alice_federated_test_config.produce()
|
|
|
|
return _alice
|
2018-09-17 18:54:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-07-11 20:13:03 +00:00
|
|
|
def blockchain_alice(alice_blockchain_test_config, testerchain):
|
2019-07-12 21:46:45 +00:00
|
|
|
_alice = alice_blockchain_test_config.produce()
|
2018-09-24 20:59:38 +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-09-24 20:59:38 +00:00
|
|
|
def federated_bob(bob_federated_test_config):
|
|
|
|
_bob = bob_federated_test_config.produce()
|
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")
|
2019-07-11 20:13:03 +00:00
|
|
|
def blockchain_bob(bob_blockchain_test_config, testerchain):
|
2019-07-12 21:46:45 +00:00
|
|
|
_bob = bob_blockchain_test_config.produce()
|
2018-09-24 20:59:38 +00:00
|
|
|
return _bob
|
2018-06-29 00:23:42 +00:00
|
|
|
|
|
|
|
|
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-24 20:59:38 +00:00
|
|
|
_ursulas = make_federated_ursulas(ursula_config=ursula_federated_test_config,
|
2018-11-22 18:31:04 +00:00
|
|
|
quantity=NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK)
|
2018-09-24 20:59:38 +00:00
|
|
|
yield _ursulas
|
2017-12-08 04:41:26 +00:00
|
|
|
|
2019-04-10 09:46:22 +00:00
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
#
|
2019-04-10 09:46:22 +00:00
|
|
|
# Blockchain
|
2018-06-29 00:23:42 +00:00
|
|
|
#
|
|
|
|
|
2020-01-12 21:57:09 +00:00
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def token_economics(testerchain):
|
|
|
|
|
|
|
|
# Get current blocktime
|
|
|
|
blockchain = BlockchainInterfaceFactory.get_interface()
|
|
|
|
now = blockchain.w3.eth.getBlock(block_identifier='latest').timestamp
|
|
|
|
|
|
|
|
# Calculate instant start time
|
|
|
|
one_hour_in_seconds = (60 * 60)
|
|
|
|
start_date = now
|
|
|
|
bidding_start_date = start_date
|
|
|
|
|
|
|
|
# Ends in one hour
|
|
|
|
bidding_end_date = start_date + one_hour_in_seconds
|
|
|
|
|
|
|
|
economics = StandardTokenEconomics(
|
|
|
|
worklock_boosting_refund_rate=200,
|
2020-01-13 00:02:19 +00:00
|
|
|
worklock_commitment_duration=60*60, # seconds
|
2020-01-13 18:34:34 +00:00
|
|
|
worklock_supply=NU.from_tokens(1_000_000),
|
2020-01-12 21:57:09 +00:00
|
|
|
bidding_start_date=bidding_start_date,
|
|
|
|
bidding_end_date=bidding_end_date
|
|
|
|
)
|
2019-03-20 03:38:29 +00:00
|
|
|
return economics
|
2018-09-24 20:59:38 +00:00
|
|
|
|
2019-04-25 13:13:46 +00:00
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
@pytest.fixture(scope='session')
|
|
|
|
def solidity_compiler():
|
|
|
|
"""Doing this more than once per session will result in slower test run times."""
|
2019-06-17 23:24:37 +00:00
|
|
|
compiler = SolidityCompiler()
|
2018-06-29 00:23:42 +00:00
|
|
|
yield compiler
|
|
|
|
|
|
|
|
|
2019-08-12 07:15:43 +00:00
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def test_registry():
|
|
|
|
registry = InMemoryContractRegistry()
|
|
|
|
return registry
|
|
|
|
|
|
|
|
|
2019-07-05 15:02:11 +00:00
|
|
|
def _make_testerchain():
|
2018-04-13 00:24:55 +00:00
|
|
|
"""
|
2019-06-17 21:10:19 +00:00
|
|
|
https://github.com/ethereum/eth-tester # available-backends
|
2018-04-13 00:24:55 +00:00
|
|
|
"""
|
2019-08-21 06:18:13 +00:00
|
|
|
# Monkey patch to prevent gas adjustment
|
|
|
|
import eth
|
|
|
|
eth._utils.headers.GAS_LIMIT_MINIMUM = TEST_GAS_LIMIT
|
|
|
|
eth._utils.headers.GENESIS_GAS_LIMIT = TEST_GAS_LIMIT
|
|
|
|
eth.vm.forks.frontier.headers.GENESIS_GAS_LIMIT = TEST_GAS_LIMIT
|
2019-09-10 15:34:20 +00:00
|
|
|
|
|
|
|
# Monkey patch to prevent gas estimates
|
|
|
|
def _get_buffered_gas_estimate(web3, transaction, gas_buffer=100000):
|
|
|
|
return TEST_GAS_LIMIT
|
|
|
|
|
|
|
|
import web3
|
|
|
|
web3.eth.get_buffered_gas_estimate = _get_buffered_gas_estimate
|
|
|
|
|
2018-06-29 00:23:42 +00:00
|
|
|
# Create the blockchain
|
2019-06-17 23:24:37 +00:00
|
|
|
testerchain = TesterBlockchain(eth_airdrop=True, free_transactions=True)
|
2020-02-15 22:39:43 +00:00
|
|
|
|
|
|
|
BlockchainInterfaceFactory.register_interface(interface=testerchain, force=True)
|
2019-06-20 01:31:00 +00:00
|
|
|
|
2019-06-21 04:45:28 +00:00
|
|
|
# Mock TransactingPower Consumption (Deployer)
|
2019-08-12 07:15:43 +00:00
|
|
|
testerchain.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
|
|
|
|
account=testerchain.etherbase_account)
|
2019-07-11 20:13:03 +00:00
|
|
|
testerchain.transacting_power.activate()
|
2019-07-05 15:02:11 +00:00
|
|
|
return testerchain
|
|
|
|
|
2019-07-02 05:36:02 +00:00
|
|
|
|
2019-07-05 15:02:11 +00:00
|
|
|
@pytest.fixture(scope='session')
|
2019-08-12 07:15:43 +00:00
|
|
|
def _testerchain():
|
2019-07-05 15:02:11 +00:00
|
|
|
testerchain = _make_testerchain()
|
2018-06-29 00:23:42 +00:00
|
|
|
yield testerchain
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
2019-08-12 07:15:43 +00:00
|
|
|
def testerchain(_testerchain):
|
|
|
|
testerchain = _testerchain
|
2019-07-10 13:10:45 +00:00
|
|
|
|
2019-09-09 14:28:51 +00:00
|
|
|
# Reset chain state
|
|
|
|
pyevm_backend = testerchain.provider.ethereum_tester.backend
|
2019-09-15 15:22:27 +00:00
|
|
|
snapshot = pyevm_backend.chain.get_canonical_block_by_number(0).hash
|
|
|
|
pyevm_backend.revert_to_snapshot(snapshot)
|
2019-09-09 14:28:51 +00:00
|
|
|
|
2019-07-10 13:10:45 +00:00
|
|
|
coinbase, *addresses = testerchain.client.accounts
|
|
|
|
|
|
|
|
for address in addresses:
|
|
|
|
balance = testerchain.client.get_balance(address)
|
|
|
|
spent = DEVELOPMENT_ETH_AIRDROP_AMOUNT - balance
|
|
|
|
|
2019-08-12 07:15:43 +00:00
|
|
|
if spent > 0:
|
|
|
|
tx = {'to': address, 'from': coinbase, 'value': spent}
|
2019-07-10 13:10:45 +00:00
|
|
|
txhash = testerchain.w3.eth.sendTransaction(tx)
|
|
|
|
|
|
|
|
_receipt = testerchain.wait_for_receipt(txhash)
|
|
|
|
eth_amount = Web3().fromWei(spent, 'ether')
|
|
|
|
testerchain.log.info("Airdropped {} ETH {} -> {}".format(eth_amount, tx['from'], tx['to']))
|
2019-07-05 15:02:11 +00:00
|
|
|
yield testerchain
|
2019-07-02 05:36:02 +00:00
|
|
|
|
2019-07-05 15:02:11 +00:00
|
|
|
|
2019-12-27 02:57:26 +00:00
|
|
|
def _make_agency(testerchain, test_registry, token_economics):
|
2019-07-05 15:02:11 +00:00
|
|
|
"""
|
|
|
|
Launch the big three contracts on provided chain,
|
|
|
|
make agents for each and return them.
|
|
|
|
"""
|
2019-11-14 02:51:50 +00:00
|
|
|
|
2019-11-25 21:31:48 +00:00
|
|
|
# Mock TransactingPower Consumption (Deployer)
|
|
|
|
testerchain.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
|
|
|
|
account=testerchain.etherbase_account)
|
|
|
|
testerchain.transacting_power.activate()
|
2019-11-14 02:51:50 +00:00
|
|
|
|
2019-04-10 09:46:22 +00:00
|
|
|
origin = testerchain.etherbase_account
|
2018-06-29 00:23:42 +00:00
|
|
|
|
2019-12-27 02:57:26 +00:00
|
|
|
token_deployer = NucypherTokenDeployer(deployer_address=origin,
|
|
|
|
economics=token_economics,
|
|
|
|
registry=test_registry)
|
2018-06-29 00:23:42 +00:00
|
|
|
token_deployer.deploy()
|
|
|
|
|
2019-12-27 02:57:26 +00:00
|
|
|
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin,
|
|
|
|
economics=token_economics,
|
|
|
|
registry=test_registry,
|
|
|
|
test_mode=True)
|
2019-09-01 02:09:08 +00:00
|
|
|
staking_escrow_deployer.deploy(secret_hash=INSECURE_DEPLOYMENT_SECRET_HASH)
|
2018-10-26 14:48:10 +00:00
|
|
|
|
2019-12-27 02:57:26 +00:00
|
|
|
policy_manager_deployer = PolicyManagerDeployer(deployer_address=origin,
|
|
|
|
economics=token_economics,
|
|
|
|
registry=test_registry)
|
2019-09-01 02:09:08 +00:00
|
|
|
policy_manager_deployer.deploy(secret_hash=INSECURE_DEPLOYMENT_SECRET_HASH)
|
2018-06-29 00:23:42 +00:00
|
|
|
|
2019-12-27 02:57:26 +00:00
|
|
|
adjudicator_deployer = AdjudicatorDeployer(deployer_address=origin,
|
|
|
|
economics=token_economics,
|
|
|
|
registry=test_registry)
|
2019-09-01 02:09:08 +00:00
|
|
|
adjudicator_deployer.deploy(secret_hash=INSECURE_DEPLOYMENT_SECRET_HASH)
|
2019-06-23 23:44:35 +00:00
|
|
|
|
2019-12-27 02:57:26 +00:00
|
|
|
staking_interface_deployer = StakingInterfaceDeployer(deployer_address=origin,
|
|
|
|
economics=token_economics,
|
|
|
|
registry=test_registry)
|
2019-10-17 11:03:29 +00:00
|
|
|
staking_interface_deployer.deploy(secret_hash=INSECURE_DEPLOYMENT_SECRET_HASH)
|
2019-06-23 23:44:35 +00:00
|
|
|
|
2019-12-27 02:57:26 +00:00
|
|
|
worklock_deployer = WorklockDeployer(deployer_address=origin,
|
|
|
|
economics=token_economics,
|
|
|
|
registry=test_registry)
|
|
|
|
worklock_deployer.deploy()
|
|
|
|
|
|
|
|
token_agent = token_deployer.make_agent() # 1 Token
|
|
|
|
staking_agent = staking_escrow_deployer.make_agent() # 2 Staking Escrow
|
|
|
|
policy_agent = policy_manager_deployer.make_agent() # 3 Policy Agent
|
|
|
|
_adjudicator_agent = adjudicator_deployer.make_agent() # 4 Adjudicator
|
|
|
|
_worklock_agent = worklock_deployer.make_agent() # 5 Worklock
|
2019-07-28 01:46:19 +00:00
|
|
|
|
2020-02-18 12:32:05 +00:00
|
|
|
# Set additional parameters
|
|
|
|
minimum, default, maximum = MIN_REWARD_RATE_RANGE
|
|
|
|
txhash = policy_agent.contract.functions.setMinRewardRateRange(minimum, default, maximum).transact()
|
|
|
|
_receipt = testerchain.wait_for_receipt(txhash)
|
|
|
|
|
2019-07-28 01:46:19 +00:00
|
|
|
# TODO: Get rid of returning these agents here.
|
2019-06-23 23:44:35 +00:00
|
|
|
# What's important is deploying and creating the first agent for each contract,
|
|
|
|
# and since agents are singletons, in tests it's only necessary to call the agent
|
2019-07-02 05:36:02 +00:00
|
|
|
# constructor again to receive the existing agent.
|
|
|
|
#
|
|
|
|
# For example:
|
2019-06-23 23:44:35 +00:00
|
|
|
# staking_agent = StakingEscrowAgent()
|
2019-07-02 05:36:02 +00:00
|
|
|
#
|
2019-06-23 23:44:35 +00:00
|
|
|
# This is more clear than how we currently obtain an agent instance in tests:
|
|
|
|
# _, staking_agent, _ = agency
|
2019-07-02 05:36:02 +00:00
|
|
|
#
|
2019-06-23 23:44:35 +00:00
|
|
|
# Other advantages is that it's closer to how agents should be use (i.e., there
|
|
|
|
# are no fixtures IRL) and it's more extensible (e.g., AdjudicatorAgent)
|
2019-04-04 02:26:37 +00:00
|
|
|
|
2019-07-05 15:02:11 +00:00
|
|
|
return token_agent, staking_agent, policy_agent
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
2020-01-18 18:39:21 +00:00
|
|
|
def test_registry_source_manager(testerchain, test_registry):
|
|
|
|
|
|
|
|
class MockRegistrySource(CanonicalRegistrySource):
|
|
|
|
name = "Mock Registry Source"
|
|
|
|
is_primary = False
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if self.network != TEMPORARY_DOMAIN:
|
|
|
|
raise ValueError(f"Somehow, MockRegistrySource is trying to get a registry for '{self.network}'. "
|
|
|
|
f"Only '{TEMPORARY_DOMAIN}' is supported.'")
|
|
|
|
factory = testerchain.get_contract_factory(contract_name=PREALLOCATION_ESCROW_CONTRACT_NAME)
|
|
|
|
preallocation_escrow_abi = factory.abi
|
|
|
|
self.allocation_template = {
|
|
|
|
"BENEFICIARY_ADDRESS": ["ALLOCATION_CONTRACT_ADDRESS", preallocation_escrow_abi]
|
|
|
|
}
|
|
|
|
|
|
|
|
def get_publication_endpoint(self) -> str:
|
|
|
|
return f":mock-registry-source:/{self.network}/{self.registry_name}"
|
|
|
|
|
|
|
|
def fetch_latest_publication(self) -> Union[str, bytes]:
|
|
|
|
self.logger.debug(f"Reading registry at {self.get_publication_endpoint()}")
|
|
|
|
if self.registry_name == BaseContractRegistry.REGISTRY_NAME:
|
|
|
|
registry_data = test_registry.read()
|
|
|
|
elif self.registry_name == IndividualAllocationRegistry.REGISTRY_NAME:
|
|
|
|
registry_data = self.allocation_template
|
|
|
|
raw_registry_data = json.dumps(registry_data)
|
|
|
|
return raw_registry_data
|
|
|
|
|
|
|
|
RegistrySourceManager._FALLBACK_CHAIN = (MockRegistrySource,)
|
|
|
|
NetworksInventory.networks = (TEMPORARY_DOMAIN,)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
2019-12-27 02:57:26 +00:00
|
|
|
def agency(testerchain, test_registry, token_economics, test_registry_source_manager):
|
|
|
|
agents = _make_agency(testerchain=testerchain,
|
|
|
|
test_registry=test_registry,
|
|
|
|
token_economics=token_economics)
|
2019-07-05 15:02:11 +00:00
|
|
|
yield agents
|
|
|
|
|
|
|
|
|
2020-01-17 02:45:50 +00:00
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def agency_local_registry(testerchain, agency, test_registry):
|
|
|
|
registry = LocalContractRegistry(filepath=MOCK_REGISTRY_FILEPATH)
|
|
|
|
registry.write(test_registry.read())
|
|
|
|
yield registry
|
|
|
|
if os.path.exists(MOCK_REGISTRY_FILEPATH):
|
|
|
|
os.remove(MOCK_REGISTRY_FILEPATH)
|
|
|
|
|
|
|
|
|
2019-03-04 22:10:12 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2019-08-12 07:15:43 +00:00
|
|
|
def stakers(testerchain, agency, token_economics, test_registry):
|
2019-05-29 14:15:18 +00:00
|
|
|
token_agent, _staking_agent, _policy_agent = agency
|
2019-04-10 09:46:22 +00:00
|
|
|
blockchain = token_agent.blockchain
|
2019-03-04 22:10:12 +00:00
|
|
|
|
2019-06-20 20:34:50 +00:00
|
|
|
# Mock Powerup consumption (Deployer)
|
2019-08-12 07:15:43 +00:00
|
|
|
blockchain.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
|
2019-06-20 17:13:13 +00:00
|
|
|
account=blockchain.etherbase_account)
|
2019-06-21 04:45:28 +00:00
|
|
|
blockchain.transacting_power.activate()
|
2019-06-20 20:34:50 +00:00
|
|
|
|
2019-04-10 09:46:22 +00:00
|
|
|
token_airdrop(origin=blockchain.etherbase_account,
|
2019-06-11 00:19:21 +00:00
|
|
|
addresses=blockchain.stakers_accounts,
|
2019-03-04 22:10:12 +00:00
|
|
|
token_agent=token_agent,
|
|
|
|
amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
|
|
|
|
|
2019-06-11 00:19:21 +00:00
|
|
|
stakers = list()
|
|
|
|
for index, account in enumerate(blockchain.stakers_accounts):
|
2019-08-12 07:15:43 +00:00
|
|
|
staker = Staker(is_me=True, checksum_address=account, registry=test_registry)
|
2019-03-04 22:10:12 +00:00
|
|
|
|
2019-06-20 17:13:13 +00:00
|
|
|
# Mock TransactingPower consumption
|
2019-08-12 07:15:43 +00:00
|
|
|
staker.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=account)
|
|
|
|
staker.transacting_power.activate()
|
2019-06-20 01:31:00 +00:00
|
|
|
|
2019-09-10 09:11:17 +00:00
|
|
|
amount = MIN_STAKE_FOR_TESTS + random.randrange(BONUS_TOKENS_FOR_TESTS)
|
2019-06-11 00:19:21 +00:00
|
|
|
|
2019-08-21 12:11:39 +00:00
|
|
|
# for a random lock duration
|
2019-06-21 13:49:06 +00:00
|
|
|
min_locktime, max_locktime = token_economics.minimum_locked_periods, token_economics.maximum_rewarded_periods
|
2019-06-11 00:19:21 +00:00
|
|
|
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)
|
2019-03-04 22:10:12 +00:00
|
|
|
|
2019-05-31 15:26:05 +00:00
|
|
|
# Stake starts next period (or else signature validation will fail)
|
|
|
|
blockchain.time_travel(periods=1)
|
|
|
|
|
2019-06-11 00:19:21 +00:00
|
|
|
yield stakers
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-08-14 02:17:08 +00:00
|
|
|
def blockchain_ursulas(testerchain, stakers, ursula_decentralized_test_config):
|
|
|
|
_ursulas = make_decentralized_ursulas(ursula_config=ursula_decentralized_test_config,
|
2019-06-11 00:19:21 +00:00
|
|
|
stakers_addresses=testerchain.stakers_accounts,
|
|
|
|
workers_addresses=testerchain.ursulas_accounts,
|
|
|
|
confirm_activity=True)
|
2020-02-16 00:58:48 +00:00
|
|
|
for u in _ursulas:
|
|
|
|
u.synchronous_query_timeout = .01 # We expect to never have to wait for content that is actually on-chain during tests.
|
2019-06-11 00:19:21 +00:00
|
|
|
testerchain.time_travel(periods=1)
|
|
|
|
|
2019-05-31 15:26:05 +00:00
|
|
|
# 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)
|
|
|
|
|
2019-03-04 22:10:12 +00:00
|
|
|
yield _ursulas
|
|
|
|
|
2019-04-29 11:24:31 +00:00
|
|
|
|
2019-06-20 13:10:11 +00:00
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def idle_staker(testerchain, agency):
|
|
|
|
token_agent, _staking_agent, _policy_agent = agency
|
|
|
|
|
|
|
|
idle_staker_account = testerchain.unassigned_accounts[-2]
|
2019-06-26 11:18:51 +00:00
|
|
|
|
|
|
|
# Mock Powerup consumption (Deployer)
|
2019-08-12 07:15:43 +00:00
|
|
|
testerchain.transacting_power = TransactingPower(account=testerchain.etherbase_account)
|
2019-06-20 13:10:11 +00:00
|
|
|
|
|
|
|
token_airdrop(origin=testerchain.etherbase_account,
|
2019-06-26 11:18:51 +00:00
|
|
|
addresses=[idle_staker_account],
|
2019-06-20 13:10:11 +00:00
|
|
|
token_agent=token_agent,
|
|
|
|
amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
|
|
|
|
|
|
|
|
# Prepare idle staker
|
2019-06-26 11:18:51 +00:00
|
|
|
idle_staker = Staker(is_me=True,
|
|
|
|
checksum_address=idle_staker_account,
|
|
|
|
blockchain=testerchain)
|
2019-06-20 13:10:11 +00:00
|
|
|
yield idle_staker
|
|
|
|
|
|
|
|
|
2019-04-29 11:24:31 +00:00
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def stake_value(token_economics):
|
|
|
|
value = NU(token_economics.minimum_allowed_locked * 2, 'NuNit')
|
|
|
|
return value
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def policy_rate():
|
|
|
|
rate = Web3.toWei(21, 'gwei')
|
|
|
|
return rate
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def policy_value(token_economics, policy_rate):
|
2019-04-30 10:07:36 +00:00
|
|
|
value = policy_rate * token_economics.minimum_locked_periods
|
2019-04-29 11:24:31 +00:00
|
|
|
return value
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
2019-08-12 07:15:43 +00:00
|
|
|
def funded_blockchain(testerchain, agency, token_economics, test_registry):
|
2019-04-29 11:24:31 +00:00
|
|
|
# Who are ya'?
|
2019-06-18 23:59:55 +00:00
|
|
|
deployer_address, *everyone_else, staking_participant = testerchain.client.accounts
|
2019-04-29 11:24:31 +00:00
|
|
|
|
|
|
|
# Free ETH!!!
|
2019-04-30 10:07:36 +00:00
|
|
|
testerchain.ether_airdrop(amount=DEVELOPMENT_ETH_AIRDROP_AMOUNT)
|
2019-04-29 11:24:31 +00:00
|
|
|
|
|
|
|
# Free Tokens!!!
|
2019-08-12 07:15:43 +00:00
|
|
|
token_airdrop(token_agent=NucypherTokenAgent(registry=test_registry),
|
2019-04-30 08:24:30 +00:00
|
|
|
origin=deployer_address,
|
2019-04-29 11:24:31 +00:00
|
|
|
addresses=everyone_else,
|
2019-11-14 02:51:50 +00:00
|
|
|
amount=token_economics.minimum_allowed_locked * 5)
|
2019-04-29 11:24:31 +00:00
|
|
|
|
|
|
|
# HERE YOU GO
|
2019-04-30 10:07:36 +00:00
|
|
|
yield testerchain, deployer_address
|
2019-04-29 11:24:31 +00:00
|
|
|
|
|
|
|
|
2019-05-13 08:27:50 +00:00
|
|
|
#
|
|
|
|
# Re-Encryption
|
|
|
|
#
|
|
|
|
|
|
|
|
def _mock_ursula_reencrypts(ursula, corrupt_cfrag: bool = False):
|
|
|
|
delegating_privkey = UmbralPrivateKey.gen_key()
|
|
|
|
_symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey())
|
|
|
|
signing_privkey = UmbralPrivateKey.gen_key()
|
|
|
|
signing_pubkey = signing_privkey.get_pubkey()
|
|
|
|
signer = Signer(signing_privkey)
|
|
|
|
priv_key_bob = UmbralPrivateKey.gen_key()
|
|
|
|
pub_key_bob = priv_key_bob.get_pubkey()
|
|
|
|
kfrags = pre.generate_kfrags(delegating_privkey=delegating_privkey,
|
|
|
|
signer=signer,
|
|
|
|
receiving_pubkey=pub_key_bob,
|
|
|
|
threshold=2,
|
|
|
|
N=4,
|
|
|
|
sign_delegating_key=False,
|
|
|
|
sign_receiving_key=False)
|
|
|
|
capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_pubkey)
|
|
|
|
|
|
|
|
ursula_pubkey = ursula.stamp.as_umbral_pubkey()
|
|
|
|
|
|
|
|
alice_address = canonical_address_from_umbral_key(signing_pubkey)
|
|
|
|
blockhash = bytes(32)
|
|
|
|
|
2019-06-17 12:49:28 +00:00
|
|
|
specification = b''.join((bytes(capsule),
|
|
|
|
bytes(ursula_pubkey),
|
|
|
|
bytes(ursula.decentralized_identity_evidence),
|
|
|
|
alice_address,
|
|
|
|
blockhash))
|
2019-05-13 08:27:50 +00:00
|
|
|
|
|
|
|
bobs_signer = Signer(priv_key_bob)
|
|
|
|
task_signature = bytes(bobs_signer(specification))
|
|
|
|
|
|
|
|
metadata = bytes(ursula.stamp(task_signature))
|
|
|
|
|
|
|
|
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata)
|
|
|
|
|
|
|
|
if corrupt_cfrag:
|
|
|
|
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
|
|
|
|
|
|
|
|
cfrag_signature = bytes(ursula.stamp(bytes(cfrag)))
|
|
|
|
|
|
|
|
bob = Bob.from_public_keys(verifying_key=pub_key_bob)
|
2019-08-10 00:30:24 +00:00
|
|
|
task = WorkOrder.PRETask(capsule, task_signature, cfrag, cfrag_signature)
|
2019-05-13 08:27:50 +00:00
|
|
|
work_order = WorkOrder(bob, None, alice_address, [task], None, ursula, blockhash)
|
|
|
|
|
|
|
|
evidence = IndisputableEvidence(task, work_order)
|
|
|
|
return evidence
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
|
|
|
def mock_ursula_reencrypts():
|
|
|
|
return _mock_ursula_reencrypts
|
2019-05-31 16:15:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
2019-07-17 00:09:23 +00:00
|
|
|
def instant_geth_dev_node():
|
2019-05-31 16:15:47 +00:00
|
|
|
geth = NuCypherGethDevProcess()
|
|
|
|
try:
|
|
|
|
yield geth
|
|
|
|
finally:
|
|
|
|
if geth.is_running:
|
|
|
|
geth.stop()
|
|
|
|
assert not geth.is_running
|
2019-07-17 02:50:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
|
|
|
def stakeholder_config_file_location():
|
|
|
|
path = os.path.join('/', 'tmp', 'nucypher-test-stakeholder.json')
|
|
|
|
if os.path.exists(path):
|
|
|
|
os.remove(path)
|
|
|
|
yield path
|
|
|
|
if os.path.exists(path):
|
|
|
|
os.remove(path)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
2019-08-12 07:15:43 +00:00
|
|
|
def software_stakeholder(testerchain, agency, stakeholder_config_file_location, test_registry):
|
|
|
|
token_agent, staking_agent, policy_agent = agency
|
2019-07-17 02:50:51 +00:00
|
|
|
|
|
|
|
# Setup
|
|
|
|
path = stakeholder_config_file_location
|
|
|
|
if os.path.exists(path):
|
|
|
|
os.remove(path)
|
|
|
|
|
|
|
|
# 0xaAa482c790b4301bE18D75A0D1B11B2ACBEF798B
|
|
|
|
stakeholder_private_key = '255f64a948eeb1595b8a2d1e76740f4683eca1c8f1433d13293db9b6e27676cc'
|
|
|
|
address = testerchain.provider.ethereum_tester.add_account(stakeholder_private_key,
|
|
|
|
password=INSECURE_DEVELOPMENT_PASSWORD)
|
|
|
|
|
|
|
|
testerchain.provider.ethereum_tester.unlock_account(address, password=INSECURE_DEVELOPMENT_PASSWORD)
|
|
|
|
|
|
|
|
tx = {'to': address,
|
|
|
|
'from': testerchain.etherbase_account,
|
|
|
|
'value': Web3.toWei('1', 'ether')}
|
|
|
|
|
|
|
|
txhash = testerchain.client.w3.eth.sendTransaction(tx)
|
|
|
|
_receipt = testerchain.wait_for_receipt(txhash)
|
|
|
|
|
|
|
|
# Mock TransactingPower consumption (Etherbase)
|
|
|
|
transacting_power = TransactingPower(account=testerchain.etherbase_account,
|
2019-08-12 07:15:43 +00:00
|
|
|
password=INSECURE_DEVELOPMENT_PASSWORD)
|
2019-07-17 02:50:51 +00:00
|
|
|
transacting_power.activate()
|
|
|
|
|
|
|
|
token_agent.transfer(amount=NU(200_000, 'NU').to_nunits(),
|
|
|
|
sender_address=testerchain.etherbase_account,
|
|
|
|
target_address=address)
|
|
|
|
|
|
|
|
# Create stakeholder from on-chain values given accounts over a web3 provider
|
2019-08-15 03:29:24 +00:00
|
|
|
stakeholder = StakeHolder(registry=test_registry, initial_address=address)
|
2019-07-17 02:50:51 +00:00
|
|
|
|
|
|
|
# Teardown
|
|
|
|
yield stakeholder
|
|
|
|
if os.path.exists(path):
|
|
|
|
os.remove(path)
|
|
|
|
|
|
|
|
|
2019-08-15 03:29:24 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2020-01-17 02:45:50 +00:00
|
|
|
def stakeholder_configuration(testerchain, agency_local_registry):
|
2019-08-15 03:29:24 +00:00
|
|
|
config = StakeHolderConfiguration(provider_uri=testerchain.provider_uri,
|
2020-01-17 02:45:50 +00:00
|
|
|
registry_filepath=agency_local_registry.filepath)
|
2019-08-15 03:29:24 +00:00
|
|
|
return config
|
|
|
|
|
|
|
|
|
2019-07-17 02:50:51 +00:00
|
|
|
@pytest.fixture(scope='module')
|
2019-08-12 07:15:43 +00:00
|
|
|
def manual_staker(testerchain, agency):
|
|
|
|
token_agent, staking_agent, policy_agent = agency
|
|
|
|
|
2019-07-17 02:50:51 +00:00
|
|
|
# 0xaaa23A5c74aBA6ca5E7c09337d5317A7C4563075
|
|
|
|
staker_private_key = '13378db1c2af06933000504838afc2d52efa383206454deefb1836f8f4cd86f8'
|
|
|
|
address = testerchain.provider.ethereum_tester.add_account(staker_private_key,
|
|
|
|
password=INSECURE_DEVELOPMENT_PASSWORD)
|
|
|
|
|
|
|
|
tx = {'to': address,
|
|
|
|
'from': testerchain.etherbase_account,
|
|
|
|
'value': Web3.toWei('1', 'ether')}
|
|
|
|
|
|
|
|
txhash = testerchain.client.w3.eth.sendTransaction(tx)
|
|
|
|
_receipt = testerchain.wait_for_receipt(txhash)
|
2019-07-22 23:08:40 +00:00
|
|
|
|
|
|
|
token_agent.transfer(amount=NU(200_000, 'NU').to_nunits(),
|
|
|
|
sender_address=testerchain.etherbase_account,
|
|
|
|
target_address=address)
|
|
|
|
|
2019-07-17 02:50:51 +00:00
|
|
|
yield address
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def manual_worker(testerchain):
|
2019-12-04 05:04:59 +00:00
|
|
|
worker_private_key = os.urandom(32).hex()
|
2019-07-17 02:50:51 +00:00
|
|
|
address = testerchain.provider.ethereum_tester.add_account(worker_private_key,
|
|
|
|
password=INSECURE_DEVELOPMENT_PASSWORD)
|
|
|
|
|
|
|
|
tx = {'to': address,
|
|
|
|
'from': testerchain.etherbase_account,
|
|
|
|
'value': Web3.toWei('1', 'ether')}
|
|
|
|
|
|
|
|
txhash = testerchain.client.w3.eth.sendTransaction(tx)
|
|
|
|
_receipt = testerchain.wait_for_receipt(txhash)
|
|
|
|
yield address
|
2019-08-03 22:08:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Test logging
|
|
|
|
#
|
|
|
|
|
|
|
|
@pytest.fixture(autouse=True, scope='function')
|
|
|
|
def log_in_and_out_of_test(request):
|
|
|
|
test_name = request.node.name
|
|
|
|
module_name = request.module.__name__
|
|
|
|
test_logger.info(f"Starting {module_name}.py::{test_name}")
|
|
|
|
yield
|
2019-08-12 07:15:43 +00:00
|
|
|
test_logger.info(f"Finalized {module_name}.py::{test_name}")
|
2019-08-14 02:17:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def deploy_contract(testerchain, test_registry):
|
|
|
|
def wrapped(contract_name, *args, **kwargs):
|
|
|
|
return testerchain.deploy_contract(testerchain.etherbase_account,
|
|
|
|
test_registry,
|
|
|
|
contract_name,
|
|
|
|
*args,
|
|
|
|
**kwargs)
|
|
|
|
|
|
|
|
return wrapped
|
2019-08-15 03:29:24 +00:00
|
|
|
|
|
|
|
|
2019-10-13 21:55:43 +00:00
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def get_random_checksum_address():
|
|
|
|
def _get_random_checksum_address():
|
|
|
|
canonical_address = os.urandom(20)
|
|
|
|
checksum_address = to_checksum_address(canonical_address)
|
|
|
|
return checksum_address
|
2019-11-14 02:51:50 +00:00
|
|
|
|
2019-10-13 21:55:43 +00:00
|
|
|
return _get_random_checksum_address
|
2019-11-27 19:08:33 +00:00
|
|
|
|
|
|
|
|
2019-11-28 12:43:41 +00:00
|
|
|
@pytest.fixture(scope='module')
|
|
|
|
def mock_transacting_power_activation(testerchain):
|
|
|
|
def _mock_transacting_power_activation(password, account):
|
|
|
|
testerchain.transacting_power = TransactingPower(password=password, account=account)
|
|
|
|
testerchain.transacting_power.activate()
|
2019-11-14 02:51:50 +00:00
|
|
|
|
2019-11-28 12:43:41 +00:00
|
|
|
return _mock_transacting_power_activation
|
2019-11-14 02:51:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-12-13 02:37:33 +00:00
|
|
|
def fleet_of_highperf_mocked_ursulas(ursula_federated_test_config, request):
|
|
|
|
try:
|
|
|
|
quantity = request.param
|
|
|
|
except AttributeError:
|
|
|
|
quantity = 5000 # Bigass fleet by default; that's kinda the point.
|
2019-11-14 02:51:50 +00:00
|
|
|
with GlobalLoggerSettings.pause_all_logging_while():
|
2019-12-14 02:33:21 +00:00
|
|
|
with mock_secret_source():
|
|
|
|
with mock_cert_storage, mock_cert_loading, mock_rest_app_creation, mock_cert_generation, mock_remember_node, mock_message_verification:
|
|
|
|
_ursulas = make_federated_ursulas(ursula_config=ursula_federated_test_config,
|
|
|
|
quantity=quantity, know_each_other=False)
|
|
|
|
all_ursulas = {u.checksum_address: u for u in _ursulas}
|
|
|
|
for ursula in _ursulas:
|
|
|
|
ursula.known_nodes._nodes = all_ursulas
|
|
|
|
ursula.known_nodes.checksum = b"This is a fleet state checksum..".hex()
|
2019-11-14 02:51:50 +00:00
|
|
|
return _ursulas
|
2019-11-14 03:09:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-12-13 02:37:33 +00:00
|
|
|
def highperf_mocked_alice(fleet_of_highperf_mocked_ursulas):
|
2019-11-14 03:09:18 +00:00
|
|
|
config = AliceConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
2019-11-14 03:09:18 +00:00
|
|
|
network_middleware=MockRestMiddlewareForLargeFleetTests(),
|
|
|
|
federated_only=True,
|
|
|
|
abort_on_learning_error=True,
|
|
|
|
save_metadata=False,
|
|
|
|
reload_metadata=False)
|
|
|
|
|
2019-11-20 04:55:54 +00:00
|
|
|
with mock_cert_storage, mock_verify_node, mock_record_fleet_state, mock_message_verification, mock_keep_learning:
|
2019-12-13 02:37:33 +00:00
|
|
|
alice = config.produce(known_nodes=list(fleet_of_highperf_mocked_ursulas)[:1])
|
2019-11-20 04:56:21 +00:00
|
|
|
return alice
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
2019-12-13 02:37:33 +00:00
|
|
|
def highperf_mocked_bob(fleet_of_highperf_mocked_ursulas):
|
2019-11-20 04:56:21 +00:00
|
|
|
config = BobConfiguration(dev_mode=True,
|
2020-01-19 17:22:07 +00:00
|
|
|
domains={TEMPORARY_DOMAIN},
|
|
|
|
network_middleware=MockRestMiddlewareForLargeFleetTests(),
|
|
|
|
federated_only=True,
|
|
|
|
abort_on_learning_error=True,
|
|
|
|
save_metadata=False,
|
|
|
|
reload_metadata=False)
|
2019-11-20 04:56:21 +00:00
|
|
|
|
|
|
|
with mock_cert_storage, mock_verify_node, mock_record_fleet_state:
|
2019-12-13 02:37:33 +00:00
|
|
|
bob = config.produce(known_nodes=list(fleet_of_highperf_mocked_ursulas)[:1])
|
2019-11-20 04:56:21 +00:00
|
|
|
return bob
|