From adb11d6785f0360d623b0191603af81842d3db45 Mon Sep 17 00:00:00 2001 From: vzotova Date: Mon, 2 Dec 2019 15:44:39 +0300 Subject: [PATCH] Test for multi-version contract deployment --- nucypher/blockchain/eth/interfaces.py | 12 +-- .../contracts/multiversion/v1/VersionTest.sol | 6 +- .../contracts/multiversion/v2/VersionTest.sol | 6 +- .../blockchain/eth/interfaces/test_chains.py | 81 ++++++++++++++++++- .../eth/interfaces/test_solidity_compiler.py | 10 +-- 5 files changed, 96 insertions(+), 19 deletions(-) diff --git a/nucypher/blockchain/eth/interfaces.py b/nucypher/blockchain/eth/interfaces.py index 49ef147f9..67738c945 100644 --- a/nucypher/blockchain/eth/interfaces.py +++ b/nucypher/blockchain/eth/interfaces.py @@ -664,13 +664,13 @@ class BlockchainDeployerInterface(BlockchainInterface): major, minor, patch = [int(v) for v in version[1:].split(".", 3)] if current_version_parsed[0] == -1 or \ requested_version == 'latest' and \ - (current_version_parsed[0] == -1 or - major > current_version_parsed[0] or - major == current_version_parsed[0] and minor > current_version_parsed[1] or - major == current_version_parsed[0] and minor == current_version_parsed[1] and patch > current_version_parsed[2]) or \ + (major > current_version_parsed[0] or + major == current_version_parsed[0] and minor > current_version_parsed[1] or + major == current_version_parsed[0] and minor == current_version_parsed[1] and patch > current_version_parsed[2]) or \ + requested_version == 'earliest' and \ (major < current_version_parsed[0] or - major == current_version_parsed[0] and minor < current_version_parsed[1] or - major == current_version_parsed[0] and minor == current_version_parsed[1] and patch < current_version_parsed[2]): + major == current_version_parsed[0] and minor < current_version_parsed[1] or + major == current_version_parsed[0] and minor == current_version_parsed[1] and patch < current_version_parsed[2]): current_version_parsed = (major, minor, patch) current_data = data current_version = version diff --git a/tests/blockchain/eth/interfaces/contracts/multiversion/v1/VersionTest.sol b/tests/blockchain/eth/interfaces/contracts/multiversion/v1/VersionTest.sol index 09b80c08e..128e8ee6a 100644 --- a/tests/blockchain/eth/interfaces/contracts/multiversion/v1/VersionTest.sol +++ b/tests/blockchain/eth/interfaces/contracts/multiversion/v1/VersionTest.sol @@ -3,6 +3,8 @@ pragma solidity ^0.5.3; /** * @notice Test extracting version number from dev docs -* @dev |v1.2.3| +* @dev |v1.1.4| */ -contract VersionTest {} +contract VersionTest { + uint16 public constant VERSION = 1; +} diff --git a/tests/blockchain/eth/interfaces/contracts/multiversion/v2/VersionTest.sol b/tests/blockchain/eth/interfaces/contracts/multiversion/v2/VersionTest.sol index b01f2ce83..72b9c7567 100644 --- a/tests/blockchain/eth/interfaces/contracts/multiversion/v2/VersionTest.sol +++ b/tests/blockchain/eth/interfaces/contracts/multiversion/v2/VersionTest.sol @@ -3,6 +3,8 @@ pragma solidity ^0.5.3; /** * @notice Test extracting version number from dev docs -* @dev |v2.3.4| +* @dev |v1.2.3| */ -contract VersionTest {} +contract VersionTest { + uint16 public constant VERSION = 2; +} diff --git a/tests/blockchain/eth/interfaces/test_chains.py b/tests/blockchain/eth/interfaces/test_chains.py index fa19ea767..6f3a6dd03 100644 --- a/tests/blockchain/eth/interfaces/test_chains.py +++ b/tests/blockchain/eth/interfaces/test_chains.py @@ -14,21 +14,24 @@ GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with nucypher. If not, see . """ - +import os +from os.path import dirname, abspath import pytest -from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface +from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface, BlockchainInterfaceFactory from nucypher.blockchain.eth.registry import InMemoryContractRegistry # Prevents TesterBlockchain to be picked up by py.test as a test class +from nucypher.blockchain.eth.sol.compile import SolidityCompiler, SourceDirs +from nucypher.crypto.powers import TransactingPower from nucypher.utilities.sandbox.blockchain import TesterBlockchain as _TesterBlockchain from nucypher.utilities.sandbox.constants import ( DEVELOPMENT_ETH_AIRDROP_AMOUNT, NUMBER_OF_ETH_TEST_ACCOUNTS, NUMBER_OF_STAKERS_IN_BLOCKCHAIN_TESTS, NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS, - TEST_PROVIDER_URI -) + TEST_PROVIDER_URI, + INSECURE_DEVELOPMENT_PASSWORD) @pytest.fixture() @@ -86,3 +89,73 @@ def test_testerchain_creation(testerchain, another_testerchain): tx = {'to': etherbase, 'from': account, 'value': 100} txhash = chain.client.send_transaction(tx) _receipt = chain.wait_for_receipt(txhash) + + +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 + testerchain = _TesterBlockchain(free_transactions=True, compiler=solidity_compiler) + origin = testerchain.etherbase_account + BlockchainInterfaceFactory.register_interface(interface=testerchain) + testerchain.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, + account=origin) + testerchain.transacting_power.activate() + testerchain.connect() + + # Searching both contract through raw data + contract_name = "VersionTest" + requested_version = "v1.2.3" + version, _data = testerchain.find_raw_contract_data(contract_name=contract_name, + requested_version=requested_version) + assert version == requested_version + version, _data = testerchain.find_raw_contract_data(contract_name=contract_name, + requested_version="latest") + assert version == requested_version + + requested_version = "v1.1.4" + version, _data = testerchain.find_raw_contract_data(contract_name=contract_name, + requested_version=requested_version) + assert version == requested_version + version, _data = testerchain.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 = testerchain.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 = testerchain.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 = testerchain.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 = testerchain.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 = testerchain.deploy_contract(deployer_address=origin, + registry=registry, + contract_name=contract_name) + assert contract.version == "v1.2.3" + assert contract.functions.VERSION().call() == 2 diff --git a/tests/blockchain/eth/interfaces/test_solidity_compiler.py b/tests/blockchain/eth/interfaces/test_solidity_compiler.py index 193c9c51d..54012535e 100644 --- a/tests/blockchain/eth/interfaces/test_solidity_compiler.py +++ b/tests/blockchain/eth/interfaces/test_solidity_compiler.py @@ -27,8 +27,8 @@ def test_nucypher_contract_compiled(testerchain, test_registry): origin, *everybody_else = testerchain.client.accounts token_contract_identifier = NucypherTokenDeployer(registry=test_registry, deployer_address=origin).contract_name - assert token_contract_identifier in testerchain._BlockchainDeployerInterface__raw_contract_cache - token_data = testerchain._BlockchainDeployerInterface__raw_contract_cache[token_contract_identifier] + assert token_contract_identifier in testerchain._raw_contract_cache + token_data = testerchain._raw_contract_cache[token_contract_identifier] assert len(token_data) == 1 assert "v0.0.0" in token_data @@ -39,7 +39,7 @@ def test_multi_source_compilation(testerchain): (SolidityCompiler.default_contract_dir(), {TesterBlockchain.TEST_CONTRACTS_DIR}) ]) interfaces = solidity_compiler.compile() - assert interfaces == testerchain._BlockchainDeployerInterface__raw_contract_cache + assert interfaces == testerchain._raw_contract_cache def test_multi_versions(): @@ -54,5 +54,5 @@ def test_multi_versions(): contract_data = interfaces["VersionTest"] assert len(contract_data) == 2 assert "v1.2.3" in contract_data - assert "v2.3.4" in contract_data - assert contract_data["v1.2.3"]["devdoc"] != contract_data["v2.3.4"]["devdoc"] + assert "v1.1.4" in contract_data + assert contract_data["v1.2.3"]["devdoc"] != contract_data["v1.1.4"]["devdoc"]