diff --git a/.circleci/config.yml b/.circleci/config.yml
index 5658503bc..23d621b0e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -126,6 +126,16 @@ workflows:
- deployers
- config
- character
+ - estimate_gas:
+ context: "NuCypher Tests"
+ filters:
+ tags:
+ only: /.*/
+ requires:
+ - actors
+ - deployers
+ - config
+ - character
#
# TODO: Initial Publication Automation
@@ -421,6 +431,19 @@ jobs:
- store_artifacts:
path: ./mypy_reports
+ estimate_gas:
+ <<: *python_36_base
+ steps:
+ - checkout
+ - attach_workspace:
+ at: ~/.local/share/virtualenvs/
+ - run:
+ name: Estimate Gas
+ command: |
+ pipenv run python tests/metrics/estimate_gas.py
+ - store_artifacts:
+ path: tests/metrics/results/
+
test_build:
<<: *python_36_base
steps:
diff --git a/Pipfile b/Pipfile
index 70672d802..c7ce1e6ea 100644
--- a/Pipfile
+++ b/Pipfile
@@ -65,6 +65,7 @@ pytest-mock = "*"
[scripts]
install-solc = "./scripts/install_solc.sh"
+estimate-gas = "python3 tests/metrics/estimate_gas.py"
nucypher = "python3 nucypher/cli.py"
[pipenv]
diff --git a/nucypher/blockchain/eth/scripts/estimate_gas_tester.py b/nucypher/blockchain/eth/scripts/estimate_gas_tester.py
deleted file mode 100755
index ccccfb716..000000000
--- a/nucypher/blockchain/eth/scripts/estimate_gas_tester.py
+++ /dev/null
@@ -1,518 +0,0 @@
-#!/usr/bin/env python3
-"""
-This file is part of nucypher.
-
-nucypher is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-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
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with nucypher. If not, see .
-"""
-
-"""
-Deploy contracts in tester.
-A simple Python script to deploy contracts and then estimate gas for different methods.
-"""
-
-import os
-import sys
-
-
-sys.path.append(os.path.abspath(os.getcwd()))
-
-from os.path import dirname, abspath
-
-from eth_tester import EthereumTester
-from web3 import EthereumTesterProvider
-from constant_sorrow import constants
-
-from nucypher.blockchain.eth.chains import TesterBlockchain
-from nucypher.blockchain.eth.deployers import NucypherTokenDeployer, MinerEscrowDeployer, PolicyManagerDeployer
-from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
-from nucypher.blockchain.eth.sol.compile import SolidityCompiler
-
-from nucypher.blockchain.eth import sol
-
-CONTRACTS_DIR = os.path.join(dirname(abspath(sol.__file__)), 'source', 'contracts')
-
-
-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 = BlockchainDeployerInterface(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.deploy()
- token_agent = token_deployer.make_agent()
-
- miners_escrow_secret = os.urandom(constants.DISPATCHER_SECRET_LENGTH)
- miner_escrow_deployer = MinerEscrowDeployer(
- token_agent=token_agent,
- deployer_address=origin,
- secret_hash=testerchain.interface.w3.sha3(miners_escrow_secret))
-
- miner_escrow_deployer.deploy()
- miner_agent = miner_escrow_deployer.make_agent()
-
- policy_manager_secret = os.urandom(constants.DISPATCHER_SECRET_LENGTH)
- policy_manager_deployer = PolicyManagerDeployer(
- miner_agent=miner_agent,
- deployer_address=origin,
- secret_hash=testerchain.interface.w3.sha3(policy_manager_secret))
-
- 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!")
-
-
-if __name__ == "__main__":
- estimate_gas()
diff --git a/nucypher/config/constants.py b/nucypher/config/constants.py
index 06b5c18ed..d537fe3c6 100644
--- a/nucypher/config/constants.py
+++ b/nucypher/config/constants.py
@@ -16,17 +16,19 @@ along with nucypher. If not, see .
"""
+import os
from collections import namedtuple
from os.path import abspath, dirname
from appdirs import AppDirs
import nucypher
-
+from nucypher.blockchain.eth import sol
# Base Filepaths
BASE_DIR = abspath(dirname(dirname(nucypher.__file__)))
PROJECT_ROOT = abspath(dirname(nucypher.__file__))
+CONTRACT_ROOT = os.path.join(abspath(dirname(sol.__file__)), 'source', 'contracts')
# User Application Filepaths
APP_DIR = AppDirs(nucypher.__title__, nucypher.__author__)
diff --git a/nucypher/utilities/logging.py b/nucypher/utilities/logging.py
index a798defa9..8e2f3ca3a 100644
--- a/nucypher/utilities/logging.py
+++ b/nucypher/utilities/logging.py
@@ -62,16 +62,16 @@ def _get_or_create_user_log_dir():
return pathlib.Path(USER_LOG_DIR).mkdir(parents=True, exist_ok=True)
-def getJsonFileObserver():
+def getJsonFileObserver(name="ursula.log.json", path=USER_LOG_DIR): # TODO: More configurable naming here?
_get_or_create_user_log_dir()
- logfile = DailyLogFile("ursula.log.json", USER_LOG_DIR)
+ logfile = DailyLogFile(name, path)
observer = jsonFileLogObserver(outFile=logfile)
return observer
-def getTextFileObserver():
+def getTextFileObserver(name="ursula.log", path=USER_LOG_DIR):
_get_or_create_user_log_dir()
- logfile = DailyLogFile("ursula.log", USER_LOG_DIR)
+ logfile = DailyLogFile(name, path)
observer = FileLogObserver(formatEvent=formatUrsulaLogEvent, outFile=logfile)
return observer
diff --git a/tests/metrics/estimate_gas.py b/tests/metrics/estimate_gas.py
new file mode 100755
index 000000000..8343c2a75
--- /dev/null
+++ b/tests/metrics/estimate_gas.py
@@ -0,0 +1,585 @@
+#!/usr/bin/env python3
+
+
+"""
+This file is part of nucypher.
+
+nucypher is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+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
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with nucypher. If not, see .
+"""
+
+
+import json
+import os
+from typing import List, Tuple
+
+import time
+from os.path import abspath, dirname
+
+import io
+import re
+from twisted.logger import globalLogPublisher, Logger, jsonFileLogObserver, ILogObserver
+from zope.interface import provider
+
+from nucypher.blockchain.eth.actors import Deployer
+from nucypher.blockchain.eth.agents import NucypherTokenAgent, MinerAgent, PolicyAgent
+from nucypher.blockchain.eth.constants import (
+ DISPATCHER_SECRET_LENGTH,
+ MIN_ALLOWED_LOCKED,
+ MIN_LOCKED_PERIODS,
+ POLICY_ID_LENGTH
+)
+from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
+from nucypher.blockchain.eth.registry import InMemoryEthereumContractRegistry
+from nucypher.blockchain.eth.sol.compile import SolidityCompiler
+from nucypher.config.constants import CONTRACT_ROOT
+from nucypher.utilities.sandbox.blockchain import TesterBlockchain
+
+
+class AnalyzeGas:
+ """
+ Callable twisted log observer with built-in record-keeping for gas estimation runs.
+ """
+
+ # Logging
+ LOG_NAME = 'estimate-gas'
+ LOG_FILENAME = '{}.log.json'.format(LOG_NAME)
+ OUTPUT_DIR = os.path.join(abspath(dirname(__file__)), 'results')
+ JSON_OUTPUT_FILENAME = '{}.json'.format(LOG_NAME)
+
+ # Tweaks
+ CONTRACT_DIR = CONTRACT_ROOT
+ PROVIDER_URI = "tester://pyevm"
+ TEST_ACCOUNTS = 10
+
+ _PATTERN = re.compile(r'''
+ ^ # Anchor at the start of a string
+ (.+) # Any character sequence longer than 1; Captured
+ \s=\s # Space-Equal-Space
+ (\d+) # A sequence of digits; Captured
+ $ # Anchor at the end of the string
+ ''', re.VERBOSE)
+
+ def __init__(self) -> None:
+
+ self.log = Logger(self.__class__.__name__)
+ self.gas_estimations = dict()
+
+ if not os.path.isdir(self.OUTPUT_DIR):
+ os.mkdir(self.OUTPUT_DIR)
+
+ @provider(ILogObserver)
+ def __call__(self, event, *args, **kwargs) -> None:
+
+ if event.get('log_namespace') == self.LOG_NAME:
+ message = event.get("log_format")
+
+ matches = self._PATTERN.match(message)
+ if not matches:
+ self.log.debug("No match for {} with pattern {}".format(message, self._PATTERN))
+ return
+
+ label, gas = matches.groups()
+ self.paint_line(label, gas)
+ self.gas_estimations[label] = int(gas)
+
+ @staticmethod
+ def paint_line(label: str, gas: str) -> None:
+ print('{label} {gas:,}'.format(label=label.ljust(65, '.'), gas=int(gas)))
+
+ def to_json_file(self) -> None:
+ print('Saving JSON Output...')
+
+ epoch_time = str(int(time.time()))
+ timestamped_filename = '{}-{}'.format(epoch_time, self.JSON_OUTPUT_FILENAME)
+ filepath = os.path.join(self.OUTPUT_DIR, timestamped_filename)
+ with open(filepath, 'w') as file:
+ file.write(json.dumps(self.gas_estimations, indent=4))
+
+ def start_collection(self) -> None:
+ print("Starting Data Collection...")
+
+ json_filepath = os.path.join(self.OUTPUT_DIR, AnalyzeGas.LOG_FILENAME)
+ json_io = io.open(json_filepath, "w")
+ json_observer = jsonFileLogObserver(json_io)
+ globalLogPublisher.addObserver(json_observer)
+ globalLogPublisher.addObserver(self)
+
+ def connect_to_blockchain(self) -> TesterBlockchain:
+ print("Deploying Blockchain...")
+
+ solidity_compiler = SolidityCompiler(test_contract_dir=self.CONTRACT_DIR)
+ memory_registry = InMemoryEthereumContractRegistry()
+ interface = BlockchainDeployerInterface(provider_uri=self.PROVIDER_URI, compiler=solidity_compiler,
+ registry=memory_registry)
+
+ testerchain = TesterBlockchain(interface=interface, test_accounts=self.TEST_ACCOUNTS, airdrop=False)
+ return testerchain
+
+ @staticmethod
+ def deploy_contracts(testerchain: TesterBlockchain) -> None:
+ print("Deploying Contracts...")
+
+ origin = testerchain.interface.w3.eth.accounts[0]
+ deployer = Deployer(blockchain=testerchain, deployer_address=origin, bare=True)
+ _txhashes, _agents = deployer.deploy_network_contracts(miner_secret=os.urandom(DISPATCHER_SECRET_LENGTH),
+ policy_secret=os.urandom(DISPATCHER_SECRET_LENGTH))
+
+ @staticmethod
+ def connect_to_contracts(testerchain: TesterBlockchain) -> Tuple[NucypherTokenAgent, MinerAgent, PolicyAgent]:
+ print("Connecting...")
+
+ token_agent = NucypherTokenAgent(blockchain=testerchain)
+ miner_agent = MinerAgent(blockchain=testerchain)
+ policy_agent = PolicyAgent(blockchain=testerchain)
+
+ return token_agent, miner_agent, policy_agent
+
+ def bootstrap_network(self) -> Tuple[TesterBlockchain, List[str]]:
+ print("Bootstrapping testing network...")
+
+ testerchain = self.connect_to_blockchain()
+ self.deploy_contracts(testerchain=testerchain)
+ return testerchain, testerchain.interface.w3.eth.accounts
+
+
+def estimate_gas(analyzer: AnalyzeGas = None) -> None:
+ """
+ Execute a linear sequence of NyCypher transactions mimicking
+ post-deployment usage on a local PyEVM blockchain;
+ Record the resulting estimated transaction gas expenditure.
+
+ Note: The function calls below are *order dependant*
+ """
+
+ #
+ # Setup
+ #
+ if AnalyzeGas is None:
+ analyzer = AnalyzeGas()
+
+ # Logger
+ log = Logger(AnalyzeGas.LOG_NAME)
+
+ # Blockchain
+ testerchain, accounts = analyzer.bootstrap_network()
+ web3 = testerchain.interface.w3
+
+ # Contracts
+ token_agent, miner_agent, policy_agent = analyzer.connect_to_contracts(testerchain=testerchain)
+ token_functions = token_agent.contract.functions
+ miner_functions = miner_agent.contract.functions
+ policy_functions = policy_agent.contract.functions
+
+ # Accounts
+ origin, ursula1, ursula2, ursula3, alice1, *everyone_else = testerchain.interface.w3.eth.accounts
+
+ analyzer.start_collection()
+ print("********* Estimating Gas *********")
+
+ #
+ # Pre deposit tokens
+ #
+ tx = token_functions.approve(miner_agent.contract_address, MIN_ALLOWED_LOCKED * 5).transact({'from': origin})
+ testerchain.wait_for_receipt(tx)
+ log.info("Pre-deposit tokens for 5 owners = " + str(miner_functions.preDeposit(everyone_else[0:5],
+ [MIN_ALLOWED_LOCKED] * 5,
+ [MIN_LOCKED_PERIODS] * 5)
+ .estimateGas({'from': origin})))
+
+ #
+ # Give Ursula and Alice some coins
+ #
+ log.info("Transfer tokens = " + str(token_functions.transfer(ursula1, MIN_ALLOWED_LOCKED * 10).estimateGas({'from': origin})))
+ tx = token_functions.transfer(ursula1, MIN_ALLOWED_LOCKED * 10).transact({'from': origin})
+ testerchain.wait_for_receipt(tx)
+ tx = token_functions.transfer(ursula2, MIN_ALLOWED_LOCKED * 10).transact({'from': origin})
+ testerchain.wait_for_receipt(tx)
+ tx = token_functions.transfer(ursula3, MIN_ALLOWED_LOCKED * 10).transact({'from': origin})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Ursula and Alice give Escrow rights to transfer
+ #
+ log.info("Approving transfer = "
+ + str(token_functions.approve(miner_agent.contract_address, MIN_ALLOWED_LOCKED * 6).estimateGas({'from': ursula1})))
+ tx = token_functions.approve(miner_agent.contract_address, MIN_ALLOWED_LOCKED * 6).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ tx = token_functions.approve(miner_agent.contract_address, MIN_ALLOWED_LOCKED * 6).transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ tx = token_functions.approve(miner_agent.contract_address, MIN_ALLOWED_LOCKED * 6).transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Ursula and Alice transfer some tokens to the escrow and lock them
+ #
+ log.info("First initial deposit tokens = " +
+ str(miner_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second initial deposit tokens = " +
+ str(miner_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third initial deposit tokens = " +
+ str(miner_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED * 3, MIN_LOCKED_PERIODS).transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Wait 1 period and confirm activity
+ #
+ testerchain.time_travel(periods=1)
+ log.info("First confirm activity = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula1})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second confirm activity = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula2})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third confirm activity = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula3})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Wait 1 period and mint tokens
+ #
+ testerchain.time_travel(periods=1)
+ log.info("First mining (1 stake) = " + str(miner_functions.mint().estimateGas({'from': ursula1})))
+ tx = miner_functions.mint().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second mining (1 stake) = " + str(miner_functions.mint().estimateGas({'from': ursula2})))
+ tx = miner_functions.mint().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third/last mining (1 stake) = " + str(miner_functions.mint().estimateGas({'from': ursula3})))
+ tx = miner_functions.mint().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ log.info("First confirm activity again = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula1})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second confirm activity again = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula2})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third confirm activity again = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula3})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Confirm again
+ #
+ testerchain.time_travel(periods=1)
+ log.info("First confirm activity + mint = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula1})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second confirm activity + mint = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula2})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third confirm activity + mint = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula3})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Get locked tokens
+ #
+ log.info("Getting locked tokens = " + str(miner_functions.getLockedTokens(ursula1).estimateGas()))
+
+ #
+ # Wait 1 period and withdraw tokens
+ #
+ testerchain.time_travel(periods=1)
+ log.info("First withdraw = " + str(miner_functions.withdraw(1).estimateGas({'from': ursula1})))
+ tx = miner_functions.withdraw(1).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second withdraw = " + str(miner_functions.withdraw(1).estimateGas({'from': ursula2})))
+ tx = miner_functions.withdraw(1).transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third withdraw = " + str(miner_functions.withdraw(1).estimateGas({'from': ursula3})))
+ tx = miner_functions.withdraw(1).transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Wait 1 period and confirm activity
+ #
+ testerchain.time_travel(periods=1)
+ log.info("First confirm activity after downtime = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula1})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second confirm activity after downtime = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula2})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third confirm activity after downtime = " +
+ str(miner_functions.confirmActivity().estimateGas({'from': ursula3})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Ursula and Alice deposit some tokens to the escrow again
+ #
+ log.info("First deposit tokens again = " +
+ str(miner_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second deposit tokens again = " +
+ str(miner_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third deposit tokens again = " +
+ str(miner_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED * 2, MIN_LOCKED_PERIODS).transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Wait 1 period and mint tokens
+ #
+ testerchain.time_travel(periods=1)
+ log.info("First mining again = " + str(miner_functions.mint().estimateGas({'from': ursula1})))
+ tx = miner_functions.mint().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second mining again = " + str(miner_functions.mint().estimateGas({'from': ursula2})))
+ tx = miner_functions.mint().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third/last mining again = " + str(miner_functions.mint().estimateGas({'from': ursula3})))
+ tx = miner_functions.mint().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Create policy
+ #
+ policy_id_1 = os.urandom(int(POLICY_ID_LENGTH))
+ policy_id_2 = os.urandom(int(POLICY_ID_LENGTH))
+ number_of_periods = 10
+ log.info("First creating policy (1 node, 10 periods) = " +
+ str(policy_functions.createPolicy(policy_id_1, number_of_periods, 0, [ursula1]).estimateGas({'from': alice1, 'value': 10000})))
+ tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 0, [ursula1]).transact({'from': alice1, 'value': 10000})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second creating policy (1 node, 10 periods) = " +
+ str(policy_functions.createPolicy(policy_id_2, number_of_periods, 0, [ursula1]).estimateGas({'from': alice1, 'value': 10000})))
+ tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 0, [ursula1]).transact({'from': alice1, 'value': 10000})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Revoke policy
+ #
+ log.info("Revoking policy = " + str(policy_functions.revokePolicy(policy_id_1).estimateGas({'from': alice1})))
+ tx = policy_functions.revokePolicy(policy_id_1).transact({'from': alice1})
+ testerchain.wait_for_receipt(tx)
+ tx = policy_functions.revokePolicy(policy_id_2).transact({'from': alice1})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Create policy with more periods
+ #
+ policy_id_1 = os.urandom(int(POLICY_ID_LENGTH))
+ policy_id_2 = os.urandom(int(POLICY_ID_LENGTH))
+ policy_id_3 = os.urandom(int(POLICY_ID_LENGTH))
+ number_of_periods = 100
+ log.info("First creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " +
+ str(policy_functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula2]).estimateGas({'from': alice1, 'value': 10050})))
+ tx = policy_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)
+ log.info("Second creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " +
+ str(policy_functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula2]).estimateGas({'from': alice1, 'value': 10050})))
+ tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula2]).transact({'from': alice1, 'value': 10050})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " +
+ str(policy_functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1]).estimateGas({'from': alice1, 'value': 10050})))
+ tx = policy_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_functions.confirmActivity().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+
+ testerchain.time_travel(periods=1)
+ log.info("First mining after downtime = " + str(miner_functions.mint().estimateGas({'from': ursula1})))
+ tx = miner_functions.mint().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second mining after downtime = " + str(miner_functions.mint().estimateGas({'from': ursula2})))
+ tx = miner_functions.mint().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+
+ testerchain.time_travel(periods=10)
+ log.info("First revoking policy after downtime = " +
+ str(policy_functions.revokePolicy(policy_id_1).estimateGas({'from': alice1})))
+ tx = policy_functions.revokePolicy(policy_id_1).transact({'from': alice1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second revoking policy after downtime = " +
+ str(policy_functions.revokePolicy(policy_id_2).estimateGas({'from': alice1})))
+ tx = policy_functions.revokePolicy(policy_id_2).transact({'from': alice1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second revoking policy after downtime = " +
+ str(policy_functions.revokePolicy(policy_id_3).estimateGas({'from': alice1})))
+ tx = policy_functions.revokePolicy(policy_id_3).transact({'from': alice1})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Create policy with multiple nodes
+ #
+ policy_id_1 = os.urandom(int(POLICY_ID_LENGTH))
+ policy_id_2 = os.urandom(int(POLICY_ID_LENGTH))
+ policy_id_3 = os.urandom(int(POLICY_ID_LENGTH))
+ number_of_periods = 100
+ log.info("First creating policy (3 nodes, 100 periods, first reward) = " +
+ str(policy_functions
+ .createPolicy(policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3])
+ .estimateGas({'from': alice1, 'value': 30150})))
+ tx = policy_functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3]).transact({'from': alice1, 'value': 30150})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second creating policy (3 nodes, 100 periods, first reward) = " +
+ str(policy_functions
+ .createPolicy(policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3])
+ .estimateGas({'from': alice1, 'value': 30150})))
+ tx = policy_functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3]).transact({'from': alice1, 'value': 30150})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third creating policy (2 nodes, 100 periods, first reward) = " +
+ str(policy_functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1, ursula2]).estimateGas({'from': alice1, 'value': 20100})))
+ tx = policy_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_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.confirmActivity().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.confirmActivity().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+ testerchain.time_travel(periods=1)
+
+ tx = miner_functions.mint().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.mint().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.mint().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Check regular deposit
+ #
+ log.info("First deposit tokens = " + str(miner_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second deposit tokens = " + str(miner_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third deposit tokens = " + str(miner_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3})))
+ tx = miner_functions.deposit(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # ApproveAndCall
+ #
+ testerchain.time_travel(periods=1)
+
+ tx = miner_functions.mint().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.mint().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.mint().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ log.info("First approveAndCall = " +
+ str(token_functions.approveAndCall(miner_agent.contract_address,
+ MIN_ALLOWED_LOCKED * 2,
+ web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1})))
+ tx = token_functions.approveAndCall(miner_agent.contract_address,
+ MIN_ALLOWED_LOCKED * 2,
+ web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second approveAndCall = " +
+ str(token_functions.approveAndCall(miner_agent.contract_address, MIN_ALLOWED_LOCKED * 2,
+ web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2})))
+ tx = token_functions.approveAndCall(miner_agent.contract_address,
+ MIN_ALLOWED_LOCKED * 2,
+ web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third approveAndCall = " +
+ str(token_functions.approveAndCall(miner_agent.contract_address,
+ MIN_ALLOWED_LOCKED * 2,
+ web3.toBytes(MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3})))
+ tx = token_functions.approveAndCall(miner_agent.contract_address,
+ MIN_ALLOWED_LOCKED * 2,
+ web3.toBytes(MIN_LOCKED_PERIODS)).transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Locking tokens
+ #
+ testerchain.time_travel(periods=1)
+
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.confirmActivity().transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ tx = miner_functions.confirmActivity().transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ log.info("First locking tokens = " +
+ str(miner_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula1})))
+ tx = miner_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second locking tokens = " +
+ str(miner_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula2})))
+ tx = miner_functions.lock(MIN_ALLOWED_LOCKED,MIN_LOCKED_PERIODS).transact({'from': ursula2})
+ testerchain.wait_for_receipt(tx)
+ log.info("Third locking tokens = " +
+ str(miner_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).estimateGas({'from': ursula3})))
+ tx = miner_functions.lock(MIN_ALLOWED_LOCKED, MIN_LOCKED_PERIODS).transact({'from': ursula3})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Divide stake
+ #
+ log.info("First divide stake = " + str(miner_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1})))
+ tx = miner_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Second divide stake = " + str(miner_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1})))
+ tx = miner_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2).transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+
+ #
+ # Divide almost finished stake
+ #
+ testerchain.time_travel(periods=1)
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ testerchain.time_travel(periods=1)
+ log.info("Divide stake (next period is not confirmed) = " + str(miner_functions.divideStake(0, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1})))
+ tx = miner_functions.confirmActivity().transact({'from': ursula1})
+ testerchain.wait_for_receipt(tx)
+ log.info("Divide stake (next period is confirmed) = " + str(miner_functions.divideStake(0, MIN_ALLOWED_LOCKED, 2).estimateGas({'from': ursula1})))
+
+ print("********* All Done! *********")
+
+
+if __name__ == "__main__":
+ print("Starting Up...")
+ analyzer = AnalyzeGas()
+ estimate_gas(analyzer=analyzer)
+ analyzer.to_json_file()