From 2806c21902b67523b12677592e18ffd06ece0cc2 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Tue, 26 Mar 2024 18:20:11 +0200 Subject: [PATCH 01/19] Add skale-contracts --- setup.py | 3 +- skale/skale_base.py | 63 +++++++++++++++++++++++---------------- skale/skale_manager.py | 12 ++++---- skale/utils/abi_utils.py | 52 -------------------------------- skale/utils/exceptions.py | 7 ----- skale/utils/helper.py | 5 ---- 6 files changed, 45 insertions(+), 97 deletions(-) delete mode 100644 skale/utils/abi_utils.py diff --git a/setup.py b/setup.py index 7892f26e..66922683 100644 --- a/setup.py +++ b/setup.py @@ -43,8 +43,9 @@ install_requires=[ "asyncio==3.4.3", "pyyaml==6.0", - "sgx.py==0.9dev2", "redis==4.4.4", + "sgx.py==0.9dev2", + "skale-contracts==1.0.1a4", "typing-extensions==4.9.0", "web3==6.13.0" ], diff --git a/skale/skale_base.py b/skale/skale_base.py index 3851942f..534d28c1 100644 --- a/skale/skale_base.py +++ b/skale/skale_base.py @@ -20,12 +20,12 @@ import abc import logging +from skale_contracts import skale_contracts + from skale.wallets import BaseWallet -from skale.utils.abi_utils import get_contract_address_by_name, get_contract_abi_by_name from skale.utils.exceptions import InvalidWalletError, EmptyWalletError from skale.utils.web3_utils import default_gas_price, init_web3 -from skale.utils.helper import get_abi from skale.contracts.contract_manager import ContractManager @@ -39,23 +39,30 @@ class EmptyPrivateKey(Exception): class SkaleBase: __metaclass__ = abc.ABCMeta - def __init__(self, endpoint, abi_filepath, + def __init__(self, endpoint, alias_or_address: str, wallet=None, state_path=None, ts_diff=None, provider_timeout=30): - logger.info(f'Initing skale.py, endpoint: {endpoint}, ' - f'wallet: {type(wallet).__name__}') - self._abi_filepath = abi_filepath + logger.info('Initializing skale.py, endpoint: %s, wallet: %s', + endpoint, type(wallet).__name__) self._endpoint = endpoint self.web3 = init_web3(endpoint, state_path=state_path, ts_diff=ts_diff, provider_timeout=provider_timeout) + self.network = skale_contracts.get_network_by_provider(self.web3.provider) + self.project = self.network.get_project(self.project_name) + self.instance = self.project.get_instance(alias_or_address) self.__contracts = {} self.__contracts_info = {} self.set_contracts_info() if wallet: self.wallet = wallet + @property + @abc.abstractmethod + def project_name(self) -> str: + """Name of smart contracts project""" + @property def gas_price(self): return default_gas_price(self.web3) @@ -82,27 +89,32 @@ def set_contracts_info(self): return def init_contract_manager(self): - abi = get_abi(self._abi_filepath) - self.add_lib_contract('contract_manager', ContractManager, abi) + self.add_lib_contract('contract_manager', ContractManager, 'ContractManager') - def __init_contract_from_info(self, abi, contract_info): + def __init_contract_from_info(self, contract_info): if contract_info.upgradeable: - self.init_upgradeable_contract(contract_info, abi) + self.init_upgradeable_contract(contract_info) else: - self.add_lib_contract(contract_info.name, contract_info.contract_class, - abi) + self.add_lib_contract( + contract_info.name, + contract_info.contract_class, + contract_info.contract_name + ) - def init_upgradeable_contract(self, contract_info, abi): + def init_upgradeable_contract(self, contract_info): address = self.get_contract_address(contract_info.contract_name) - self.add_lib_contract(contract_info.name, contract_info.contract_class, - abi, address) - - def add_lib_contract(self, name, contract_class, - abi, contract_address=None): - address = contract_address or get_contract_address_by_name( - abi, name) - logger.debug(f'Fetching abi for {name}, address {address}') - contract_abi = get_contract_abi_by_name(abi, name) + self.add_lib_contract( + contract_info.name, + contract_info.contract_class, + contract_info.contract_name, + address + ) + + def add_lib_contract(self, name: str, contract_class, + contract_name: str, contract_address:str=None): + address = contract_address or self.instance.get_contract_address(contract_name) + logger.debug('Fetching abi for %s, address %s', name, address) + contract_abi = self.instance.abi[contract_name] self.add_contract(name, contract_class( self, name, address, contract_abi)) @@ -118,10 +130,9 @@ def __get_contract_by_name(self, name): def __getattr__(self, name): if name not in self.__contracts: if not self.__contracts_info.get(name): - logger.warning(f'{name} method/contract wasn\'t found') + logger.warning("%s method/contract wasn't found", name) return None - logger.debug(f'Contract {name} wasn\'t inited, creating now') + logger.debug("Contract %s wasn't inited, creating now", name) contract_info = self.__contracts_info[name] - abi = get_abi(self._abi_filepath) - self.__init_contract_from_info(abi, contract_info) + self.__init_contract_from_info(contract_info) return self.__get_contract_by_name(name) diff --git a/skale/skale_manager.py b/skale/skale_manager.py index f52e8d56..87ff5ec5 100644 --- a/skale/skale_manager.py +++ b/skale/skale_manager.py @@ -24,7 +24,7 @@ from skale.contracts.contract_manager import ContractManager from skale.utils.contract_info import ContractInfo from skale.utils.contract_types import ContractTypes -from skale.utils.helper import get_abi, get_contracts_info +from skale.utils.helper import get_contracts_info logger = logging.getLogger(__name__) @@ -86,11 +86,11 @@ def spawn_skale_manager_lib(skale): class SkaleManager(SkaleBase): + """Represents skale-manager smart contracts""" + @property + def project_name(self) -> str: + return 'skale-manager' + def set_contracts_info(self): self.init_contract_manager() - abi = get_abi(self._abi_filepath) self._SkaleBase__contracts_info = get_contracts_info(CONTRACTS_INFO) - if self._SkaleBase__is_debug_contracts(abi): - logger.info('Debug contracts found in ABI file') - self._SkaleBase__contracts_info.update( - get_contracts_info(DEBUG_CONTRACTS_INFO)) diff --git a/skale/utils/abi_utils.py b/skale/utils/abi_utils.py deleted file mode 100644 index c693293a..00000000 --- a/skale/utils/abi_utils.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SKALE.py -# -# Copyright (C) 2019-Present SKALE Labs -# -# SKALE.py is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# SKALE.py 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with SKALE.py. If not, see . - -from skale.utils.exceptions import IncompatibleAbiError - - -def get_abi_key_name(contract_name): - # todo: tmp fix for inconsistent contract names - if contract_name == 'manager' or contract_name == 'token': - return f'skale_{contract_name}_abi' - if contract_name == 'dkg': - return 'skale_d_k_g_abi' - return f'{contract_name}_abi' - - -def get_address_key_name(contract_name): - if contract_name == 'manager' or contract_name == 'token': - return f'skale_{contract_name}_address' - if contract_name == 'dkg': - return 'skale_d_k_g_address' - return f'{contract_name}_address' - - -def get_abi_key(abi, key): - try: - return abi[key] - except KeyError: - raise IncompatibleAbiError(key) - - -def get_contract_address_by_name(abi, name): - return get_abi_key(abi, get_address_key_name(name)) - - -def get_contract_abi_by_name(abi, name): - return get_abi_key(abi, get_abi_key_name(name)) diff --git a/skale/utils/exceptions.py b/skale/utils/exceptions.py index a59912ae..df417dd4 100644 --- a/skale/utils/exceptions.py +++ b/skale/utils/exceptions.py @@ -34,13 +34,6 @@ class SChainNotFoundException(Exception): """Raised when requested sChain is not found""" -class IncompatibleAbiError(Exception): - """Raised when required contract is not found in the ABI file""" - def __init__(self, key): - message = f'Required field was not found in the ABI file: {key}' - super().__init__(message) - - class InvalidNodeIdError(Exception): """Raised when wrong node id passed""" def __init__(self, node_id): diff --git a/skale/utils/helper.py b/skale/utils/helper.py index 0a8b65ee..9af07b7f 100644 --- a/skale/utils/helper.py +++ b/skale/utils/helper.py @@ -94,11 +94,6 @@ def is_valid_ipv4_address(address): return True -def get_abi(abi_filepath=None): - with open(abi_filepath) as data_file: - return json.load(data_file) - - def generate_nonce(): # pragma: no cover return randint(0, 65534) From 11b501f481a750a134a71b3870cf43f05b71bd58 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Tue, 26 Mar 2024 18:45:31 +0200 Subject: [PATCH 02/19] Improve formatting --- skale/skale_base.py | 2 +- skale/utils/helper.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/skale/skale_base.py b/skale/skale_base.py index 534d28c1..0b125643 100644 --- a/skale/skale_base.py +++ b/skale/skale_base.py @@ -111,7 +111,7 @@ def init_upgradeable_contract(self, contract_info): ) def add_lib_contract(self, name: str, contract_class, - contract_name: str, contract_address:str=None): + contract_name: str, contract_address: str = None): address = contract_address or self.instance.get_contract_address(contract_name) logger.debug('Fetching abi for %s, address %s', name, address) contract_abi = self.instance.abi[contract_name] diff --git a/skale/utils/helper.py b/skale/utils/helper.py index 9af07b7f..4a54261c 100644 --- a/skale/utils/helper.py +++ b/skale/utils/helper.py @@ -19,7 +19,6 @@ """ SKALE helper utilities """ import ipaddress -import json import logging import random import socket From 8353d2e47097ddc1642d0843aef6566f531db457 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Wed, 27 Mar 2024 17:19:05 +0200 Subject: [PATCH 03/19] Fix address reading --- tests/manager/schains_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/manager/schains_test.py b/tests/manager/schains_test.py index 4b2dd78a..db242c28 100644 --- a/tests/manager/schains_test.py +++ b/tests/manager/schains_test.py @@ -1,12 +1,12 @@ """ SKALE chain test """ +import json from hexbytes import HexBytes from skale.contracts.manager.schains import FIELDS, SchainStructure from skale.dataclasses.schain_options import SchainOptions from skale.utils.contracts_provision.fake_multisig_contract import FAKE_MULTISIG_DATA_PATH from skale.utils.contracts_provision.main import generate_random_schain_data, create_schain -from skale.utils.helper import get_abi from skale.wallets.web3_wallet import generate_wallet from tests.constants import (DEFAULT_NODE_NAME, DEFAULT_SCHAIN_ID, @@ -184,7 +184,7 @@ def test_add_schain_by_foundation_custom_originator(skale, nodes): type_of_nodes = 1 # test2 schain custom_originator = generate_wallet(skale.web3) - fake_multisig_data = get_abi(FAKE_MULTISIG_DATA_PATH) + fake_multisig_data = json.load(open(FAKE_MULTISIG_DATA_PATH)) payable_contract_address = fake_multisig_data['address'] try: From 77b888792a203b4d677a7ff2a5b380d84ee15f88 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Wed, 27 Mar 2024 17:24:11 +0200 Subject: [PATCH 04/19] Update build --- .github/workflows/publish.yml | 5 +++-- .github/workflows/test.yml | 20 +++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7a4e2968..818ad071 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,10 +20,11 @@ jobs: PIP_USERNAME: ${{ secrets.PIP_USERNAME }} PIP_PASSWORD: ${{ secrets.PIP_PASSWORD }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: + cache: 'pip' python-version: ${{ matrix.python-version }} - name: Install host dependencies run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d999019b..26ad9251 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,12 +13,13 @@ jobs: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} MANAGER_TAG: "1.10.0-v1.10.0.0" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: + cache: 'pip' python-version: ${{ matrix.python-version }} - name: Install python dependencies @@ -30,7 +31,7 @@ jobs: - name: Launch hardhat node working-directory: hardhat-node run: | - docker-compose up -d && sleep 20 + docker-compose up -d && sleep 20 - name: Deploy manager run: | @@ -39,7 +40,7 @@ jobs: - name: Show stats before tests if: always() - run: | + run: | sudo lsblk -f sudo free -h @@ -52,7 +53,7 @@ jobs: - name: Show stats after tests if: always() - run: | + run: | sudo lsblk -f sudo free -h @@ -67,13 +68,14 @@ jobs: MANAGER_TAG: "1.9.0-develop.20" ALLOCATOR_TAG: "2.2.2-develop.0" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: + cache: 'pip' python-version: ${{ matrix.python-version }} - name: Install host dependencies @@ -85,7 +87,7 @@ jobs: - name: Launch hardhat node working-directory: hardhat-node run: | - docker-compose up -d && sleep 20 + docker-compose up -d && sleep 20 - name: Deploy manager contracts run: | @@ -103,6 +105,6 @@ jobs: - name: Show stats after tests if: always() - run: | + run: | sudo lsblk -f sudo free -h From ff3d134674f1e139c976ce08fdf717fd03af2258 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Wed, 27 Mar 2024 17:33:02 +0200 Subject: [PATCH 05/19] Replace abi file with address --- skale/utils/helper.py | 8 ++++++++ tests/helper.py | 9 ++++++--- tests/manager/schains_test.py | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/skale/utils/helper.py b/skale/utils/helper.py index 4a54261c..5bd12000 100644 --- a/skale/utils/helper.py +++ b/skale/utils/helper.py @@ -19,6 +19,7 @@ """ SKALE helper utilities """ import ipaddress +import json import logging import random import socket @@ -93,6 +94,13 @@ def is_valid_ipv4_address(address): return True +def get_abi(abi_filepath: string = None): + if abi_filepath: + with open(abi_filepath, encoding='utf-8') as data_file: + return json.load(data_file) + return {} + + def generate_nonce(): # pragma: no cover return randint(0, 65534) diff --git a/tests/helper.py b/tests/helper.py index 016cab10..c330b78f 100644 --- a/tests/helper.py +++ b/tests/helper.py @@ -7,6 +7,7 @@ from web3 import Web3 from skale import SkaleManager, SkaleAllocator +from skale.utils.helper import get_abi from skale.wallets import Web3Wallet from tests.constants import (ENDPOINT, TEST_ABI_FILEPATH, TEST_ALLOCATOR_ABI_FILEPATH, @@ -32,7 +33,8 @@ def init_skale(web3: Web3, eth_private_key: str = ETH_PRIVATE_KEY, test_abi_filepath: str = TEST_ABI_FILEPATH) -> SkaleManager: wallet = Web3Wallet(eth_private_key, web3) - return SkaleManager(ENDPOINT, test_abi_filepath, wallet) + skale_manager_address = get_abi(test_abi_filepath)['skale_manager_address'] + return SkaleManager(ENDPOINT, skale_manager_address, wallet) def init_skale_allocator( @@ -40,8 +42,9 @@ def init_skale_allocator( eth_private_key: str = ETH_PRIVATE_KEY, test_allocator_abi_filepath: str = TEST_ALLOCATOR_ABI_FILEPATH ) -> SkaleAllocator: - wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - return SkaleAllocator(ENDPOINT, TEST_ALLOCATOR_ABI_FILEPATH, wallet) + wallet = Web3Wallet(eth_private_key, web3) + allocator_address = get_abi(test_allocator_abi_filepath)['allocator_address'] + return SkaleAllocator(ENDPOINT, allocator_address, wallet) @contextmanager diff --git a/tests/manager/schains_test.py b/tests/manager/schains_test.py index db242c28..4b2dd78a 100644 --- a/tests/manager/schains_test.py +++ b/tests/manager/schains_test.py @@ -1,12 +1,12 @@ """ SKALE chain test """ -import json from hexbytes import HexBytes from skale.contracts.manager.schains import FIELDS, SchainStructure from skale.dataclasses.schain_options import SchainOptions from skale.utils.contracts_provision.fake_multisig_contract import FAKE_MULTISIG_DATA_PATH from skale.utils.contracts_provision.main import generate_random_schain_data, create_schain +from skale.utils.helper import get_abi from skale.wallets.web3_wallet import generate_wallet from tests.constants import (DEFAULT_NODE_NAME, DEFAULT_SCHAIN_ID, @@ -184,7 +184,7 @@ def test_add_schain_by_foundation_custom_originator(skale, nodes): type_of_nodes = 1 # test2 schain custom_originator = generate_wallet(skale.web3) - fake_multisig_data = json.load(open(FAKE_MULTISIG_DATA_PATH)) + fake_multisig_data = get_abi(FAKE_MULTISIG_DATA_PATH) payable_contract_address = fake_multisig_data['address'] try: From 1ba7e68c22a1e90fca77961d9a5c4061c4c11ae0 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Wed, 27 Mar 2024 18:17:54 +0200 Subject: [PATCH 06/19] Fix BountyV2 contract name --- skale/skale_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skale/skale_manager.py b/skale/skale_manager.py index 87ff5ec5..b848745c 100644 --- a/skale/skale_manager.py +++ b/skale/skale_manager.py @@ -64,7 +64,7 @@ ContractTypes.API, False), ContractInfo('wallets', 'Wallets', contracts.Wallets, ContractTypes.API, True), - ContractInfo('bounty_v2', 'Bounty', contracts.BountyV2, + ContractInfo('bounty_v2', 'BountyV2', contracts.BountyV2, ContractTypes.API, True), ContractInfo('punisher', 'Punisher', contracts.Punisher, ContractTypes.API, True), From a857c48ecfdd62e4957c96e44b24eca5edf7a602 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Thu, 28 Mar 2024 16:34:41 +0200 Subject: [PATCH 07/19] Fix error with address retrieving --- skale/skale_base.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/skale/skale_base.py b/skale/skale_base.py index 0b125643..9f8e8758 100644 --- a/skale/skale_base.py +++ b/skale/skale_base.py @@ -17,8 +17,11 @@ # You should have received a copy of the GNU Affero General Public License # along with SKALE.py. If not, see . +from __future__ import annotations + import abc import logging +from typing import TYPE_CHECKING from skale_contracts import skale_contracts @@ -28,6 +31,9 @@ from skale.contracts.contract_manager import ContractManager +if TYPE_CHECKING: + from eth_typing import Address + logger = logging.getLogger(__name__) @@ -111,7 +117,7 @@ def init_upgradeable_contract(self, contract_info): ) def add_lib_contract(self, name: str, contract_class, - contract_name: str, contract_address: str = None): + contract_name: str, contract_address: Address = None): address = contract_address or self.instance.get_contract_address(contract_name) logger.debug('Fetching abi for %s, address %s', name, address) contract_abi = self.instance.abi[contract_name] @@ -122,7 +128,7 @@ def add_contract(self, name, contract): self.__contracts[name] = contract def get_contract_address(self, name): - return self.contract_manager.get_contract_address(name) + return self.instance.get_contract_address(name) def __get_contract_by_name(self, name): return self.__contracts[name] From 013432bb9a728d3487726ebeacb233c40c4e53a5 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Thu, 28 Mar 2024 16:45:00 +0200 Subject: [PATCH 08/19] Fix typo in the contract name --- skale/skale_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skale/skale_manager.py b/skale/skale_manager.py index b848745c..8c092586 100644 --- a/skale/skale_manager.py +++ b/skale/skale_manager.py @@ -60,7 +60,7 @@ ContractTypes.API, False), ContractInfo('distributor', 'Distributor', contracts.Distributor, ContractTypes.API, False), - ContractInfo('slashing_table', 'Distributor', contracts.SlashingTable, + ContractInfo('slashing_table', 'SlashingTable', contracts.SlashingTable, ContractTypes.API, False), ContractInfo('wallets', 'Wallets', contracts.Wallets, ContractTypes.API, True), From 36d092c6a8bcd13b104c36bf51721be3c24748ba Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Thu, 28 Mar 2024 16:49:24 +0200 Subject: [PATCH 09/19] Replace Address with ChecksumAddress --- skale/skale_base.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/skale/skale_base.py b/skale/skale_base.py index 9f8e8758..92adbfff 100644 --- a/skale/skale_base.py +++ b/skale/skale_base.py @@ -32,7 +32,7 @@ from skale.contracts.contract_manager import ContractManager if TYPE_CHECKING: - from eth_typing import Address + from eth_typing import Address, ChecksumAddress logger = logging.getLogger(__name__) @@ -127,8 +127,10 @@ def add_lib_contract(self, name: str, contract_class, def add_contract(self, name, contract): self.__contracts[name] = contract - def get_contract_address(self, name): - return self.instance.get_contract_address(name) + def get_contract_address(self, name) -> ChecksumAddress: + return self.web3.to_checksum_address( + self.instance.get_contract_address(name) + ) def __get_contract_by_name(self, name): return self.__contracts[name] From d1d7bca452bd9b5c0022421b5ecb973146361a92 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Fri, 29 Mar 2024 15:41:59 +0200 Subject: [PATCH 10/19] Update node_skales fixture --- tests/conftest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 488a1b3d..75244db2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,6 +25,7 @@ from skale.utils.contracts_provision.fake_multisig_contract import ( deploy_fake_multisig_contract ) +from skale.utils.helper import get_abi from skale.utils.web3_utils import init_web3 from skale.wallets import Web3Wallet @@ -79,8 +80,9 @@ def node_wallets(skale): @pytest.fixture def node_skales(skale, node_wallets): + skale_manager_address = get_abi(TEST_ABI_FILEPATH)['skale_manager_address'] return [ - SkaleManager(ENDPOINT, TEST_ABI_FILEPATH, wallet) + SkaleManager(ENDPOINT, skale_manager_address, wallet) for wallet in node_wallets ] From 00a28f430f9d56c3304c778ea6e0db6c2b67f3c8 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Fri, 29 Mar 2024 15:55:11 +0200 Subject: [PATCH 11/19] Update Skale initialization --- skale/utils/helper.py | 4 ++++ tests/allocator/provision_contracts.py | 4 ++-- tests/conftest.py | 5 ++--- tests/helper.py | 5 ++--- tests/main_test.py | 19 +++++++++++++++---- tests/multithreading_test.py | 3 ++- tests/prepare_data.py | 4 ++-- tests/rotation_history/utils.py | 3 ++- tests/transaction_tools_test.py | 3 ++- 9 files changed, 33 insertions(+), 17 deletions(-) diff --git a/skale/utils/helper.py b/skale/utils/helper.py index 5bd12000..bd5dcd66 100644 --- a/skale/utils/helper.py +++ b/skale/utils/helper.py @@ -101,6 +101,10 @@ def get_abi(abi_filepath: string = None): return {} +def get_skale_manager_address(abi_filepath: string = None) -> str: + return get_abi(abi_filepath)['skale_manager_address'] + + def generate_nonce(): # pragma: no cover return randint(0, 65534) diff --git a/tests/allocator/provision_contracts.py b/tests/allocator/provision_contracts.py index de121775..57e36bf9 100644 --- a/tests/allocator/provision_contracts.py +++ b/tests/allocator/provision_contracts.py @@ -3,7 +3,7 @@ from skale import SkaleAllocator, SkaleManager from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3 -from skale.utils.helper import init_default_logger +from skale.utils.helper import get_skale_manager_address, init_default_logger from skale.utils.contracts_provision.allocator import transfer_tokens_to_allocator, add_test_plan from skale.utils.contracts_provision.main import setup_validator, add_test_permissions from tests.constants import (ENDPOINT, TEST_ABI_FILEPATH, ETH_PRIVATE_KEY, @@ -13,7 +13,7 @@ def init_libs(): web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - return (SkaleManager(ENDPOINT, TEST_ABI_FILEPATH, wallet), + return (SkaleManager(ENDPOINT, get_skale_manager_address(TEST_ABI_FILEPATH), wallet), SkaleAllocator(ENDPOINT, TEST_ALLOCATOR_ABI_FILEPATH, wallet)) diff --git a/tests/conftest.py b/tests/conftest.py index 75244db2..fd0cb2bb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,7 +25,7 @@ from skale.utils.contracts_provision.fake_multisig_contract import ( deploy_fake_multisig_contract ) -from skale.utils.helper import get_abi +from skale.utils.helper import get_skale_manager_address from skale.utils.web3_utils import init_web3 from skale.wallets import Web3Wallet @@ -80,9 +80,8 @@ def node_wallets(skale): @pytest.fixture def node_skales(skale, node_wallets): - skale_manager_address = get_abi(TEST_ABI_FILEPATH)['skale_manager_address'] return [ - SkaleManager(ENDPOINT, skale_manager_address, wallet) + SkaleManager(ENDPOINT, get_skale_manager_address(TEST_ABI_FILEPATH), wallet) for wallet in node_wallets ] diff --git a/tests/helper.py b/tests/helper.py index c330b78f..7f33a1d1 100644 --- a/tests/helper.py +++ b/tests/helper.py @@ -7,7 +7,7 @@ from web3 import Web3 from skale import SkaleManager, SkaleAllocator -from skale.utils.helper import get_abi +from skale.utils.helper import get_abi, get_skale_manager_address from skale.wallets import Web3Wallet from tests.constants import (ENDPOINT, TEST_ABI_FILEPATH, TEST_ALLOCATOR_ABI_FILEPATH, @@ -33,8 +33,7 @@ def init_skale(web3: Web3, eth_private_key: str = ETH_PRIVATE_KEY, test_abi_filepath: str = TEST_ABI_FILEPATH) -> SkaleManager: wallet = Web3Wallet(eth_private_key, web3) - skale_manager_address = get_abi(test_abi_filepath)['skale_manager_address'] - return SkaleManager(ENDPOINT, skale_manager_address, wallet) + return SkaleManager(ENDPOINT, get_skale_manager_address(test_abi_filepath), wallet) def init_skale_allocator( diff --git a/tests/main_test.py b/tests/main_test.py index bf269f62..5e93892c 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -4,6 +4,7 @@ from web3 import HTTPProvider, WebsocketProvider from skale import Skale +from skale.utils.helper import get_skale_manager_address from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3 from skale.contracts.base_contract import BaseContract @@ -18,7 +19,12 @@ def test_lib_init(): web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - skale = Skale(ENDPOINT, TEST_ABI_FILEPATH, wallet, provider_timeout=20) + skale = Skale( + ENDPOINT, + get_skale_manager_address(TEST_ABI_FILEPATH), + wallet, + provider_timeout=20 + ) lib_contracts = skale._SkaleBase__contracts @@ -35,7 +41,7 @@ def test_lib_init(): ws_endpoint = 'ws://localhost:8080' - skale = Skale(ws_endpoint, TEST_ABI_FILEPATH, wallet) + skale = Skale(ws_endpoint, get_skale_manager_address(TEST_ABI_FILEPATH), wallet) assert skale.web3.provider.websocket_timeout == 30 assert skale.web3.provider.conn.websocket_kwargs == { 'max_size': 5 * 1024 * 1024 @@ -44,13 +50,18 @@ def test_lib_init(): file_endpoint = 'file://local_file:1001' with pytest.raises(Exception): - Skale(file_endpoint, TEST_ABI_FILEPATH, wallet) + Skale(file_endpoint, get_skale_manager_address(TEST_ABI_FILEPATH), wallet) def test_contract_init(): web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - skale = Skale(ENDPOINT, TEST_ABI_FILEPATH, wallet, provider_timeout=20) + skale = Skale( + ENDPOINT, + get_skale_manager_address(TEST_ABI_FILEPATH), + wallet, + provider_timeout=20 + ) lib_contracts = skale._SkaleBase__contracts diff --git a/tests/multithreading_test.py b/tests/multithreading_test.py index b6d5591e..f818320f 100644 --- a/tests/multithreading_test.py +++ b/tests/multithreading_test.py @@ -3,12 +3,13 @@ import threading from skale import Skale +from skale.utils.helper import get_skale_manager_address from skale.utils.web3_utils import init_web3 from tests.constants import ENDPOINT, TEST_ABI_FILEPATH, DEFAULT_NODE_NAME def get_node_data(): - skale = Skale(ENDPOINT, TEST_ABI_FILEPATH) + skale = Skale(ENDPOINT, get_skale_manager_address(TEST_ABI_FILEPATH)) for _ in range(0, 30): skale.nodes.get_by_name(DEFAULT_NODE_NAME) diff --git a/tests/prepare_data.py b/tests/prepare_data.py index 0f5830ad..f810a6ce 100644 --- a/tests/prepare_data.py +++ b/tests/prepare_data.py @@ -5,7 +5,7 @@ from skale import SkaleManager from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3 -from skale.utils.helper import init_default_logger +from skale.utils.helper import get_skale_manager_address, init_default_logger from skale.utils.contracts_provision import MONTH_IN_SECONDS from skale.utils.contracts_provision.main import ( add_test2_schain_type, cleanup_nodes_schains, setup_validator, @@ -32,7 +32,7 @@ def prepare_data(cleanup_only): init_default_logger() web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - skale = SkaleManager(ENDPOINT, TEST_ABI_FILEPATH, wallet) + skale = SkaleManager(ENDPOINT, get_skale_manager_address(TEST_ABI_FILEPATH), wallet) add_test_permissions(skale) add_test2_schain_type(skale) # add_test4_schain_type(skale) diff --git a/tests/rotation_history/utils.py b/tests/rotation_history/utils.py index c017a8fb..0091dd13 100644 --- a/tests/rotation_history/utils.py +++ b/tests/rotation_history/utils.py @@ -11,6 +11,7 @@ from skale.contracts.manager.nodes import NodeStatus from skale.utils.contracts_provision.utils import generate_random_node_data from skale.utils.account_tools import send_eth +from skale.utils.helper import get_skale_manager_address from skale.wallets.web3_wallet import generate_wallet from tests.constants import (ENDPOINT, TEST_ABI_FILEPATH) @@ -103,7 +104,7 @@ def register_nodes(skale_instances): def init_skale_from_wallet(wallet) -> Skale: - return Skale(ENDPOINT, TEST_ABI_FILEPATH, wallet) + return Skale(ENDPOINT, get_skale_manager_address(TEST_ABI_FILEPATH), wallet) def send_broadcasts(nodes, skale_instances, group_index, skip_node_index=None, rotation_id=0): diff --git a/tests/transaction_tools_test.py b/tests/transaction_tools_test.py index bf142117..ab69654f 100644 --- a/tests/transaction_tools_test.py +++ b/tests/transaction_tools_test.py @@ -15,6 +15,7 @@ run_tx_with_retry ) from skale.utils.account_tools import generate_account +from skale.utils.helper import get_skale_manager_address from skale.utils.web3_utils import init_web3 from skale.wallets import Web3Wallet from skale.wallets.web3_wallet import generate_wallet @@ -33,7 +34,7 @@ def generate_new_skale(): account = generate_account(web3) wallet = Web3Wallet(account['private_key'], web3) wallet.wait = mock.Mock() - return Skale(ENDPOINT, TEST_ABI_FILEPATH, wallet) + return Skale(ENDPOINT, get_skale_manager_address(TEST_ABI_FILEPATH), wallet) def test_run_tx_with_retry(skale): From a48397cb0c2481b8fc1f499a7280f6a2df6cda5e Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Fri, 29 Mar 2024 16:49:24 +0200 Subject: [PATCH 12/19] Update WebSocket port --- tests/main_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/main_test.py b/tests/main_test.py index 5e93892c..f4408e30 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -39,7 +39,7 @@ def test_lib_init(): isinstance(skale.web3.provider, HTTPProvider) - ws_endpoint = 'ws://localhost:8080' + ws_endpoint = 'ws://localhost:8545' skale = Skale(ws_endpoint, get_skale_manager_address(TEST_ABI_FILEPATH), wallet) assert skale.web3.provider.websocket_timeout == 30 From ac8b20e43465468d334b15e4ba986f4c096a3c28 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Fri, 29 Mar 2024 19:05:17 +0200 Subject: [PATCH 13/19] Update SkaleAllocator configuration --- skale/utils/helper.py | 4 ++++ tests/allocator/provision_contracts.py | 4 ++-- tests/allocator/skale_allocator_test.py | 9 +++++++-- tests/helper.py | 5 ++--- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/skale/utils/helper.py b/skale/utils/helper.py index bd5dcd66..e3a69e46 100644 --- a/skale/utils/helper.py +++ b/skale/utils/helper.py @@ -105,6 +105,10 @@ def get_skale_manager_address(abi_filepath: string = None) -> str: return get_abi(abi_filepath)['skale_manager_address'] +def get_allocator_address(abi_filepath: string = None) -> str: + return get_abi(abi_filepath)['allocator_address'] + + def generate_nonce(): # pragma: no cover return randint(0, 65534) diff --git a/tests/allocator/provision_contracts.py b/tests/allocator/provision_contracts.py index 57e36bf9..ac8b1dd2 100644 --- a/tests/allocator/provision_contracts.py +++ b/tests/allocator/provision_contracts.py @@ -3,7 +3,7 @@ from skale import SkaleAllocator, SkaleManager from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3 -from skale.utils.helper import get_skale_manager_address, init_default_logger +from skale.utils.helper import get_allocator_address, get_skale_manager_address, init_default_logger from skale.utils.contracts_provision.allocator import transfer_tokens_to_allocator, add_test_plan from skale.utils.contracts_provision.main import setup_validator, add_test_permissions from tests.constants import (ENDPOINT, TEST_ABI_FILEPATH, ETH_PRIVATE_KEY, @@ -14,7 +14,7 @@ def init_libs(): web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) return (SkaleManager(ENDPOINT, get_skale_manager_address(TEST_ABI_FILEPATH), wallet), - SkaleAllocator(ENDPOINT, TEST_ALLOCATOR_ABI_FILEPATH, wallet)) + SkaleAllocator(ENDPOINT, get_allocator_address(TEST_ALLOCATOR_ABI_FILEPATH), wallet)) def provision_contracts(): diff --git a/tests/allocator/skale_allocator_test.py b/tests/allocator/skale_allocator_test.py index fb16751a..a4708a38 100644 --- a/tests/allocator/skale_allocator_test.py +++ b/tests/allocator/skale_allocator_test.py @@ -1,6 +1,7 @@ """ SKALE Allocator test """ from skale import SkaleAllocator +from skale.utils.helper import get_allocator_address from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3 from tests.constants import ENDPOINT, TEST_ALLOCATOR_ABI_FILEPATH, ETH_PRIVATE_KEY @@ -9,8 +10,12 @@ def test_init_allocator(): web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - skale_allocator = SkaleAllocator(ENDPOINT, TEST_ALLOCATOR_ABI_FILEPATH, wallet, - provider_timeout=20) + skale_allocator = SkaleAllocator( + ENDPOINT, + get_allocator_address(TEST_ALLOCATOR_ABI_FILEPATH), + wallet, + provider_timeout=20 + ) assert len(skale_allocator._SkaleBase__contracts) == 1 assert skale_allocator.allocator assert skale_allocator.escrow diff --git a/tests/helper.py b/tests/helper.py index 7f33a1d1..4cf5a0ca 100644 --- a/tests/helper.py +++ b/tests/helper.py @@ -7,7 +7,7 @@ from web3 import Web3 from skale import SkaleManager, SkaleAllocator -from skale.utils.helper import get_abi, get_skale_manager_address +from skale.utils.helper import get_allocator_address, get_skale_manager_address from skale.wallets import Web3Wallet from tests.constants import (ENDPOINT, TEST_ABI_FILEPATH, TEST_ALLOCATOR_ABI_FILEPATH, @@ -42,8 +42,7 @@ def init_skale_allocator( test_allocator_abi_filepath: str = TEST_ALLOCATOR_ABI_FILEPATH ) -> SkaleAllocator: wallet = Web3Wallet(eth_private_key, web3) - allocator_address = get_abi(test_allocator_abi_filepath)['allocator_address'] - return SkaleAllocator(ENDPOINT, allocator_address, wallet) + return SkaleAllocator(ENDPOINT, get_allocator_address(test_allocator_abi_filepath), wallet) @contextmanager From 16d535162075a0d0a577307d481b0df8707593a9 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Mon, 1 Apr 2024 18:07:59 +0300 Subject: [PATCH 14/19] Add a project name --- skale/skale_allocator.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/skale/skale_allocator.py b/skale/skale_allocator.py index 12c2f060..bee56a11 100644 --- a/skale/skale_allocator.py +++ b/skale/skale_allocator.py @@ -45,6 +45,11 @@ def spawn_skale_allocator_lib(skale): class SkaleAllocator(SkaleBase): + """Represents skale-allocator smart contracts""" + @property + def project_name(self) -> str: + return 'skale-allocator' + def set_contracts_info(self): self.init_contract_manager() self._SkaleBase__contracts_info = get_contracts_info(CONTRACTS_INFO) From 65e460fa09c23e0850ee121716a1880690a9fb97 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Thu, 4 Apr 2024 18:48:22 +0300 Subject: [PATCH 15/19] Add TimeHelpersWithDebug --- skale/skale_manager.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/skale/skale_manager.py b/skale/skale_manager.py index 8c092586..592b6848 100644 --- a/skale/skale_manager.py +++ b/skale/skale_manager.py @@ -70,11 +70,6 @@ ContractTypes.API, True), ContractInfo('sync_manager', 'SyncManager', contracts.SyncManager, ContractTypes.API, False), -] - - -DEBUG_CONTRACTS_INFO = [ - ContractInfo('time_helpers_with_debug', 'TimeHelpersWithDebug', contracts.TimeHelpersWithDebug, ContractTypes.API, False) ] From d5574e0fac19d5095f5541ce2bdae3765f925dee Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Thu, 4 Apr 2024 19:02:28 +0300 Subject: [PATCH 16/19] Update skale-contracts --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 66922683..dfab96fa 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ "pyyaml==6.0", "redis==4.4.4", "sgx.py==0.9dev2", - "skale-contracts==1.0.1a4", + "skale-contracts==1.0.1a5", "typing-extensions==4.9.0", "web3==6.13.0" ], From ec4a5c888945360eb5ea641e9ebade06a6e88ed2 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Thu, 4 Apr 2024 19:12:47 +0300 Subject: [PATCH 17/19] Remove ContractManager initialization for skale-allocator --- skale/skale_allocator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/skale/skale_allocator.py b/skale/skale_allocator.py index bee56a11..fc499cc8 100644 --- a/skale/skale_allocator.py +++ b/skale/skale_allocator.py @@ -51,5 +51,4 @@ def project_name(self) -> str: return 'skale-allocator' def set_contracts_info(self): - self.init_contract_manager() self._SkaleBase__contracts_info = get_contracts_info(CONTRACTS_INFO) From 6da3a2a51340dbaa0fccd97f618963cbe528bf42 Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Fri, 5 Apr 2024 12:24:02 +0300 Subject: [PATCH 18/19] Don't create Escrow contract without beneficiary specification --- skale/contracts/allocator/escrow.py | 8 +++----- skale/contracts/base_contract.py | 5 ++++- skale/skale_allocator.py | 11 +++++++++++ tests/allocator/skale_allocator_test.py | 4 ++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/skale/contracts/allocator/escrow.py b/skale/contracts/allocator/escrow.py index 0e92a559..c65feda6 100644 --- a/skale/contracts/allocator/escrow.py +++ b/skale/contracts/allocator/escrow.py @@ -27,7 +27,7 @@ def beneficiary_escrow(transaction): @functools.wraps(transaction) def wrapper(self, *args, beneficiary_address, **kwargs): - self.contract = self.init_beneficiary_contract(beneficiary_address) + self.contract = self.skale.instance.get_contract('Escrow', beneficiary_address) return transaction(self, *args, **kwargs) return wrapper @@ -38,10 +38,8 @@ class Escrow(BaseContract): def allocator(self): return self.skale.allocator - def init_beneficiary_contract(self, beneficiary_address: str): - beneficiary_escrow_address = self.allocator.get_escrow_address(beneficiary_address) - return Escrow(self.skale, f'escrow_{beneficiary_address}', beneficiary_escrow_address, - self.contract.abi).contract + def init_contract(self, skale, address, abi) -> None: + self.contract = None @beneficiary_escrow @transaction_method diff --git a/skale/contracts/base_contract.py b/skale/contracts/base_contract.py index e984c1aa..fef65a85 100644 --- a/skale/contracts/base_contract.py +++ b/skale/contracts/base_contract.py @@ -121,7 +121,10 @@ def __init__(self, skale, name, address, abi): self.skale = skale self.name = name self.address = Web3.to_checksum_address(address) - self.contract = skale.web3.eth.contract(address=self.address, abi=abi) + self.init_contract(skale, address, abi) + + def init_contract(self, skale, address, abi) -> None: + self.contract = skale.web3.eth.contract(address=address, abi=abi) def __getattr__(self, attr): """Fallback for contract calls""" diff --git a/skale/skale_allocator.py b/skale/skale_allocator.py index fc499cc8..db0f00ce 100644 --- a/skale/skale_allocator.py +++ b/skale/skale_allocator.py @@ -16,8 +16,11 @@ # # You should have received a copy of the GNU Affero General Public License # along with SKALE.py. If not, see . +from __future__ import annotations import logging +from typing import TYPE_CHECKING +from web3.constants import ADDRESS_ZERO from skale.skale_base import SkaleBase import skale.contracts.allocator as contracts @@ -26,6 +29,9 @@ from skale.utils.contract_types import ContractTypes from skale.utils.helper import get_contracts_info +if TYPE_CHECKING: + from eth_typing import ChecksumAddress + logger = logging.getLogger(__name__) @@ -50,5 +56,10 @@ class SkaleAllocator(SkaleBase): def project_name(self) -> str: return 'skale-allocator' + def get_contract_address(self, name) -> ChecksumAddress: + if name == 'Escrow': + return ADDRESS_ZERO + return super().get_contract_address(name) + def set_contracts_info(self): self._SkaleBase__contracts_info = get_contracts_info(CONTRACTS_INFO) diff --git a/tests/allocator/skale_allocator_test.py b/tests/allocator/skale_allocator_test.py index a4708a38..8fc4a93a 100644 --- a/tests/allocator/skale_allocator_test.py +++ b/tests/allocator/skale_allocator_test.py @@ -16,7 +16,7 @@ def test_init_allocator(): wallet, provider_timeout=20 ) - assert len(skale_allocator._SkaleBase__contracts) == 1 + assert len(skale_allocator._SkaleBase__contracts) == 0 assert skale_allocator.allocator assert skale_allocator.escrow - assert len(skale_allocator._SkaleBase__contracts) == 3 + assert len(skale_allocator._SkaleBase__contracts) == 2 From 5683233376b40cd404cd9c301e7752086773c99b Mon Sep 17 00:00:00 2001 From: Dmytro Stebaiev Date: Tue, 9 Apr 2024 16:24:33 +0300 Subject: [PATCH 19/19] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dfab96fa..ad54f7a8 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ setup( name='skale.py', - version='6.2', + version='7', description='SKALE client tools', long_description_markdown_filename='README.md', author='SKALE Labs',