def test_upgradeability(temp_dir_path): # Prepare remote source for compilation download_github_dir(GITHUB_SOURCE_LINK, temp_dir_path) solidity_compiler = SolidityCompiler(source_dirs=[SourceDirs(SolidityCompiler.default_contract_dir()), SourceDirs(temp_dir_path)]) # Prepare the blockchain provider_uri = 'tester://pyevm/2' try: blockchain_interface = BlockchainDeployerInterface(provider_uri=provider_uri, compiler=solidity_compiler, gas_strategy=free_gas_price_strategy) blockchain_interface.connect() origin = blockchain_interface.client.accounts[0] BlockchainInterfaceFactory.register_interface(interface=blockchain_interface) blockchain_interface.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=origin) blockchain_interface.transacting_power.activate() # Check contracts with multiple versions raw_contracts = blockchain_interface._raw_contract_cache contract_name = AdjudicatorDeployer.contract_name test_adjudicator = len(raw_contracts[contract_name]) > 1 contract_name = StakingEscrowDeployer.contract_name test_staking_escrow = len(raw_contracts[contract_name]) > 1 contract_name = PolicyManagerDeployer.contract_name test_policy_manager = len(raw_contracts[contract_name]) > 1 if not test_adjudicator and not test_staking_escrow and not test_policy_manager: return # Prepare master version of contracts and upgrade to the latest registry = InMemoryContractRegistry() token_deployer = NucypherTokenDeployer(registry=registry, deployer_address=origin) token_deployer.deploy() staking_escrow_deployer = StakingEscrowDeployer(registry=registry, deployer_address=origin) deploy_earliest_contract(blockchain_interface, staking_escrow_deployer) if test_staking_escrow: staking_escrow_deployer.upgrade(contract_version="latest", confirmations=0) if test_policy_manager: policy_manager_deployer = PolicyManagerDeployer(registry=registry, deployer_address=origin) deploy_earliest_contract(blockchain_interface, policy_manager_deployer) policy_manager_deployer.upgrade(contract_version="latest", confirmations=0) if test_adjudicator: adjudicator_deployer = AdjudicatorDeployer(registry=registry, deployer_address=origin) deploy_earliest_contract(blockchain_interface, adjudicator_deployer) adjudicator_deployer.upgrade(contract_version="latest", confirmations=0) finally: # Unregister interface with contextlib.suppress(KeyError): del BlockchainInterfaceFactory._interfaces[provider_uri]
def test_multi_versions(): base_dir = os.path.join(dirname(abspath(__file__)), "contracts", "multiversion") v1_dir = os.path.join(base_dir, "v1") v2_dir = os.path.join(base_dir, "v2") root_dir = SolidityCompiler.default_contract_dir() solidity_compiler = SolidityCompiler(source_dirs=[SourceDirs(root_dir, {v1_dir}), SourceDirs(root_dir, {v2_dir})]) interfaces = solidity_compiler.compile() assert "VersionTest" in interfaces contract_data = interfaces["VersionTest"] assert len(contract_data) == 2 assert "v1.2.3" in contract_data assert "v1.1.4" in contract_data assert contract_data["v1.2.3"]["devdoc"] != contract_data["v1.1.4"]["devdoc"]
def connect(cls, *args, **kwargs) -> 'TesterBlockchain': interface = BlockchainDeployerInterface(provider_uri=cls._PROVIDER_URI, compiler=SolidityCompiler(test_contract_dir=CONTRACT_ROOT), registry=InMemoryEthereumContractRegistry()) testerchain = TesterBlockchain(interface=interface, *args, **kwargs) return testerchain
def connect(cls, provider_uri: str = None, registry: EthereumContractRegistry = None, deployer: bool = False, compile: bool = False, poa: bool = False) -> 'Blockchain': if cls._instance is NO_BLOCKCHAIN_AVAILABLE: registry = registry or EthereumContractRegistry() compiler = SolidityCompiler() if compile is True else None InterfaceClass = BlockchainDeployerInterface if deployer is True else BlockchainInterface interface = InterfaceClass(provider_uri=provider_uri, registry=registry, compiler=compiler) if poa is True: interface.w3.middleware_onion.inject(geth_poa_middleware, layer=0) cls._instance = cls(interface=interface) else: if provider_uri is not None: existing_uri = cls._instance.interface.provider_uri if existing_uri != provider_uri: raise ValueError( "There is an existing blockchain connection to {}. " "Use Interface.add_provider to connect additional providers" .format(existing_uri)) return cls._instance
def bootstrap_network( cls, economics: BaseEconomics = None ) -> Tuple['TesterBlockchain', 'InMemoryContractRegistry']: """For use with metric testing scripts""" registry = InMemoryContractRegistry() testerchain = cls(compiler=SolidityCompiler()) BlockchainInterfaceFactory.register_interface(testerchain) power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=testerchain.etherbase_account) power.activate() testerchain.transacting_power = power origin = testerchain.client.etherbase deployer = ContractAdministrator(deployer_address=origin, registry=registry, economics=economics or cls._default_token_economics, staking_escrow_test_mode=True) secrets = dict() for deployer_class in deployer.upgradeable_deployer_classes: secrets[ deployer_class.contract_name] = INSECURE_DEVELOPMENT_PASSWORD _receipts = deployer.deploy_network_contracts(secrets=secrets, interactive=False) return testerchain, registry
def test_multi_source_compilation(testerchain): solidity_compiler = SolidityCompiler( source_dirs=[(SolidityCompiler.default_contract_dir(), None), (SolidityCompiler.default_contract_dir(), {TesterBlockchain.TEST_CONTRACTS_DIR})]) interfaces = solidity_compiler.compile() # Remove AST because id in tree node depends on compilation scope for contract_name, contract_data in interfaces.items(): for version, data in contract_data.items(): data.pop("ast") raw_cache = testerchain._raw_contract_cache.copy() for contract_name, contract_data in raw_cache.items(): for version, data in contract_data.items(): data.pop("ast") assert interfaces == raw_cache
def test_rapid_deployment(): compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri='tester://pyevm') blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=4) blockchain.ether_airdrop(amount=1000000000) origin, *everyone = blockchain.interface.w3.eth.accounts deployer = Deployer(blockchain=blockchain, deployer_address=origin) deployer_address, *all_yall = deployer.blockchain.interface.w3.eth.accounts # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=os.urandom(32), policy_secret=os.urandom(32)) # User Escrow Proxy deployer.deploy_escrow_proxy(secret=os.urandom(32)) # Deploy User Escrow total_allocations = 100 # Start with some hard-coded cases... 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[3], 'amount': MIN_ALLOWED_LOCKED * 100, 'duration': ONE_YEAR_IN_SECONDS * 3 }] # Pile on the rest for _ in range(total_allocations - len(allocation_data)): random_password = ''.join( random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(16)) acct = w3.eth.account.create(random_password) beneficiary_address = acct.address amount = random.randint(MIN_ALLOWED_LOCKED, MAX_ALLOWED_LOCKED) duration = random.randint(MIN_LOCKED_PERIODS, MAX_MINTING_PERIODS * 3) random_allocation = { 'address': beneficiary_address, 'amount': amount, 'duration': duration } allocation_data.append(random_allocation) deployer.deploy_beneficiary_contracts( allocations=allocation_data, allocation_registry=allocation_registry)
def test_rapid_deployment(token_economics): compiler = SolidityCompiler() allocation_registry = InMemoryAllocationRegistry() blockchain = _TesterBlockchain(eth_airdrop=False, test_accounts=4, compiler=compiler) # TODO: #1092 - TransactingPower blockchain.transacting_power = BlockchainPower( blockchain=blockchain, account=blockchain.etherbase_account) deployer_address = blockchain.etherbase_account deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) deployer.deploy_network_contracts( staker_secret=STAKING_ESCROW_DEPLOYMENT_SECRET, policy_secret=POLICY_MANAGER_DEPLOYMENT_SECRET, adjudicator_secret=ADJUDICATOR_DEPLOYMENT_SECRET, user_escrow_proxy_secret=USER_ESCROW_PROXY_DEPLOYMENT_SECRET) all_yall = blockchain.unassigned_accounts # Start with some hard-coded cases... allocation_data = [{ 'address': all_yall[1], 'amount': token_economics.maximum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS }, { 'address': all_yall[2], 'amount': token_economics.minimum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS * 2 }, { 'address': all_yall[3], 'amount': token_economics.minimum_allowed_locked * 100, 'duration': ONE_YEAR_IN_SECONDS * 3 }] # Pile on the rest for _ in range(NUMBER_OF_ALLOCATIONS_IN_TESTS - len(allocation_data)): random_password = ''.join( random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(16)) acct = w3.eth.account.create(random_password) beneficiary_address = acct.address amount = random.randint(token_economics.minimum_allowed_locked, token_economics.maximum_allowed_locked) duration = random.randint( token_economics.minimum_locked_periods * ONE_YEAR_IN_SECONDS, (token_economics.maximum_locked_periods * ONE_YEAR_IN_SECONDS) * 3) random_allocation = { 'address': beneficiary_address, 'amount': amount, 'duration': duration } allocation_data.append(random_allocation) deployer.deploy_beneficiary_contracts( allocations=allocation_data, allocation_registry=allocation_registry)
def __init__(self, compiler: SolidityCompiler = None, ignore_solidity_check: bool = False, *args, **kwargs): super().__init__(*args, **kwargs) self.compiler = compiler or SolidityCompiler( ignore_solidity_check=ignore_solidity_check)
def _setup_solidity(self, compiler: SolidityCompiler = None): if compiler: # Execute the compilation if we're recompiling # Otherwise read compiled contract data from the registry. _raw_contract_cache = compiler.compile() else: _raw_contract_cache = NO_COMPILATION_PERFORMED self._raw_contract_cache = _raw_contract_cache
def __init__(self, deployer_address: str = None, compiler: SolidityCompiler = None, *args, **kwargs): super().__init__(*args, **kwargs) self.compiler = compiler or SolidityCompiler() self.__deployer_address = deployer_address or NO_DEPLOYER_CONFIGURED
def _setup_solidity(self, compiler: SolidityCompiler = None) -> None: if self.dry_run: self.log.info("Dry run is active, skipping solidity compile steps.") return if compiler: # Execute the compilation if we're recompiling # Otherwise read compiled contract data from the registry. _raw_contract_cache = compiler.compile() else: _raw_contract_cache = NO_COMPILATION_PERFORMED self._raw_contract_cache = _raw_contract_cache
def test_rapid_deployment(token_economics, test_registry): compiler = SolidityCompiler() allocation_registry = InMemoryAllocationRegistry() blockchain = _TesterBlockchain(eth_airdrop=False, test_accounts=4, compiler=compiler) # TODO: #1092 - TransactingPower blockchain.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=blockchain.etherbase_account) blockchain.transacting_power.activate() deployer_address = blockchain.etherbase_account deployer = ContractAdministrator(deployer_address=deployer_address, registry=test_registry) secrets = dict() for deployer_class in deployer.upgradeable_deployer_classes: secrets[deployer_class.contract_name] = INSECURE_DEVELOPMENT_PASSWORD deployer.deploy_network_contracts(secrets=secrets, emitter=StdoutEmitter()) all_yall = blockchain.unassigned_accounts # Start with some hard-coded cases... allocation_data = [{'beneficiary_address': all_yall[1], 'amount': token_economics.maximum_allowed_locked, 'duration_seconds': ONE_YEAR_IN_SECONDS}, {'beneficiary_address': all_yall[2], 'amount': token_economics.minimum_allowed_locked, 'duration_seconds': ONE_YEAR_IN_SECONDS*2}, {'beneficiary_address': all_yall[3], 'amount': token_economics.minimum_allowed_locked*100, 'duration_seconds': ONE_YEAR_IN_SECONDS*3} ] # Pile on the rest for _ in range(NUMBER_OF_ALLOCATIONS_IN_TESTS - len(allocation_data)): random_password = ''.join(random.SystemRandom().choice(string.ascii_uppercase+string.digits) for _ in range(16)) acct = w3.eth.account.create(random_password) beneficiary_address = acct.address amount = random.randint(token_economics.minimum_allowed_locked, token_economics.maximum_allowed_locked) duration = random.randint(token_economics.minimum_locked_periods*ONE_YEAR_IN_SECONDS, (token_economics.maximum_rewarded_periods*ONE_YEAR_IN_SECONDS)*3) random_allocation = {'beneficiary_address': beneficiary_address, 'amount': amount, 'duration_seconds': duration} allocation_data.append(random_allocation) deployer.deploy_beneficiary_contracts(allocations=allocation_data, allocation_registry=allocation_registry, interactive=False)
def test_rapid_deployment(token_economics, test_registry, tmpdir, get_random_checksum_address): compiler = SolidityCompiler() blockchain = _TesterBlockchain(eth_airdrop=False, test_accounts=4, compiler=compiler) # TODO: #1092 - TransactingPower blockchain.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=blockchain.etherbase_account) blockchain.transacting_power.activate() deployer_address = blockchain.etherbase_account administrator = ContractAdministrator(deployer_address=deployer_address, registry=test_registry) administrator.deploy_network_contracts(emitter=StdoutEmitter(), interactive=False) all_yall = blockchain.unassigned_accounts # Start with some hard-coded cases... allocation_data = [{'checksum_address': all_yall[1], 'amount': token_economics.maximum_allowed_locked, 'lock_periods': token_economics.minimum_locked_periods}, {'checksum_address': all_yall[2], 'amount': token_economics.minimum_allowed_locked, 'lock_periods': token_economics.minimum_locked_periods}, {'checksum_address': all_yall[3], 'amount': token_economics.minimum_allowed_locked*100, 'lock_periods': token_economics.minimum_locked_periods}, ] # Pile on the rest for _ in range(NUMBER_OF_ALLOCATIONS_IN_TESTS - len(allocation_data)): checksum_address = get_random_checksum_address() amount = random.randint(token_economics.minimum_allowed_locked, token_economics.maximum_allowed_locked) duration = random.randint(token_economics.minimum_locked_periods, token_economics.maximum_rewarded_periods) random_allocation = {'checksum_address': checksum_address, 'amount': amount, 'lock_periods': duration} allocation_data.append(random_allocation) filepath = tmpdir / "allocations.json" with open(filepath, 'w') as f: json.dump(allocation_data, f) administrator.batch_deposits(allocation_data_filepath=str(filepath), interactive=False) minimum, default, maximum = 10, 20, 30 administrator.set_fee_rate_range(minimum, default, maximum)
def test_rapid_deployment(token_economics): compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri='tester://pyevm') blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=4) deployer_address = blockchain.etherbase_account deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=MINERS_ESCROW_DEPLOYMENT_SECRET, policy_secret=POLICY_MANAGER_DEPLOYMENT_SECRET, adjudicator_secret=MINING_ADJUDICATOR_DEPLOYMENT_SECRET) # Deploy User Escrow, too (+ Linker) deployer.deploy_escrow_proxy(secret=USER_ESCROW_PROXY_DEPLOYMENT_SECRET) total_allocations = NUMBER_OF_ALLOCATIONS_IN_TESTS all_yall = blockchain.unassigned_accounts # Start with some hard-coded cases... allocation_data = [{'address': all_yall[1], 'amount': token_economics.maximum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS}, {'address': all_yall[2], 'amount': token_economics.minimum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS*2}, {'address': all_yall[3], 'amount': token_economics.minimum_allowed_locked*100, 'duration': ONE_YEAR_IN_SECONDS*3} ] # Pile on the rest for _ in range(total_allocations - len(allocation_data)): random_password = ''.join(random.SystemRandom().choice(string.ascii_uppercase+string.digits) for _ in range(16)) acct = w3.eth.account.create(random_password) beneficiary_address = acct.address amount = random.randint(token_economics.minimum_allowed_locked, token_economics.maximum_allowed_locked) duration = random.randint(token_economics.minimum_locked_periods*ONE_YEAR_IN_SECONDS, (token_economics.maximum_locked_periods*ONE_YEAR_IN_SECONDS)*3) random_allocation = {'address': beneficiary_address, 'amount': amount, 'duration': duration} allocation_data.append(random_allocation) deployer.deploy_beneficiary_contracts(allocations=allocation_data, allocation_registry=allocation_registry)
def bootstrap_network(cls) -> Tuple['TesterBlockchain', Dict[str, EthereumContractAgent]]: """For use with metric testing scripts""" testerchain = cls(compiler=SolidityCompiler()) power = BlockchainPower(blockchain=testerchain, account=testerchain.client.etherbase) power.unlock_account(password=INSECURE_DEVELOPMENT_PASSWORD) testerchain.transacting_power = power origin = testerchain.client.etherbase deployer = Deployer(blockchain=testerchain, deployer_address=origin, bare=True) _txhashes, agents = deployer.deploy_network_contracts(staker_secret=STAKING_ESCROW_DEPLOYMENT_SECRET, policy_secret=POLICY_MANAGER_DEPLOYMENT_SECRET, adjudicator_secret=ADJUDICATOR_DEPLOYMENT_SECRET, user_escrow_proxy_secret=USER_ESCROW_PROXY_DEPLOYMENT_SECRET) return testerchain, agents
def from_configuration_file(cls, config: NodeConfiguration) -> 'BlockchainInterface': # Parse payload = parse_blockchain_config(filepath=config.config_file_location) # Init deps compiler = SolidityCompiler() if payload['compile'] else None registry = EthereumContractRegistry.from_config(config=config) interface_class = BlockchainInterface if not payload['deploy'] else BlockchainDeployerInterface # init class interface = interface_class(timeout=payload['timeout'], provider_uri=payload['provider_uri'], compiler=compiler, registry=registry) return interface
def deployed_blockchain(): # # Interface # compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri=TEST_PROVIDER_URI) # # Blockchain # blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=5, poa=True) blockchain.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT) origin, *everyone = blockchain.interface.w3.eth.accounts # # Delpoyer # deployer = Deployer(blockchain=blockchain, deployer_address=origin) deployer_address, *all_yall = deployer.blockchain.interface.w3.eth.accounts # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=os.urandom(32), policy_secret=os.urandom(32)) # User Escrow Proxy deployer.deploy_escrow_proxy(secret=os.urandom(32)) # Start with some hard-coded cases... 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) yield blockchain, deployer_address, registry
def from_config(cls, filepath=None) -> 'BlockchainInterface': # Parse filepath = filepath if filepath is None else DEFAULT_INI_FILEPATH payload = parse_blockchain_config(filepath=filepath) # Init deps compiler = SolidityCompiler() if payload['compile'] else None registry = EthereumContractRegistry.from_config(filepath=filepath) interface_class = BlockchainInterface if not payload['deploy'] else BlockchainDeployerInterface # init class circumflex = interface_class(timeout=payload['timeout'], provider_uri=payload['provider_uri'], compiler=compiler, registry=registry) return circumflex
def deployed_blockchain(token_economics): # Interface compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri=TEST_PROVIDER_URI) # Blockchain blockchain = TesterBlockchain(interface=interface, airdrop=True, test_accounts=5, poa=True) deployer_address = blockchain.etherbase_account # Deployer deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=os.urandom(32), policy_secret=os.urandom(32), adjudicator_secret=os.urandom(32)) # User Escrow Proxy deployer.deploy_escrow_proxy(secret=os.urandom(32)) # Start with some hard-coded cases... all_yall = blockchain.unassigned_accounts allocation_data = [{ 'address': all_yall[1], 'amount': token_economics.maximum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS }] deployer.deploy_beneficiary_contracts( allocations=allocation_data, allocation_registry=allocation_registry) yield blockchain, deployer_address, registry
def bootstrap_network(cls) -> 'TesterBlockchain': """For use with metric testing scripts""" testerchain = cls(compiler=SolidityCompiler()) power = TransactingPower(blockchain=testerchain, password=INSECURE_DEVELOPMENT_PASSWORD, account=testerchain.etherbase_account) power.activate() testerchain.transacting_power = power origin = testerchain.client.etherbase deployer = DeployerActor(blockchain=testerchain, deployer_address=origin, bare=True) secrets = dict() for deployer_class in deployer.upgradeable_deployer_classes: secrets[ deployer_class.contract_name] = INSECURE_DEVELOPMENT_PASSWORD _receipts = deployer.deploy_network_contracts(secrets=secrets, interactive=False) return testerchain
def test_multiversion_contract(): # Prepare compiler base_dir = os.path.join(dirname(abspath(__file__)), "contracts", "multiversion") v1_dir = os.path.join(base_dir, "v1") v2_dir = os.path.join(base_dir, "v2") root_dir = SolidityCompiler.default_contract_dir() solidity_compiler = SolidityCompiler(source_dirs=[ SourceDirs(root_dir, {v2_dir}), SourceDirs(root_dir, {v1_dir}) ]) # Prepare chain blockchain_interface = BlockchainDeployerInterface( provider_uri='tester://pyevm/2', compiler=solidity_compiler) blockchain_interface.connect() origin = blockchain_interface.client.accounts[0] blockchain_interface.transacting_power = TransactingPower( password=INSECURE_DEVELOPMENT_PASSWORD, account=origin) blockchain_interface.transacting_power.activate() # Searching both contract through raw data contract_name = "VersionTest" requested_version = "v1.2.3" version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version=requested_version) assert version == requested_version version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version="latest") assert version == requested_version requested_version = "v1.1.4" version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version=requested_version) assert version == requested_version version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version="earliest") assert version == requested_version # Deploy different contracts and check their versions registry = InMemoryContractRegistry() contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="v1.1.4") assert contract.version == "v1.1.4" assert contract.functions.VERSION().call() == 1 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="earliest") assert contract.version == "v1.1.4" assert contract.functions.VERSION().call() == 1 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="v1.2.3") assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="latest") assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name) assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2
def solidity_compiler(): """Doing this more than once per session will result in slower test run times.""" compiler = SolidityCompiler() yield compiler
class TesterBlockchain(BlockchainDeployerInterface): """ Blockchain subclass with additional test utility methods and options. """ _instance = None GAS_STRATEGIES = { **BlockchainDeployerInterface.GAS_STRATEGIES, 'free': free_gas_price_strategy } _PROVIDER_URI = 'tester://pyevm' TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts') _compiler = SolidityCompiler( source_dirs=[(SolidityCompiler.default_contract_dir(), {TEST_CONTRACTS_DIR})]) _test_account_cache = list() _default_test_accounts = NUMBER_OF_ETH_TEST_ACCOUNTS # Reserved addresses _ETHERBASE = 0 _ALICE = 1 _BOB = 2 _FIRST_STAKER = 5 _stakers_range = range(NUMBER_OF_STAKERS_IN_BLOCKCHAIN_TESTS) _FIRST_URSULA = _FIRST_STAKER + NUMBER_OF_STAKERS_IN_BLOCKCHAIN_TESTS _ursulas_range = range(NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS) _default_token_economics = StandardTokenEconomics() def __init__(self, test_accounts=None, poa=True, light=False, eth_airdrop=False, free_transactions=False, compiler: SolidityCompiler = None, *args, **kwargs): if not test_accounts: test_accounts = self._default_test_accounts self.free_transactions = free_transactions if compiler: TesterBlockchain._compiler = compiler super().__init__(provider_uri=self._PROVIDER_URI, provider_process=None, poa=poa, light=light, compiler=self._compiler, *args, **kwargs) self.log = Logger("test-blockchain") self.connect() # Generate additional ethereum accounts for testing population = test_accounts enough_accounts = len(self.client.accounts) >= population if not enough_accounts: accounts_to_make = population - len(self.client.accounts) self.__generate_insecure_unlocked_accounts( quantity=accounts_to_make) assert test_accounts == len(self.w3.eth.accounts) if eth_airdrop is True: # ETH for everyone! self.ether_airdrop(amount=DEVELOPMENT_ETH_AIRDROP_AMOUNT) def attach_middleware(self): if self.free_transactions: self.w3.eth.setGasPriceStrategy(free_gas_price_strategy) def __generate_insecure_unlocked_accounts(self, quantity: int) -> List[str]: # # Sanity Check - Only PyEVM can be used. # # Detect provider platform client_version = self.w3.clientVersion if 'Geth' in client_version: raise RuntimeError("WARNING: Geth providers are not implemented.") elif "Parity" in client_version: raise RuntimeError( "WARNING: Parity providers are not implemented.") addresses = list() for _ in range(quantity): address = self.provider.ethereum_tester.add_account( '0x' + os.urandom(32).hex()) addresses.append(address) self._test_account_cache.append(address) self.log.info('Generated new insecure account {}'.format(address)) return addresses def ether_airdrop(self, amount: int) -> List[str]: """Airdrops ether from creator address to all other addresses!""" coinbase, *addresses = self.w3.eth.accounts tx_hashes = list() for address in addresses: tx = {'to': address, 'from': coinbase, 'value': amount} txhash = self.w3.eth.sendTransaction(tx) _receipt = self.wait_for_receipt(txhash) tx_hashes.append(txhash) eth_amount = Web3().fromWei(amount, 'ether') self.log.info("Airdropped {} ETH {} -> {}".format( eth_amount, tx['from'], tx['to'])) return tx_hashes def time_travel(self, hours: int = None, seconds: int = None, periods: int = None): """ Wait the specified number of wait_hours by comparing block timestamps and mines a single block. """ more_than_one_arg = sum(map(bool, (hours, seconds, periods))) > 1 if more_than_one_arg: raise ValueError( "Specify hours, seconds, or periods, not a combination") if periods: duration = self._default_token_economics.seconds_per_period * periods base = self._default_token_economics.seconds_per_period elif hours: duration = hours * (60 * 60) base = 60 * 60 elif seconds: duration = seconds base = 1 else: raise ValueError("Specify either hours, seconds, or periods.") now = self.w3.eth.getBlock(block_identifier='latest').timestamp end_timestamp = ((now + duration) // base) * base self.w3.eth.web3.testing.timeTravel(timestamp=end_timestamp) self.w3.eth.web3.testing.mine(1) delta = maya.timedelta(seconds=end_timestamp - now) self.log.info( f"Time traveled {delta} " f"| period {epoch_to_period(epoch=end_timestamp, seconds_per_period=self._default_token_economics.seconds_per_period)} " f"| epoch {end_timestamp}") @classmethod def bootstrap_network( cls, economics: BaseEconomics = None ) -> Tuple['TesterBlockchain', 'InMemoryContractRegistry']: """For use with metric testing scripts""" registry = InMemoryContractRegistry() testerchain = cls(compiler=SolidityCompiler()) BlockchainInterfaceFactory.register_interface(testerchain) power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=testerchain.etherbase_account) power.activate() testerchain.transacting_power = power origin = testerchain.client.etherbase deployer = ContractAdministrator(deployer_address=origin, registry=registry, economics=economics or cls._default_token_economics, staking_escrow_test_mode=True) secrets = dict() for deployer_class in deployer.upgradeable_deployer_classes: secrets[ deployer_class.contract_name] = INSECURE_DEVELOPMENT_PASSWORD _receipts = deployer.deploy_network_contracts(secrets=secrets, interactive=False) return testerchain, registry @property def etherbase_account(self): return self.client.accounts[self._ETHERBASE] @property def alice_account(self): return self.client.accounts[self._ALICE] @property def bob_account(self): return self.client.accounts[self._BOB] def ursula_account(self, index): if index not in self._ursulas_range: raise ValueError( f"Ursula index must be lower than {NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS}" ) return self.client.accounts[index + self._FIRST_URSULA] def staker_account(self, index): if index not in self._stakers_range: raise ValueError( f"Staker index must be lower than {NUMBER_OF_STAKERS_IN_BLOCKCHAIN_TESTS}" ) return self.client.accounts[index + self._FIRST_STAKER] @property def ursulas_accounts(self): return list(self.ursula_account(i) for i in self._ursulas_range) @property def stakers_accounts(self): return list(self.staker_account(i) for i in self._stakers_range) @property def unassigned_accounts(self): special_accounts = [ self.etherbase_account, self.alice_account, self.bob_account ] assigned_accounts = set(self.stakers_accounts + self.ursulas_accounts + special_accounts) accounts = set(self.client.accounts) return list(accounts.difference(assigned_accounts)) def wait_for_receipt(self, txhash: bytes, timeout: int = None) -> dict: """Wait for a transaction receipt and return it""" timeout = timeout or self.TIMEOUT result = self.w3.eth.waitForTransactionReceipt(txhash, timeout=timeout) if result.status == 0: raise TransactionFailed() return result
def solidity_compiler(): """Doing this more than once per session will result in slower test run times.""" compiler = SolidityCompiler(test_contract_dir=TEST_CONTRACTS_DIR) yield compiler
def __init__(self, compiler: SolidityCompiler = None, *args, **kwargs): super().__init__(*args, **kwargs) self.compiler = compiler or SolidityCompiler()
def geth_poa_devchain(): _testerchain = make_testerchain(provider_uri='tester://geth', solidity_compiler=SolidityCompiler()) return f'ipc://{_testerchain.interface.provider.ipc_path}'
def deploy(click_config, action, poa, provider_uri, geth, enode, deployer_address, contract_name, allocation_infile, allocation_outfile, registry_infile, registry_outfile, no_compile, amount, recipient_address, config_root, sync, force): """Manage contract and registry deployment""" ETH_NODE = None # # Validate # # Ensure config root exists, because we need a default place to put output files. config_root = config_root or DEFAULT_CONFIG_ROOT if not os.path.exists(config_root): os.makedirs(config_root) # # Connect to Blockchain # if geth: # Spawn geth child process ETH_NODE = NuCypherGethDevnetProcess(config_root=config_root) ETH_NODE.ensure_account_exists(password=click_config.get_password( confirm=True)) ETH_NODE.start() # TODO: Graceful shutdown provider_uri = ETH_NODE.provider_uri # Establish a contract registry from disk if specified registry, registry_filepath = None, (registry_outfile or registry_infile) if registry_filepath is not None: registry = EthereumContractRegistry( registry_filepath=registry_filepath) # Deployment-tuned blockchain connection blockchain = BlockchainDeployerInterface(provider_uri=provider_uri, poa=poa, registry=registry, compiler=SolidityCompiler(), fetch_registry=False, sync_now=sync) # # Deployment Actor # if not deployer_address: for index, address in enumerate(blockchain.client.accounts): click.secho(f"{index} --- {address}") choices = click.IntRange(0, len(blockchain.client.accounts)) deployer_address_index = click.prompt("Select deployer address", default=0, type=choices) deployer_address = blockchain.client.accounts[deployer_address_index] # Verify Address if not force: click.confirm("Selected {} - Continue?".format(deployer_address), abort=True) # TODO: Integrate with Deployer Actor (Character) blockchain.transacting_power = BlockchainPower(blockchain=blockchain, account=deployer_address) deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # Verify ETH Balance click.secho(f"\n\nDeployer ETH balance: {deployer.eth_balance}") if deployer.eth_balance == 0: click.secho("Deployer address has no ETH.", fg='red', bold=True) raise click.Abort() if not blockchain.client.is_local: # (~ dev mode; Assume accounts are already unlocked) password = click.prompt("Enter ETH node password", hide_input=True) blockchain.client.unlockAccount(deployer_address, password) # Add ETH Bootnode or Peer if enode: if geth: blockchain.w3.geth.admin.addPeer(enode) click.secho(f"Added ethereum peer {enode}") else: raise NotImplemented # TODO: other backends # # Action switch # if action == 'upgrade': if not contract_name: raise click.BadArgumentUsage( message="--contract-name is required when using --upgrade") existing_secret = click.prompt( 'Enter existing contract upgrade secret', hide_input=True) new_secret = click.prompt('Enter new contract upgrade secret', hide_input=True, confirmation_prompt=True) deployer.upgrade_contract(contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) elif action == 'rollback': existing_secret = click.prompt( 'Enter existing contract upgrade secret', hide_input=True) new_secret = click.prompt('Enter new contract upgrade secret', hide_input=True, confirmation_prompt=True) deployer.rollback_contract(contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) elif action == "contracts": registry_filepath = deployer.blockchain.registry.filepath if os.path.isfile(registry_filepath): click.secho( f"\nThere is an existing contract registry at {registry_filepath}.\n" f"Did you mean 'nucypher-deploy upgrade'?\n", fg='yellow') click.confirm( "Optionally, destroy existing local registry and continue?", abort=True) click.confirm( f"Confirm deletion of contract registry '{registry_filepath}'?", abort=True) os.remove(registry_filepath) # # Deploy Single Contract # if contract_name: # TODO: Handle secret collection for single contract deployment try: deployer_func = deployer.deployers[contract_name] except KeyError: message = f"No such contract {contract_name}. Available contracts are {deployer.deployers.keys()}" click.secho(message, fg='red', bold=True) raise click.Abort() else: # Deploy single contract _txs, _agent = deployer_func() # TODO: Painting for single contract deployment if ETH_NODE: ETH_NODE.stop() return # # Stage Deployment # # Track tx hashes, and new agents __deployment_transactions = dict() __deployment_agents = dict() secrets = click_config.collect_deployment_secrets() click.clear() click.secho(NU_BANNER) w3 = deployer.blockchain.w3 click.secho(f"Current Time ........ {maya.now().iso8601()}") click.secho( f"Web3 Provider ....... {deployer.blockchain.provider_uri}") click.secho( f"Block ............... {deployer.blockchain.client.block_number}") click.secho( f"Gas Price ........... {deployer.blockchain.client.gas_price}") click.secho(f"Deployer Address .... {deployer.checksum_address}") click.secho(f"ETH ................. {deployer.eth_balance}") click.secho( f"Chain ID ............ {deployer.blockchain.client.chain_id}") click.secho( f"Chain Name .......... {deployer.blockchain.client.chain_name}") # Ask - Last chance to gracefully abort if not force: click.secho( "\nDeployment successfully staged. Take a deep breath. \n", fg='green') if click.prompt("Type 'DEPLOY' to continue") != 'DEPLOY': raise click.Abort() # Delay - Last chance to crash and abort click.secho(f"Starting deployment in 3 seconds...", fg='red') time.sleep(1) click.secho(f"2...", fg='yellow') time.sleep(1) click.secho(f"1...", fg='green') time.sleep(1) click.secho(f"Deploying...", bold=True) # # DEPLOY < ------- # txhashes, deployers = deployer.deploy_network_contracts( staker_secret=secrets.staker_secret, policy_secret=secrets.policy_secret, adjudicator_secret=secrets.adjudicator_secret, user_escrow_proxy_secret=secrets.escrow_proxy_secret) # Success __deployment_transactions.update(txhashes) # # Paint # total_gas_used = 0 # TODO: may be faulty for contract_name, transactions in __deployment_transactions.items(): # Paint heading heading = '\n{} ({})'.format( contract_name, deployers[contract_name].contract_address) click.secho(heading, bold=True) click.echo('*' * (42 + 3 + len(contract_name))) for tx_name, txhash in transactions.items(): # Wait for inclusion in the blockchain receipt = deployer.blockchain.w3.eth.waitForTransactionReceipt( txhash) click.secho("OK", fg='green', nl=False, bold=True) # Accumulate gas total_gas_used += int(receipt['gasUsed']) # Paint click.secho(" | {}".format(tx_name), fg='yellow', nl=False) click.secho(" | {}".format(txhash.hex()), fg='yellow', nl=False) click.secho(" ({} gas)".format(receipt['cumulativeGasUsed'])) click.secho("Block #{} | {}\n".format( receipt['blockNumber'], receipt['blockHash'].hex())) # Paint outfile paths click.secho( "Cumulative Gas Consumption: {} gas".format(total_gas_used), bold=True, fg='blue') registry_outfile = deployer.blockchain.registry.filepath click.secho('Generated registry {}'.format(registry_outfile), bold=True, fg='blue') # Save transaction metadata receipts_filepath = deployer.save_deployment_receipts( transactions=__deployment_transactions) click.secho(f"Saved deployment receipts to {receipts_filepath}", fg='blue', bold=True) elif action == "allocations": if not allocation_infile: allocation_infile = click.prompt("Enter allocation data filepath") click.confirm("Continue deploying and allocating?", abort=True) deployer.deploy_beneficiaries_from_file( allocation_data_filepath=allocation_infile, allocation_outfile=allocation_outfile) elif action == "transfer": token_agent = NucypherTokenAgent(blockchain=blockchain) click.confirm( f"Transfer {amount} from {token_agent.contract_address} to {recipient_address}?", abort=True) txhash = token_agent.transfer( amount=amount, sender_address=token_agent.contract_address, target_address=recipient_address) click.secho(f"OK | {txhash}") elif action == "destroy-registry": registry_filepath = deployer.blockchain.registry.filepath click.confirm( f"Are you absolutely sure you want to destroy the contract registry at {registry_filepath}?", abort=True) os.remove(registry_filepath) click.secho(f"Successfully destroyed {registry_filepath}", fg='red') else: raise click.BadArgumentUsage(message=f"Unknown action '{action}'") if ETH_NODE: ETH_NODE.stop()
def solidity_compiler(): """Doing this more than once per session will result in slower test run times.""" test_contracts_dir = os.path.join(dirname(abspath(contracts.__file__)), 'contracts') compiler = SolidityCompiler(test_contract_dir=test_contracts_dir) yield compiler
def estimate_gas(): solidity_compiler = SolidityCompiler(test_contract_dir=CONTRACTS_DIR) # create a temporary registrar for the tester blockchain temporary_registry = TemporaryEthereumContractRegistry() # Configure a custom provider overrides = {'gas_limit': 4626271} pyevm_backend = OverridablePyEVMBackend(genesis_overrides=overrides) eth_tester = EthereumTester(backend=pyevm_backend, auto_mine_transactions=True) pyevm_provider = EthereumTesterProvider(ethereum_tester=eth_tester) # Use the the custom provider and registrar to init an interface circumflex = DeployerCircumflex( compiler=solidity_compiler, # freshly recompile registry=temporary_registry, # use temporary registrar providers=(pyevm_provider, )) # use custom test provider # Create the blockchain testerchain = TesterBlockchain(interface=circumflex, test_accounts=10) origin, ursula1, ursula2, ursula3, alice1, *everyone_else = testerchain.interface.w3.eth.accounts circumflex.deployer_address = origin # Set the deployer address from a freshly created test account token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin) token_deployer.arm() token_deployer.deploy() token_agent = token_deployer.make_agent() miner_escrow_deployer = MinerEscrowDeployer(token_agent=token_agent, deployer_address=origin) miner_escrow_deployer.arm() miner_escrow_deployer.deploy() miner_agent = miner_escrow_deployer.make_agent() policy_manager_deployer = PolicyManagerDeployer(miner_agent=miner_agent, deployer_address=origin) policy_manager_deployer.arm() policy_manager_deployer.deploy() policy_agent = policy_manager_deployer.make_agent() web3 = testerchain.interface.w3 print("Estimate gas:") # Pre deposit tokens tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 5)\ .transact({'from': origin}) testerchain.wait_for_receipt(tx) print("Pre-deposit tokens for 5 owners = " + str( miner_agent.contract.functions.preDeposit( everyone_else[0:5], [int(constants.MIN_ALLOWED_LOCKED)] * 5, [int(constants.MIN_LOCKED_PERIODS)] * 5).estimateGas({'from': origin}))) # Give Ursula and Alice some coins print("Transfer tokens = " + str( token_agent.contract.functions.transfer( ursula1, constants.MIN_ALLOWED_LOCKED * 10).estimateGas({'from': origin}))) tx = token_agent.contract.functions.transfer( ursula1, constants.MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.transfer( ursula2, constants.MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.transfer( ursula3, constants.MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) # Ursula and Alice give Escrow rights to transfer print("Approving transfer = " + str( token_agent.contract.functions.approve( miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6).estimateGas({'from': ursula1}))) tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6)\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6)\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6)\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Ursula and Alice transfer some tokens to the escrow and lock them print("First initial deposit tokens = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 3, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 3, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second initial deposit tokens = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 3, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 3, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third initial deposit tokens = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 3, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 3, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and confirm activity testerchain.time_travel(periods=1) print("First confirm activity = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and mint tokens testerchain.time_travel(periods=1) print("First mining (1 stake) = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second mining (1 stake) = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third/last mining (1 stake) = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) print("First confirm activity again = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity again = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity again = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Confirm again testerchain.time_travel(periods=1) print("First confirm activity + mint = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity + mint = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity + mint = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Get locked tokens print("Getting locked tokens = " + str( miner_agent.contract.functions.getLockedTokens(ursula1).estimateGas())) # Wait 1 period and withdraw tokens testerchain.time_travel(periods=1) print("First withdraw = " + str( miner_agent.contract.functions.withdraw(1).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.withdraw(1).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second withdraw = " + str( miner_agent.contract.functions.withdraw(1).estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.withdraw(1).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third withdraw = " + str( miner_agent.contract.functions.withdraw(1).estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.withdraw(1).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and confirm activity testerchain.time_travel(periods=1) print("First confirm activity after downtime = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity after downtime = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity after downtime = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Ursula and Alice deposit some tokens to the escrow again print("First deposit tokens again = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 2, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 2, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second deposit tokens again = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 2, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 2, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third deposit tokens again = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 2, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 2, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and mint tokens testerchain.time_travel(periods=1) print("First mining again = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second mining again = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third/last mining again = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Create policy policy_id_1 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(constants.POLICY_ID_LENGTH)) number_of_periods = 10 print("First creating policy (1 node, 10 periods) = " + str( policy_agent.contract.functions.createPolicy( policy_id_1, number_of_periods, 0, [ursula1]).estimateGas( { 'from': alice1, 'value': 10000 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_1, number_of_periods, 0, [ursula1])\ .transact({'from': alice1, 'value': 10000}) testerchain.wait_for_receipt(tx) print("Second creating policy (1 node, 10 periods) = " + str( policy_agent.contract.functions.createPolicy( policy_id_2, number_of_periods, 0, [ursula1]).estimateGas( { 'from': alice1, 'value': 10000 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_2, number_of_periods, 0, [ursula1])\ .transact({'from': alice1, 'value': 10000}) testerchain.wait_for_receipt(tx) # Revoke policy print("Revoking policy = " + str( policy_agent.contract.functions.revokePolicy(policy_id_1).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_1).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) tx = policy_agent.contract.functions.revokePolicy(policy_id_2).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) # Create policy with more periods policy_id_1 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(constants.POLICY_ID_LENGTH)) number_of_periods = 100 print("First creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_1, number_of_periods, 50, [ursula2]).estimateGas( { 'from': alice1, 'value': 10050 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula2])\ .transact({'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) print("Second creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_2, number_of_periods, 50, [ursula2]).estimateGas( { 'from': alice1, 'value': 10050 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula2])\ .transact({'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) print("Third creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_3, number_of_periods, 50, [ursula1]).estimateGas( { 'from': alice1, 'value': 10050 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1])\ .transact({'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) # Mine and revoke policy testerchain.time_travel(periods=10) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) print("First mining after downtime = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second mining after downtime = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=10) print("First revoking policy after downtime = " + str( policy_agent.contract.functions.revokePolicy(policy_id_1).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_1).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) print("Second revoking policy after downtime = " + str( policy_agent.contract.functions.revokePolicy(policy_id_2).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_2).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) print("Second revoking policy after downtime = " + str( policy_agent.contract.functions.revokePolicy(policy_id_3).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_3).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) # Create policy with multiple nodes policy_id_1 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(constants.POLICY_ID_LENGTH)) number_of_periods = 100 print("First creating policy (3 nodes, 100 periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3]).estimateGas({ 'from': alice1, 'value': 30150 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3])\ .transact({'from': alice1, 'value': 30150}) testerchain.wait_for_receipt(tx) print("Second creating policy (3 nodes, 100 periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3]).estimateGas({ 'from': alice1, 'value': 30150 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3])\ .transact({'from': alice1, 'value': 30150}) testerchain.wait_for_receipt(tx) print("Third creating policy (2 nodes, 100 periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_3, number_of_periods, 50, [ursula1, ursula2]).estimateGas({ 'from': alice1, 'value': 20100 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1, ursula2])\ .transact({'from': alice1, 'value': 20100}) testerchain.wait_for_receipt(tx) for index in range(5): tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Check regular deposit print("First deposit tokens = " + str( miner_agent.contract.functions.deposit( int(constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.deposit(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second deposit tokens = " + str( miner_agent.contract.functions.deposit( int(constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.deposit(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third deposit tokens = " + str( miner_agent.contract.functions.deposit( int(constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.deposit(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # ApproveAndCall testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) print("First approveAndCall = " + str( token_agent.contract.functions.approveAndCall( miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS))).estimateGas( {'from': ursula1}))) tx = token_agent.contract.functions.approveAndCall(miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS)))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second approveAndCall = " + str( token_agent.contract.functions.approveAndCall( miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS))).estimateGas( {'from': ursula2}))) tx = token_agent.contract.functions.approveAndCall(miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS)))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third approveAndCall = " + str( token_agent.contract.functions.approveAndCall( miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS))).estimateGas( {'from': ursula3}))) tx = token_agent.contract.functions.approveAndCall(miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS)))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Locking tokens testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) print("First locking tokens = " + str( miner_agent.contract.functions.lock(int( constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.lock(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second locking tokens = " + str( miner_agent.contract.functions.lock(int( constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.lock(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third locking tokens = " + str( miner_agent.contract.functions.lock(int( constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.lock(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Divide stake print("First divide stake = " + str( miner_agent.contract.functions.divideStake( 1, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.divideStake( 1, int(constants.MIN_ALLOWED_LOCKED), 2).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second divide stake = " + str( miner_agent.contract.functions.divideStake( 3, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.divideStake( 3, int(constants.MIN_ALLOWED_LOCKED), 2).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) # Divide almost finished stake testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) print("Divide stake (next period is not confirmed) = " + str( miner_agent.contract.functions.divideStake( 0, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Divide stake (next period is confirmed) = " + str( miner_agent.contract.functions.divideStake( 0, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) print("All done!")