From b80c01bab8e645c49d69f04c7d272994b6642703 Mon Sep 17 00:00:00 2001 From: Dmytro Tkachuk Date: Mon, 2 Mar 2020 16:37:10 +0200 Subject: [PATCH 1/3] SKALE-2261 Move everything to the latest delegation contracts --- .github/workflows/publish.yml | 1 - .github/workflows/test.yml | 2 +- .gitignore | 1 + CHANGELOG.md | 6 +- scripts/deploy_manager.sh | 19 ++- setup.py | 2 +- skale/contracts/__init__.py | 1 + .../delegation/delegation_controller.py | 148 ++++++++++++++++- .../delegation/delegation_service.py | 149 ------------------ skale/contracts/delegation/distributor.py | 90 +++++++++++ skale/contracts/delegation/token_state.py | 11 +- skale/contracts_info.py | 2 + skale/dataclasses/delegation_status.py | 8 +- skale/utils/constants.py | 1 + tests/constants.py | 4 + .../delegation/delegation_controller_test.py | 144 ++++++++++++++++- .../delegation/delegation_service_test.py | 145 +---------------- .../contracts/delegation/distributor_test.py | 36 +++++ .../contracts/delegation/token_state_test.py | 43 ----- tests/main_test.py | 8 + tests/prepare_data.py | 15 +- tests/utils.py | 6 + 22 files changed, 473 insertions(+), 369 deletions(-) create mode 100644 skale/contracts/delegation/distributor.py create mode 100644 tests/contracts/delegation/distributor_test.py delete mode 100644 tests/contracts/delegation/token_state_test.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cf7663b4..410b839e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,7 +17,6 @@ jobs: env: ETH_PRIVATE_KEY: ${{ secrets.ETH_PRIVATE_KEY }} ENDPOINT: ${{ secrets.ENDPOINT }} - MANAGER_BRANCH: "delegation-manual" PIP_USERNAME: ${{ secrets.PIP_USERNAME }} PIP_PASSWORD: ${{ secrets.PIP_PASSWORD }} steps: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c3224fb..8268e745 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: ETH_PRIVATE_KEY: ${{ secrets.ETH_PRIVATE_KEY }} ENDPOINT: ${{ secrets.ENDPOINT }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - MANAGER_BRANCH: "delegation-manual" + MANAGER_BRANCH: "delegation-v2" steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/.gitignore b/.gitignore index 1be648cb..4851c4d3 100644 --- a/.gitignore +++ b/.gitignore @@ -114,6 +114,7 @@ schain.json abi.json test_abi.json +unique.json .DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 734cadb6..fba2c418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [3.0.0] - Unreleased +## [3.1] + +Updated delegation functionality + +## [3.0.0] ### Added diff --git a/scripts/deploy_manager.sh b/scripts/deploy_manager.sh index 584a348f..9ba3f984 100644 --- a/scripts/deploy_manager.sh +++ b/scripts/deploy_manager.sh @@ -5,15 +5,22 @@ set -e : "${ETH_PRIVATE_KEY?Need to set ETH_PRIVATE_KEY}" : "${MANAGER_BRANCH?Need to set MANAGER_BRANCH}" -docker run -d --network host --name ganache trufflesuite/ganache-cli:v6.8.1-beta.0 \ - --account="${ETH_PRIVATE_KEY},100000000000000000000000000" -l 80000000 - export DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +export DOCKER_NETWORK_ENDPOINT=http://ganache:8545 + +docker rm -f ganache || true +docker network create testnet || true + +docker run -d --network testnet -p 8545:8545 -p 8546:8546 \ + --name ganache trufflesuite/ganache-cli:v6.8.1-beta.0 \ + --account="0x${ETH_PRIVATE_KEY},100000000000000000000000000" -l 80000000 docker run \ -v $DIR/contracts_data:/usr/src/manager/data \ - --network host \ + --network testnet \ + -e ENDPOINT=$DOCKER_NETWORK_ENDPOINT \ + -e PRIVATE_KEY=$ETH_PRIVATE_KEY \ skalenetwork/skale-manager:$MANAGER_BRANCH-latest \ - npx truffle migrate --network test + npx truffle migrate --network unique -cp $DIR/contracts_data/test.json $DIR/../test_abi.json +cp $DIR/contracts_data/unique.json $DIR/../test_abi.json diff --git a/setup.py b/setup.py index 67c30f66..4bc6cfe7 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ setup( name='skale.py', - version='3.0', + version='3.1', description='SKALE client tools', long_description_markdown_filename='README.md', author='SKALE Labs', diff --git a/skale/contracts/__init__.py b/skale/contracts/__init__.py index f307611f..e1175baf 100644 --- a/skale/contracts/__init__.py +++ b/skale/contracts/__init__.py @@ -20,5 +20,6 @@ from skale.contracts.delegation.delegation_controller import DelegationController from skale.contracts.delegation.validator_service import ValidatorService from skale.contracts.delegation.token_state import TokenState +from skale.contracts.delegation.distributor import Distributor from skale.contracts.dkg import DKG diff --git a/skale/contracts/delegation/delegation_controller.py b/skale/contracts/delegation/delegation_controller.py index fd100fe8..377e8489 100644 --- a/skale/contracts/delegation/delegation_controller.py +++ b/skale/contracts/delegation/delegation_controller.py @@ -17,10 +17,18 @@ # You should have received a copy of the GNU Affero General Public License # along with SKALE.py. If not, see . -from skale.contracts import BaseContract +from skale.contracts import BaseContract, transaction_method from skale.utils.helper import format_fields +from skale.transactions.tools import post_transaction +from skale.dataclasses.tx_res import TxRes +from skale.utils.constants import GAS +from skale.dataclasses.delegation_status import DelegationStatus -FIELDS = ['address', 'validator_id', 'amount', 'delegation_period', 'created', 'info'] + +FIELDS = [ + 'address', 'validator_id', 'amount', 'delegation_period', 'created', + 'started', 'finished', 'info' +] class DelegationController(BaseContract): @@ -35,6 +43,17 @@ def get_delegation(self, delegation_id: int) -> dict: """ return self.__raw_get_delegation(delegation_id) + def get_delegation_full(self, delegation_id: int) -> dict: + """Returns delegation structure with ID and status fields. + + :returns: Info about delegation request + :rtype: dict + """ + delegation = self.get_delegation(delegation_id) + delegation['id'] = delegation_id + delegation['status'] = self._get_delegation_status(delegation_id) + return delegation + def __raw_get_delegation(self, delegation_id: int) -> list: """Returns raw delegation fields. @@ -42,3 +61,128 @@ def __raw_get_delegation(self, delegation_id: int) -> list: :rtype: list """ return self.contract.functions.getDelegation(delegation_id).call() + + def _get_delegation_ids_by_validator(self, validator_id: int) -> list: + delegation_ids_len = self._get_delegation_ids_len_by_validator(validator_id) + return [ + self.contract.functions.delegationsByValidator(validator_id, _id).call() + for _id in range(delegation_ids_len) + ] + + def _get_delegation_ids_by_holder(self, address: str) -> list: + delegation_ids_len = self._get_delegation_ids_len_by_holder(address) + return [ + self.contract.functions.delegationsByHolder(address, _id).call() + for _id in range(delegation_ids_len) + ] + + def _get_delegation_ids_len_by_validator(self, validator_id: int) -> list: + return self.contract.functions.getDelegationsByValidatorLength(validator_id).call() + + def _get_delegation_ids_len_by_holder(self, address: str) -> list: + return self.contract.functions.getDelegationsByHolderLength(address).call() + + def _get_delegation_state_index(self, delegation_id: int) -> str: + return self.contract.functions.getState(delegation_id).call() + + def _get_delegation_status(self, delegation_id: int) -> str: + index = self._get_delegation_state_index(delegation_id) + return DelegationStatus(index).name + + def get_all_delegations(self, delegation_ids: list) -> list: + """Returns list of formatted delegations with particular status. + + :param delegation_ids: List of delegation IDs + :type address: list + :returns: List of formatted delegations + :rtype: list + """ + return [ + self.skale.delegation_controller.get_delegation_full(_id) + for _id in delegation_ids + ] + + def get_all_delegations_by_holder(self, address: str) -> list: + """Returns list of formatted delegations for token holder. + + :param address: Ethereum address + :type address: str + :returns: List of formatted delegation requests + :rtype: list + """ + delegation_ids = self._get_delegation_ids_by_holder(address) + return self.get_all_delegations(delegation_ids) + + def get_all_delegations_by_validator(self, validator_id: int) -> list: + """Returns list of formatted delegations for validator. + + :param validator_id: ID of the validator + :type address: int + :returns: List of formatted delegations + :rtype: list + """ + validator_id = int(validator_id) + delegation_ids = self._get_delegation_ids_by_validator(validator_id) + return self.get_all_delegations(delegation_ids) + + @transaction_method + def delegate(self, validator_id: int, amount: int, delegation_period: int, info: str) -> TxRes: + """Creates request to delegate amount of tokens to validator_id. + + :param validator_id: ID of the validator to delegate tokens + :type validator_id: int + :param amount: Amount of tokens to delegate + :type amount: int + :param delegation_period: Period of delegation + :type delegation_period: int + :param info: Delegation request information + :type info: str + :returns: Transaction results + :rtype: TxRes + """ + func = self.contract.functions.delegate(validator_id, amount, delegation_period, info) + return post_transaction(self.skale.wallet, func, GAS['delegate']) + + @transaction_method + def accept_pending_delegation(self, delegation_id: int) -> TxRes: + """Accepts a pending delegation by delegation ID. + + :param delegation_id: Delegation ID to accept + :type delegation_id: int + :returns: Transaction results + :rtype: TxRes + """ + func = self.contract.functions.acceptPendingDelegation(delegation_id) + return post_transaction(self.skale.wallet, func, GAS['accept_pending_delegation']) + + @transaction_method + def cancel_pending_delegation(self, delegation_id: int) -> TxRes: + """Cancel pending delegation request. + + :param delegation_id: ID of the delegation to cancel + :type delegation_id: int + :returns: Transaction results + :rtype: TxRes + """ + func = self.contract.functions.cancelPendingDelegation(delegation_id) + return post_transaction(self.skale.wallet, func, GAS['cancel_pending_delegation']) + + def get_delegated_to_validator_now(self, validator_id: int) -> int: + """Amount of delegated tokens to the validator + + :param validator_id: ID of the validator + :type validator_id: int + :returns: Amount of delegated tokens + :rtype: int + """ + return self.contract.functions.getAndUpdateDelegatedToValidatorNow(validator_id).call() + + def get_delegated_amount(self, address: str) -> int: + """Amount of delegated tokens by token holder + + :param address: Token holder address + :type address: str + :returns: Amount of delegated tokens + :rtype: int + """ + return self.contract.functions.getAndUpdateDelegatedAmount(address).call() diff --git a/skale/contracts/delegation/delegation_service.py b/skale/contracts/delegation/delegation_service.py index 1568cf25..15fa059f 100644 --- a/skale/contracts/delegation/delegation_service.py +++ b/skale/contracts/delegation/delegation_service.py @@ -22,8 +22,6 @@ from skale.dataclasses.tx_res import TxRes from skale.utils.constants import GAS -from skale.dataclasses.delegation_status import DelegationStatus - class DelegationService(BaseContract): """Wrapper for DelegationService.sol functions""" @@ -48,109 +46,6 @@ def register_validator(self, name: str, description: str, fee_rate: int, name, description, fee_rate, min_delegation_amount) return post_transaction(self.skale.wallet, func, GAS['register_validator']) - @transaction_method - def delegate(self, validator_id: int, amount: int, delegation_period: int, info: str) -> TxRes: - """Creates request to delegate amount of tokens to validator_id. - - :param validator_id: ID of the validator to delegate tokens - :type validator_id: int - :param amount: Amount of tokens to delegate - :type amount: int - :param delegation_period: Period of delegation - :type delegation_period: int - :param info: Delegation request information - :type info: str - :returns: Transaction results - :rtype: TxRes - """ - func = self.contract.functions.delegate(validator_id, amount, delegation_period, info) - return post_transaction(self.skale.wallet, func, GAS['delegate']) - - def _get_delegation_ids_by_validator(self, address: str, status: DelegationStatus) -> list: - # return self.contract.functions.getDelegationsByValidator(status.value).call({ # todo: tmp - return self.contract.functions.getDelegationsForValidator(status.value).call({ - 'from': address - }) - - def _get_delegation_ids_by_holder(self, address: str, status: DelegationStatus) -> list: - return self.contract.functions.getDelegationsByHolder(status.value).call({ - 'from': address - }) - - def get_delegations(self, address: str, status: DelegationStatus, account_type: str) -> list: - """Returns list of formatted delegations with particular status. - - :param address: Ethereum address - :type address: str - :param status: Delegation status - :type address: DelegationStatus - :param address: Account type - holder or validator - :type address: str - :returns: List of formatted delegation requests - :rtype: list - """ - delegations = [] - - if account_type == 'validator': - delegation_ids = self._get_delegation_ids_by_validator(address, status) - else: - delegation_ids = self._get_delegation_ids_by_holder(address, status) - - for _id in delegation_ids: - delegation = self.skale.delegation_controller.get_delegation(_id) - delegation['status'] = status.name - delegation['id'] = _id - delegations.append(delegation) - return delegations - - def get_all_delegations(self, address: str, account_type: str): - """Returns list of formatted delegations. - - :param address: Ethereum address - :type address: str - :param address: Account type - holder or validator - :type address: str - :returns: List of formatted delegation requests - :rtype: list - """ - delegations = [] - for status in DelegationStatus: - _delegations = self.get_delegations(address, status, account_type) - delegations.extend(_delegations) - return delegations - - def get_all_delegations_by_holder(self, address: str) -> list: - """Returns list of formatted delegations for token holder. - - :param address: Ethereum address - :type address: str - :returns: List of formatted delegation requests - :rtype: list - """ - return self.get_all_delegations(address, 'holder') - - def get_all_delegations_by_validator(self, address: str) -> list: - """Returns list of formatted delegations for validator. - - :param address: Ethereum address - :type address: str - :returns: List of formatted delegation requests - :rtype: list - """ - return self.get_all_delegations(address, 'validator') - - @transaction_method - def accept_pending_delegation(self, delegation_id: int) -> TxRes: - """Accepts a pending delegation by delegation ID. - - :param delegation_id: Delegation ID to accept - :type delegation_id: int - :returns: Transaction results - :rtype: TxRes - """ - func = self.contract.functions.acceptPendingDelegation(delegation_id) - return post_transaction(self.skale.wallet, func, GAS['accept_pending_delegation']) - @transaction_method def link_node_address(self, node_address: str) -> TxRes: """Link node address to your validator account. @@ -174,47 +69,3 @@ def unlink_node_address(self, node_address: str) -> TxRes: """ func = self.contract.functions.unlinkNodeAddress(node_address) return post_transaction(self.skale.wallet, func, GAS['unlink_node_address']) - - @transaction_method - def cancel_pending_delegation(self, delegation_id: int) -> TxRes: - """Cancel pending delegation request. - - :param delegation_id: ID of the delegation to cancel - :type delegation_id: int - :returns: Transaction results - :rtype: TxRes - """ - func = self.contract.functions.cancelPendingDelegation(delegation_id) - return post_transaction(self.skale.wallet, func, GAS['cancel_pending_delegation']) - - def get_delegated_amount(self, validator_id: int) -> int: - return self.contract.functions.getDelegatedAmount(validator_id).call() - - def get_delegated_of(self, address: str) -> int: - return self.contract.functions.getDelegatedOf(address).call() - - @transaction_method - def withdraw_bounty(self, bounty_collection_address: str, amount: int) -> TxRes: - """Withdraw earned validator bounty. - - :param bounty_collection_address: Address to transfer funds - :type bounty_collection_address: str - :param amount: Amount of tokens to withdraw - :type amount: int - :returns: Transaction results - :rtype: TxRes - """ - func = self.contract.functions.withdrawBounty(bounty_collection_address, amount) - return post_transaction(self.skale.wallet, func, GAS['withdraw_bounty']) - - def get_earned_bounty_amount(self, address: str) -> int: - """Returns earned bounty amount for validator. - - :param address: Ethereum address - :type address: str - :returns: Amount of earned bounty - :rtype: int - """ - return self.contract.functions.getEarnedBountyAmount().call({ - 'from': address - }) diff --git a/skale/contracts/delegation/distributor.py b/skale/contracts/delegation/distributor.py new file mode 100644 index 00000000..3214fe06 --- /dev/null +++ b/skale/contracts/delegation/distributor.py @@ -0,0 +1,90 @@ +# -*- 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 functools import wraps + +from skale.contracts import BaseContract, transaction_method +from skale.transactions.tools import post_transaction +from skale.dataclasses.tx_res import TxRes +from skale.utils.constants import GAS + + +def formatter(method): + @wraps(method) + def wrapper(self, *args, **kwargs): + res = method(self, *args, **kwargs) + return { + 'earned': res[0], + 'end_month': res[1], + } + return wrapper + + +class Distributor(BaseContract): + """Wrapper for Distributor.sol functions""" + + @formatter + def get_earned_bounty_amount(self, validator_id: int) -> dict: + """Get earned bounty amount for the validator + + :param validator_id: ID of the validator + :type validator_id: int + :returns: Earned bounty amount and end month + :rtype: dict + """ + return self.contract.functions.getAndUpdateEarnedBountyAmount(validator_id).call() + + @formatter + def get_earned_fee_amount(self, address: str) -> dict: + """Get earned fee amount for the address + + :param address: Address of the validator + :type address: str + :returns: Earned bounty amount and end month + :rtype: dict + """ + return self.contract.functions.getEarnedFeeAmount().call({ + 'from': address + }) + + @transaction_method + def withdraw_bounty(self, validator_id: int, to: str) -> TxRes: + """Withdraw earned bounty to specified address + + :param validator_id: ID of the validator + :type validator_id: int + :param to: Address to transfer bounty + :type to: str + :returns: Transaction results + :rtype: TxRes + """ + func = self.contract.functions.withdrawBounty(validator_id, to) + return post_transaction(self.skale.wallet, func, GAS['withdraw_bounty']) + + @transaction_method + def withdraw_fee(self, to: str) -> TxRes: + """Withdraw earned fee to specified address + + :param to: Address to transfer bounty + :type to: str + :returns: Transaction results + :rtype: TxRes + """ + func = self.contract.functions.withdrawFee(to) + return post_transaction(self.skale.wallet, func, GAS['withdraw_fee']) diff --git a/skale/contracts/delegation/token_state.py b/skale/contracts/delegation/token_state.py index 77d8d1ec..465ee9a2 100644 --- a/skale/contracts/delegation/token_state.py +++ b/skale/contracts/delegation/token_state.py @@ -17,17 +17,8 @@ # You should have received a copy of the GNU Affero General Public License # along with SKALE.py. If not, see . -from skale.contracts import BaseContract, transaction_method - -from skale.transactions.tools import post_transaction -from skale.dataclasses.tx_res import TxRes -from skale.utils.constants import GAS +from skale.contracts import BaseContract class TokenState(BaseContract): """Wrapper for TokenState.sol functions""" - - @transaction_method - def _skip_transition_delay(self, delegation_id: int) -> TxRes: # internal function - func = self.contract.functions.skipTransitionDelay(delegation_id) - return post_transaction(self.skale.wallet, func, GAS['skip_transition_delay']) diff --git a/skale/contracts_info.py b/skale/contracts_info.py index 6cf0c7a6..8111d002 100644 --- a/skale/contracts_info.py +++ b/skale/contracts_info.py @@ -50,6 +50,8 @@ ContractInfo('validator_service', 'ValidatorService', contracts.ValidatorService, ContractTypes.API, False), ContractInfo('token_state', 'TokenState', contracts.TokenState, + ContractTypes.API, False), + ContractInfo('distributor', 'Distributor', contracts.Distributor, ContractTypes.API, False) ] diff --git a/skale/dataclasses/delegation_status.py b/skale/dataclasses/delegation_status.py index 0b117647..f25bd675 100644 --- a/skale/dataclasses/delegation_status.py +++ b/skale/dataclasses/delegation_status.py @@ -23,6 +23,8 @@ class DelegationStatus(Enum): PROPOSED = 0 ACCEPTED = 1 - DELEGATED = 2 - ENDING_DELEGATED = 3 - COMPLETED = 4 + CANCELED = 2 + REJECTED = 3 + DELEGATED = 4 + UNDELEGATION_REQUESTED = 5 + COMPLETED = 6 diff --git a/skale/utils/constants.py b/skale/utils/constants.py index 497cb3d2..3a52edf5 100644 --- a/skale/utils/constants.py +++ b/skale/utils/constants.py @@ -47,6 +47,7 @@ 'unlink_node_address': 1000000, 'cancel_pending_delegation': 1000000, 'withdraw_bounty': 3000000, + 'withdraw_fee': 3000000, 'skip_transition_delay': 1000000, 'set_msr': 200000 diff --git a/tests/constants.py b/tests/constants.py index e04af0b0..fa232385 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -60,3 +60,7 @@ D_DELEGATION_INFO = 'test' NOT_EXISTING_ID = 123123 + +MONTH_IN_SECONDS = (60 * 60 * 24 * 31) + 100 + +DELEGATION_STRUCT_LEN = 8 diff --git a/tests/contracts/delegation/delegation_controller_test.py b/tests/contracts/delegation/delegation_controller_test.py index cb7da05f..89da0bb9 100644 --- a/tests/contracts/delegation/delegation_controller_test.py +++ b/tests/contracts/delegation/delegation_controller_test.py @@ -1,9 +1,16 @@ """ Tests for contracts/delegation/delegation_controller.py """ import pytest -from tests.constants import NOT_EXISTING_ID, D_DELEGATION_ID +from tests.constants import (NOT_EXISTING_ID, D_DELEGATION_ID, D_DELEGATION_INFO, D_VALIDATOR_ID, + D_DELEGATION_AMOUNT, D_DELEGATION_PERIOD, DELEGATION_STRUCT_LEN, + MONTH_IN_SECONDS) from skale.contracts.delegation.delegation_controller import FIELDS +from tests.utils import skip_evm_time + + +def _get_number_of_delegations(skale): + return skale.delegation_controller._get_delegation_ids_len_by_validator(D_VALIDATOR_ID) def test_get_raw_not_exist(skale): @@ -11,7 +18,142 @@ def test_get_raw_not_exist(skale): skale.delegation_controller._DelegationController__raw_get_delegation(NOT_EXISTING_ID) +def test_get_raw(skale): + delegation_struct = skale.delegation_controller._DelegationController__raw_get_delegation( + D_DELEGATION_ID + ) + assert len(delegation_struct) == DELEGATION_STRUCT_LEN + + def test_get(skale): delegation = skale.delegation_controller.get_delegation(D_DELEGATION_ID) assert list(delegation.keys()) == FIELDS assert [k for k, v in delegation.items() if v is None] == [] + + +def test_delegate(skale): + num_of_delegations_before = _get_number_of_delegations(skale) + _delegate_and_activate(skale) + num_of_delegations_after = _get_number_of_delegations(skale) + assert num_of_delegations_after == num_of_delegations_before + 1 + + delegations = skale.delegation_controller.get_all_delegations_by_validator( + validator_id=D_VALIDATOR_ID + ) + assert delegations[-1]['info'] == D_DELEGATION_INFO + + +def test_get_delegation_ids_by_validator(skale): + delegation_ids = skale.delegation_controller._get_delegation_ids_by_validator( + validator_id=D_VALIDATOR_ID + ) + delegation_ids_len = skale.delegation_controller._get_delegation_ids_len_by_validator( + D_VALIDATOR_ID + ) + assert len(delegation_ids) == delegation_ids_len + latest_delegation = skale.delegation_controller.get_delegation(delegation_ids[-1]) + assert latest_delegation['validator_id'] == D_VALIDATOR_ID + + +def test_get_all_delegations_by_holder(skale): + delegations = skale.delegation_controller.get_all_delegations_by_holder( + skale.wallet.address + ) + assert all([delegation['address'] == skale.wallet.address for delegation in delegations]) + + +def test_get_all_delegations_by_validator(skale): + delegations = skale.delegation_controller.get_all_delegations_by_validator( + validator_id=D_VALIDATOR_ID + ) + assert all([delegation['validator_id'] == D_VALIDATOR_ID for delegation in delegations]) + + +def test_accept_pending_delegation(skale): + skale.delegation_controller.delegate( + validator_id=D_VALIDATOR_ID, + amount=D_DELEGATION_AMOUNT, + delegation_period=D_DELEGATION_PERIOD, + info=D_DELEGATION_INFO, + wait_for=True + ) + delegations = skale.delegation_controller.get_all_delegations_by_validator( + validator_id=D_VALIDATOR_ID + ) + delegation_id = delegations[-1]['id'] + assert delegations[-1]['status'] == 'PROPOSED' + skale.delegation_controller.accept_pending_delegation( + delegation_id, + wait_for=True + ) + delegations = skale.delegation_controller.get_all_delegations_by_validator( + validator_id=D_VALIDATOR_ID + ) + assert delegations[-1]['id'] == delegation_id + assert delegations[-1]['status'] == 'ACCEPTED' + skip_evm_time(skale.web3, MONTH_IN_SECONDS) + + +def test_cancel_pending_delegation(skale): + skale.delegation_controller.delegate( + validator_id=D_VALIDATOR_ID, + amount=D_DELEGATION_AMOUNT, + delegation_period=D_DELEGATION_PERIOD, + info=D_DELEGATION_INFO, + wait_for=True + ) + delegations = skale.delegation_controller.get_all_delegations_by_validator( + validator_id=D_VALIDATOR_ID + ) + delegation_id = delegations[-1]['id'] + assert delegations[-1]['status'] == 'PROPOSED' + skale.delegation_controller.cancel_pending_delegation( + delegation_id, + wait_for=True + ) + delegations = skale.delegation_controller.get_all_delegations_by_validator( + validator_id=D_VALIDATOR_ID + ) + assert delegations[-1]['id'] == delegation_id + assert delegations[-1]['status'] == 'CANCELED' + skip_evm_time(skale.web3, MONTH_IN_SECONDS) + + +def _delegate_and_activate(skale): + skale.delegation_controller.delegate( + validator_id=D_VALIDATOR_ID, + amount=D_DELEGATION_AMOUNT, + delegation_period=D_DELEGATION_PERIOD, + info=D_DELEGATION_INFO, + wait_for=True + ) + delegation_ids = skale.delegation_controller._get_delegation_ids_by_validator( + validator_id=D_VALIDATOR_ID + ) + skale.delegation_controller.accept_pending_delegation( + delegation_ids[-1], + wait_for=True + ) + skip_evm_time(skale.web3, MONTH_IN_SECONDS) + + +def test_get_delegated_to_validator_now(skale): + delegated_amount_before = skale.delegation_controller.get_delegated_to_validator_now( + D_VALIDATOR_ID + ) + _delegate_and_activate(skale) + delegated_amount_after = skale.delegation_controller.get_delegated_to_validator_now( + D_VALIDATOR_ID + ) + assert delegated_amount_after == delegated_amount_before + D_DELEGATION_AMOUNT + + +def test_get_delegated_amount(skale): + delegated_amount_before = skale.delegation_controller.get_delegated_amount( + skale.wallet.address + ) + _delegate_and_activate(skale) + delegated_amount_after = skale.delegation_controller.get_delegated_amount( + skale.wallet.address + ) + assert delegated_amount_after == delegated_amount_before + D_DELEGATION_AMOUNT diff --git a/tests/contracts/delegation/delegation_service_test.py b/tests/contracts/delegation/delegation_service_test.py index 5f7b9ef6..542a623f 100644 --- a/tests/contracts/delegation/delegation_service_test.py +++ b/tests/contracts/delegation/delegation_service_test.py @@ -3,13 +3,11 @@ import pytest from skale.utils.web3_utils import check_receipt -from skale.dataclasses.delegation_status import DelegationStatus from skale.utils.account_tools import send_ether from skale.wallets.web3_wallet import generate_wallet from tests.constants import ( - D_VALIDATOR_NAME, D_VALIDATOR_DESC, D_VALIDATOR_FEE, D_VALIDATOR_MIN_DEL, D_VALIDATOR_ID, - D_DELEGATION_AMOUNT, D_DELEGATION_PERIOD, D_DELEGATION_INFO + D_VALIDATOR_NAME, D_VALIDATOR_DESC, D_VALIDATOR_FEE, D_VALIDATOR_MIN_DEL ) @@ -48,88 +46,6 @@ def test_register_new_validator(skale): assert n_of_validators_after == n_of_validators_before + 1 -def _get_number_of_pending_delegations(skale): - return len(_get_pending_delegations(skale)) - - -def _get_pending_delegations(skale): - return skale.delegation_service._get_delegation_ids_by_validator( - skale.wallet.address, - DelegationStatus.PROPOSED - ) - - -def test_delegate(skale): - num_of_delegations_before = _get_number_of_pending_delegations(skale) - tx_res = skale.delegation_service.delegate( - validator_id=D_VALIDATOR_ID, - amount=D_DELEGATION_AMOUNT, - delegation_period=D_DELEGATION_PERIOD, - info=D_DELEGATION_INFO, - wait_for=True - ) - check_receipt(tx_res.receipt) - num_of_delegations_after = _get_number_of_pending_delegations(skale) - assert num_of_delegations_after == num_of_delegations_before + 1 - - pending_delegations = skale.delegation_service.get_all_delegations_by_validator( - skale.wallet.address - ) - assert pending_delegations[-1]['info'] == D_DELEGATION_INFO - - -def test_get_delegations(skale): - delegations = skale.delegation_service.get_delegations( - skale.wallet.address, - DelegationStatus.PROPOSED, - 'validator' - ) - assert delegations[0]['status'] == 'PROPOSED' - assert delegations[0]['validator_id'] == D_VALIDATOR_ID - - -def test_get_all_delegations_by_holder(skale): - delegations = skale.delegation_service.get_all_delegations_by_holder( - skale.wallet.address - ) - assert all([delegation['address'] == skale.wallet.address for delegation in delegations]) - - -def test_get_all_delegations_by_validator(skale): - delegations = skale.delegation_service.get_all_delegations_by_validator( - skale.wallet.address - ) - assert all([delegation['validator_id'] == D_VALIDATOR_ID for delegation in delegations]) - - -def test_accept_pending_delegation(skale): - tx_res = skale.delegation_service.delegate( - validator_id=D_VALIDATOR_ID, - amount=D_DELEGATION_AMOUNT, - delegation_period=D_DELEGATION_PERIOD, - info=D_DELEGATION_INFO, - wait_for=True - ) - check_receipt(tx_res.receipt) - delegations = skale.delegation_service.get_delegations( - skale.wallet.address, - DelegationStatus.PROPOSED, - 'validator' - ) - delegation_id = delegations[-1]['id'] - tx_res = skale.delegation_service.accept_pending_delegation( - delegation_id, - wait_for=True - ) - check_receipt(tx_res.receipt) - delegations = skale.delegation_service.get_delegations( - skale.wallet.address, - DelegationStatus.ACCEPTED, - 'validator' - ) - assert delegations[-1]['id'] == delegation_id - - def test_link_node_address(skale): wallet = generate_wallet(skale.web3) addresses = skale.validator_service.get_linked_addresses_by_validator_address( @@ -171,62 +87,3 @@ def test_unlink_node_address(skale): skale.wallet.address ) assert wallet.address not in addresses - - -def test_cancel_pending_delegation(skale): - tx_res = skale.delegation_service.delegate( - validator_id=D_VALIDATOR_ID, - amount=D_DELEGATION_AMOUNT, - delegation_period=D_DELEGATION_PERIOD, - info=D_DELEGATION_INFO, - wait_for=True - ) - check_receipt(tx_res.receipt) - delegations = skale.delegation_service.get_delegations( - skale.wallet.address, - DelegationStatus.PROPOSED, - 'validator' - ) - delegation_id = delegations[-1]['id'] - tx_res = skale.delegation_service.cancel_pending_delegation( - delegation_id, - wait_for=True - ) - check_receipt(tx_res.receipt) - delegations = skale.delegation_service.get_delegations( - skale.wallet.address, - DelegationStatus.COMPLETED, - 'validator' - ) - assert delegations[-1]['id'] == delegation_id - - -@pytest.mark.skip('Investigate: revert Message sender is invalid') -def test_get_delegated_amount(skale): # todo: fix test - delegated_amount = skale.delegation_service.get_delegated_amount( - validator_id=D_VALIDATOR_ID - ) - assert isinstance(delegated_amount, int) - - -def test_get_delegated_of(skale): # todo: improve test - delegated_amount = skale.delegation_service.get_delegated_of( - address=skale.wallet.address - ) - assert isinstance(delegated_amount, int) - - -def test_withdraw_bounty(skale): # todo: improve test - tx_res = skale.delegation_service.withdraw_bounty( - bounty_collection_address=skale.wallet.address, - amount=0, - wait_for=True - ) - check_receipt(tx_res.receipt) - - -def test_get_earned_bounty_amount(skale): # todo: improve test - earned_bounty_amount = skale.delegation_service.get_earned_bounty_amount( - address=skale.wallet.address - ) - assert isinstance(earned_bounty_amount, int) diff --git a/tests/contracts/delegation/distributor_test.py b/tests/contracts/delegation/distributor_test.py new file mode 100644 index 00000000..92d31d7c --- /dev/null +++ b/tests/contracts/delegation/distributor_test.py @@ -0,0 +1,36 @@ +""" Tests for contracts/delegation/distributor.py """ + +from tests.constants import D_VALIDATOR_ID + + +def test_get_earned_bounty_amount(skale): + res = skale.distributor.get_earned_bounty_amount( + D_VALIDATOR_ID + ) + assert res['earned'] == 0 + + +def test_get_earned_fee_amount(skale): + res = skale.distributor.get_earned_fee_amount( + skale.wallet.address + ) + assert res['earned'] == 0 + + +# todo: improve test +def test_withdraw_bounty(skale): + tx_res = skale.distributor.withdraw_bounty( + validator_id=D_VALIDATOR_ID, + to=skale.wallet.address, + wait_for=True + ) + assert tx_res.receipt['status'] == 1 + + +# todo: improve test +def test_withdraw_fee(skale): + tx_res = skale.distributor.withdraw_fee( + to=skale.wallet.address, + wait_for=True + ) + assert tx_res.receipt['status'] == 1 diff --git a/tests/contracts/delegation/token_state_test.py b/tests/contracts/delegation/token_state_test.py deleted file mode 100644 index 09a75f16..00000000 --- a/tests/contracts/delegation/token_state_test.py +++ /dev/null @@ -1,43 +0,0 @@ -""" Tests for contracts/delegation/token_state.py """ - -from skale.utils.web3_utils import check_receipt -from skale.dataclasses.delegation_status import DelegationStatus - -from tests.constants import ( - D_VALIDATOR_ID, D_DELEGATION_AMOUNT, D_DELEGATION_PERIOD, D_DELEGATION_INFO -) - - -def test_skip_transition_delay(skale): - tx_res = skale.delegation_service.delegate( - validator_id=D_VALIDATOR_ID, - amount=D_DELEGATION_AMOUNT, - delegation_period=D_DELEGATION_PERIOD, - info=D_DELEGATION_INFO, - wait_for=True - ) - check_receipt(tx_res.receipt) - delegations = skale.delegation_service.get_delegations( - skale.wallet.address, - DelegationStatus.PROPOSED, - 'validator' - ) - delegation_id = delegations[-1]['id'] - tx_res = skale.delegation_service.accept_pending_delegation( - delegation_id, - wait_for=True - ) - check_receipt(tx_res.receipt) - - tx_res = skale.token_state._skip_transition_delay( - delegation_id=delegation_id, - wait_for=True - ) - check_receipt(tx_res.receipt) - - delegations = skale.delegation_service.get_delegations( - skale.wallet.address, - DelegationStatus.DELEGATED, - 'validator' - ) - assert delegations[-1]['id'] == delegation_id diff --git a/tests/main_test.py b/tests/main_test.py index ba7c4552..8296d27e 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -11,6 +11,7 @@ from skale.contracts.functionality.nodes import Nodes from skale.contracts_info import CONTRACTS_INFO from tests.constants import TEST_CONTRACT_NAME, ENDPOINT, TEST_ABI_FILEPATH, ETH_PRIVATE_KEY +from tests.utils import skip_evm_time def test_lib_init(): @@ -57,3 +58,10 @@ def test_get_attr(skale): skale_py_nodes_contract = skale.nodes assert issubclass(type(skale_py_nodes_contract), BaseContract) assert isinstance(skale_py_nodes_contract, Nodes) + + +def test_skip_evm_time(skale): + seconds = 10 + old_time = skip_evm_time(skale.web3, 0) + new_time = skip_evm_time(skale.web3, seconds) + assert new_time == old_time + seconds diff --git a/tests/prepare_data.py b/tests/prepare_data.py index d2169579..22592b9c 100644 --- a/tests/prepare_data.py +++ b/tests/prepare_data.py @@ -10,9 +10,9 @@ from tests.constants import ( DEFAULT_SCHAIN_NAME, DEFAULT_NODE_NAME, ENDPOINT, SECOND_NODE_NAME, TEST_ABI_FILEPATH, D_VALIDATOR_ID, ETH_PRIVATE_KEY, D_VALIDATOR_NAME, D_VALIDATOR_DESC, D_VALIDATOR_FEE, - D_VALIDATOR_MIN_DEL, D_DELEGATION_PERIOD, D_DELEGATION_INFO + D_VALIDATOR_MIN_DEL, D_DELEGATION_PERIOD, D_DELEGATION_INFO, MONTH_IN_SECONDS ) -from tests.utils import generate_random_node_data, generate_random_schain_data +from tests.utils import generate_random_node_data, generate_random_schain_data, skip_evm_time def cleanup_nodes_schains(skale): @@ -37,12 +37,13 @@ def setup_validator(skale): if not validator_exist(skale): create_validator(skale) enable_validator(skale) - delegation_id = len(skale.delegation_service.get_all_delegations_by_validator( - skale.wallet.address)) + else: + print('Skipping default validator creation') + delegation_id = skale.delegation_controller._get_delegation_ids_len_by_validator(D_VALIDATOR_ID) set_test_msr(skale) delegate_to_validator(skale) accept_pending_delegation(skale, delegation_id) - skip_delegation_delay(skale, delegation_id) + skip_evm_time(skale.web3, MONTH_IN_SECONDS) def link_address_to_validator(skale): @@ -65,7 +66,7 @@ def skip_delegation_delay(skale, delegation_id): def accept_pending_delegation(skale, delegation_id): print(f'Accepting delegation with ID: {delegation_id}') - tx_res = skale.delegation_service.accept_pending_delegation( + tx_res = skale.delegation_controller.accept_pending_delegation( delegation_id=delegation_id, wait_for=True ) @@ -86,7 +87,7 @@ def set_test_msr(skale): def delegate_to_validator(skale): print(f'Delegating tokens to validator ID: {D_VALIDATOR_ID}') - tx_res = skale.delegation_service.delegate( + tx_res = skale.delegation_controller.delegate( validator_id=D_VALIDATOR_ID, amount=get_test_delegation_amount(skale), delegation_period=D_DELEGATION_PERIOD, diff --git a/tests/utils.py b/tests/utils.py index 6aca5608..64e7577a 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -42,3 +42,9 @@ def response_mock(status_code=0, json_data=None, cookies=None, def request_mock(response_mock): request_mock = Mock(return_value=response_mock) return request_mock + + +def skip_evm_time(web3, seconds) -> int: + res = web3.provider.make_request("evm_increaseTime", [seconds]) + web3.provider.make_request("evm_mine", []) + return res['result'] From db7bb3a01c8c704605f5db8d301dc2230df83ff4 Mon Sep 17 00:00:00 2001 From: Dmytro Tkachuk Date: Mon, 2 Mar 2020 17:25:07 +0200 Subject: [PATCH 2/3] SKALE-2261 Move contracts provision methods to the separate module --- skale/utils/contracts_provision/__init__.py | 38 +++++ skale/utils/contracts_provision/main.py | 151 ++++++++++++++++++ skale/utils/contracts_provision/utils.py | 44 +++++ .../delegation/delegation_controller_test.py | 8 +- tests/contracts/manager_test.py | 4 +- tests/main_test.py | 6 +- tests/prepare_data.py | 137 +--------------- tests/utils.py | 34 +--- 8 files changed, 247 insertions(+), 175 deletions(-) create mode 100644 skale/utils/contracts_provision/__init__.py create mode 100644 skale/utils/contracts_provision/main.py create mode 100644 skale/utils/contracts_provision/utils.py diff --git a/skale/utils/contracts_provision/__init__.py b/skale/utils/contracts_provision/__init__.py new file mode 100644 index 00000000..8ef0a8e9 --- /dev/null +++ b/skale/utils/contracts_provision/__init__.py @@ -0,0 +1,38 @@ +# -*- 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 . + +DEFAULT_NODE_NAME = 'test_node' +SECOND_NODE_NAME = 'test_node_2' + +DEFAULT_SCHAIN_NAME = 'test_schain' + +D_VALIDATOR_ID = 1 +D_VALIDATOR_NAME = 'test' +D_VALIDATOR_DESC = 'test' +D_VALIDATOR_FEE = 10 +D_VALIDATOR_MIN_DEL = 1000 + +D_DELEGATION_ID = 0 +D_DELEGATION_AMOUNT = 55000000 +D_DELEGATION_PERIOD = 3 +D_DELEGATION_INFO = 'test' + +NOT_EXISTING_ID = 123123 + +MONTH_IN_SECONDS = (60 * 60 * 24 * 31) + 100 diff --git a/skale/utils/contracts_provision/main.py b/skale/utils/contracts_provision/main.py new file mode 100644 index 00000000..aaa33d3a --- /dev/null +++ b/skale/utils/contracts_provision/main.py @@ -0,0 +1,151 @@ +# -*- 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.contracts_provision import ( + D_VALIDATOR_ID, MONTH_IN_SECONDS, D_VALIDATOR_MIN_DEL, D_DELEGATION_PERIOD, D_DELEGATION_INFO, + D_VALIDATOR_NAME, D_VALIDATOR_DESC, D_VALIDATOR_FEE, DEFAULT_NODE_NAME, SECOND_NODE_NAME, + DEFAULT_SCHAIN_NAME +) +from skale.utils.contracts_provision.utils import ( + generate_random_node_data, generate_random_schain_data +) + + +def _skip_evm_time(web3, seconds) -> int: + """For test purposes only, works only with ganache node""" + res = web3.provider.make_request("evm_increaseTime", [seconds]) + web3.provider.make_request("evm_mine", []) + return res['result'] + + +def cleanup_nodes_schains(skale): + print('Cleanup nodes and schains') + for schain_id in skale.schains_data.get_all_schains_ids(): + schain_data = skale.schains_data.get(schain_id) + schain_name = schain_data.get('name', None) + if schain_name is not None: + skale.manager.delete_schain(schain_name, wait_for=True) + for node_id in skale.nodes_data.get_active_node_ids(): + skale.manager.deregister(node_id, wait_for=True) + + +def validator_exist(skale): + return skale.validator_service.number_of_validators() > 0 + + +def setup_validator(skale): + """Create and activate a validator""" + if not validator_exist(skale): + create_validator(skale) + enable_validator(skale) + else: + print('Skipping default validator creation') + delegation_id = skale.delegation_controller._get_delegation_ids_len_by_validator(D_VALIDATOR_ID) + set_test_msr(skale) + delegate_to_validator(skale) + accept_pending_delegation(skale, delegation_id) + _skip_evm_time(skale.web3, MONTH_IN_SECONDS) + + +def link_address_to_validator(skale): + print('Linking address to validator') + skale.delegation_service.link_node_address( + node_address=skale.wallet.address, + wait_for=True + ) + + +def skip_delegation_delay(skale, delegation_id): + print(f'Activating delegation with ID {delegation_id}') + skale.token_state._skip_transition_delay( + delegation_id, + wait_for=True + ) + + +def accept_pending_delegation(skale, delegation_id): + print(f'Accepting delegation with ID: {delegation_id}') + skale.delegation_controller.accept_pending_delegation( + delegation_id=delegation_id, + wait_for=True + ) + + +def get_test_delegation_amount(skale): + msr = skale.constants_holder.msr() + return msr * 10 + + +def set_test_msr(skale): + skale.constants_holder._set_msr( + new_msr=D_VALIDATOR_MIN_DEL, + wait_for=True + ) + + +def delegate_to_validator(skale): + print(f'Delegating tokens to validator ID: {D_VALIDATOR_ID}') + skale.delegation_controller.delegate( + validator_id=D_VALIDATOR_ID, + amount=get_test_delegation_amount(skale), + delegation_period=D_DELEGATION_PERIOD, + info=D_DELEGATION_INFO, + wait_for=True + ) + + +def enable_validator(skale): + print(f'Enabling validator ID: {D_VALIDATOR_ID}') + skale.validator_service._enable_validator(D_VALIDATOR_ID, wait_for=True) + + +def create_validator(skale): + print('Creating default validator') + skale.delegation_service.register_validator( + name=D_VALIDATOR_NAME, + description=D_VALIDATOR_DESC, + fee_rate=D_VALIDATOR_FEE, + min_delegation_amount=D_VALIDATOR_MIN_DEL, + wait_for=True + ) + + +def create_nodes(skale): + # create couple of nodes + print('Creating two nodes') + node_names = [DEFAULT_NODE_NAME, SECOND_NODE_NAME] + for name in node_names: + ip, public_ip, port, _ = generate_random_node_data() + skale.manager.create_node(ip, port, name, public_ip, wait_for=True) + + +def create_schain(skale): + print('Creating schain') + # create 1 s-chain + type_of_nodes, lifetime_seconds, _ = generate_random_schain_data() + price_in_wei = skale.schains.get_schain_price(type_of_nodes, + lifetime_seconds) + + skale.manager.create_schain( + lifetime_seconds, + type_of_nodes, + price_in_wei, + DEFAULT_SCHAIN_NAME, + wait_for=True + ) diff --git a/skale/utils/contracts_provision/utils.py b/skale/utils/contracts_provision/utils.py new file mode 100644 index 00000000..6b83c8e4 --- /dev/null +++ b/skale/utils/contracts_provision/utils.py @@ -0,0 +1,44 @@ +# -*- 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 . + +import random +import string + + +def generate_random_ip(): + return '.'.join('%s' % random.randint(0, 255) for i in range(4)) + + +def generate_random_name(len=8): + return ''.join(random.choices(string.ascii_uppercase + string.digits, k=len)) + + +def generate_random_port(): + return random.randint(0, 60000) + + +def generate_random_node_data(): + return generate_random_ip(), generate_random_ip(), generate_random_port(), \ + generate_random_name() + + +def generate_random_schain_data(): + lifetime_seconds = 3600 # 1 hour + type_of_nodes = 4 + return type_of_nodes, lifetime_seconds, generate_random_name() diff --git a/tests/contracts/delegation/delegation_controller_test.py b/tests/contracts/delegation/delegation_controller_test.py index 89da0bb9..574bf2ba 100644 --- a/tests/contracts/delegation/delegation_controller_test.py +++ b/tests/contracts/delegation/delegation_controller_test.py @@ -6,7 +6,7 @@ MONTH_IN_SECONDS) from skale.contracts.delegation.delegation_controller import FIELDS -from tests.utils import skip_evm_time +from skale.utils.contracts_provision.main import _skip_evm_time def _get_number_of_delegations(skale): @@ -91,7 +91,7 @@ def test_accept_pending_delegation(skale): ) assert delegations[-1]['id'] == delegation_id assert delegations[-1]['status'] == 'ACCEPTED' - skip_evm_time(skale.web3, MONTH_IN_SECONDS) + _skip_evm_time(skale.web3, MONTH_IN_SECONDS) def test_cancel_pending_delegation(skale): @@ -116,7 +116,7 @@ def test_cancel_pending_delegation(skale): ) assert delegations[-1]['id'] == delegation_id assert delegations[-1]['status'] == 'CANCELED' - skip_evm_time(skale.web3, MONTH_IN_SECONDS) + _skip_evm_time(skale.web3, MONTH_IN_SECONDS) def _delegate_and_activate(skale): @@ -134,7 +134,7 @@ def _delegate_and_activate(skale): delegation_ids[-1], wait_for=True ) - skip_evm_time(skale.web3, MONTH_IN_SECONDS) + _skip_evm_time(skale.web3, MONTH_IN_SECONDS) def test_get_delegated_to_validator_now(skale): diff --git a/tests/contracts/manager_test.py b/tests/contracts/manager_test.py index 5c83a5b4..eb016d9e 100644 --- a/tests/contracts/manager_test.py +++ b/tests/contracts/manager_test.py @@ -9,7 +9,9 @@ from skale.utils.constants import GAS from skale.utils.web3_utils import (private_key_to_public, TransactionFailedError) -from tests.utils import generate_random_node_data, generate_random_schain_data +from skale.utils.contracts_provision.main import ( + generate_random_node_data, generate_random_schain_data +) def test_create_node_data_to_bytes(skale): diff --git a/tests/main_test.py b/tests/main_test.py index 8296d27e..ced7fb40 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -11,7 +11,7 @@ from skale.contracts.functionality.nodes import Nodes from skale.contracts_info import CONTRACTS_INFO from tests.constants import TEST_CONTRACT_NAME, ENDPOINT, TEST_ABI_FILEPATH, ETH_PRIVATE_KEY -from tests.utils import skip_evm_time +from skale.utils.contracts_provision.main import _skip_evm_time def test_lib_init(): @@ -62,6 +62,6 @@ def test_get_attr(skale): def test_skip_evm_time(skale): seconds = 10 - old_time = skip_evm_time(skale.web3, 0) - new_time = skip_evm_time(skale.web3, seconds) + old_time = _skip_evm_time(skale.web3, 0) + new_time = _skip_evm_time(skale.web3, seconds) assert new_time == old_time + seconds diff --git a/tests/prepare_data.py b/tests/prepare_data.py index 22592b9c..0fc2adef 100644 --- a/tests/prepare_data.py +++ b/tests/prepare_data.py @@ -6,141 +6,10 @@ from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3 from skale.utils.helper import init_default_logger -from skale.utils.web3_utils import check_receipt -from tests.constants import ( - DEFAULT_SCHAIN_NAME, DEFAULT_NODE_NAME, ENDPOINT, SECOND_NODE_NAME, TEST_ABI_FILEPATH, - D_VALIDATOR_ID, ETH_PRIVATE_KEY, D_VALIDATOR_NAME, D_VALIDATOR_DESC, D_VALIDATOR_FEE, - D_VALIDATOR_MIN_DEL, D_DELEGATION_PERIOD, D_DELEGATION_INFO, MONTH_IN_SECONDS +from skale.utils.contracts_provision.main import ( + cleanup_nodes_schains, setup_validator, create_nodes, create_schain ) -from tests.utils import generate_random_node_data, generate_random_schain_data, skip_evm_time - - -def cleanup_nodes_schains(skale): - print('Cleanup nodes and schains') - for schain_id in skale.schains_data.get_all_schains_ids(): - schain_data = skale.schains_data.get(schain_id) - schain_name = schain_data.get('name', None) - if schain_name is not None: - tx_res = skale.manager.delete_schain(schain_name, wait_for=True) - check_receipt(tx_res.receipt) - for node_id in skale.nodes_data.get_active_node_ids(): - tx_res = skale.manager.deregister(node_id, wait_for=True) - check_receipt(tx_res.receipt) - - -def validator_exist(skale): - return skale.validator_service.number_of_validators() > 0 - - -def setup_validator(skale): - """Create and activate a validator""" - if not validator_exist(skale): - create_validator(skale) - enable_validator(skale) - else: - print('Skipping default validator creation') - delegation_id = skale.delegation_controller._get_delegation_ids_len_by_validator(D_VALIDATOR_ID) - set_test_msr(skale) - delegate_to_validator(skale) - accept_pending_delegation(skale, delegation_id) - skip_evm_time(skale.web3, MONTH_IN_SECONDS) - - -def link_address_to_validator(skale): - print('Linking address to validator') - tx_res = skale.delegation_service.link_node_address( - node_address=skale.wallet.address, - wait_for=True - ) - check_receipt(tx_res.receipt) - - -def skip_delegation_delay(skale, delegation_id): - print(f'Activating delegation with ID {delegation_id}') - tx_res = skale.token_state._skip_transition_delay( - delegation_id, - wait_for=True - ) - check_receipt(tx_res.receipt) - - -def accept_pending_delegation(skale, delegation_id): - print(f'Accepting delegation with ID: {delegation_id}') - tx_res = skale.delegation_controller.accept_pending_delegation( - delegation_id=delegation_id, - wait_for=True - ) - check_receipt(tx_res.receipt) - - -def get_test_delegation_amount(skale): - msr = skale.constants_holder.msr() - return msr * 10 - - -def set_test_msr(skale): - skale.constants_holder._set_msr( - new_msr=D_VALIDATOR_MIN_DEL, - wait_for=True - ) - - -def delegate_to_validator(skale): - print(f'Delegating tokens to validator ID: {D_VALIDATOR_ID}') - tx_res = skale.delegation_controller.delegate( - validator_id=D_VALIDATOR_ID, - amount=get_test_delegation_amount(skale), - delegation_period=D_DELEGATION_PERIOD, - info=D_DELEGATION_INFO, - wait_for=True - ) - check_receipt(tx_res.receipt) - - -def enable_validator(skale): - print(f'Enabling validator ID: {D_VALIDATOR_ID}') - tx_res = skale.validator_service._enable_validator(D_VALIDATOR_ID, wait_for=True) - check_receipt(tx_res.receipt) - - -def create_validator(skale): - print('Creating default validator') - tx_res = skale.delegation_service.register_validator( - name=D_VALIDATOR_NAME, - description=D_VALIDATOR_DESC, - fee_rate=D_VALIDATOR_FEE, - min_delegation_amount=D_VALIDATOR_MIN_DEL, - wait_for=True - ) - check_receipt(tx_res.receipt) - - -def create_nodes(skale): - # create couple of nodes - print('Creating two nodes') - node_names = [DEFAULT_NODE_NAME, SECOND_NODE_NAME] - for name in node_names: - ip, public_ip, port, _ = generate_random_node_data() - tx_res = skale.manager.create_node(ip, port, name, public_ip, - wait_for=True) - check_receipt(tx_res.receipt) - - -def create_schain(skale): - print('Creating schain') - # create 1 s-chain - type_of_nodes, lifetime_seconds, _ = generate_random_schain_data() - price_in_wei = skale.schains.get_schain_price(type_of_nodes, - lifetime_seconds) - - tx_res = skale.manager.create_schain( - lifetime_seconds, - type_of_nodes, - price_in_wei, - DEFAULT_SCHAIN_NAME, - wait_for=True - ) - check_receipt(tx_res.receipt) +from tests.constants import ENDPOINT, TEST_ABI_FILEPATH, ETH_PRIVATE_KEY @click.command() diff --git a/tests/utils.py b/tests/utils.py index 64e7577a..44aa0102 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,33 +1,8 @@ """ SKALE test utilities """ -import random -import string from mock import Mock, MagicMock -def generate_random_ip(): - return '.'.join('%s' % random.randint(0, 255) for i in range(4)) - - -def generate_random_name(len=8): - return ''.join(random.choices(string.ascii_uppercase + string.digits, k=len)) - - -def generate_random_port(): - return random.randint(0, 60000) - - -def generate_random_node_data(): - return generate_random_ip(), generate_random_ip(), generate_random_port(), \ - generate_random_name() - - -def generate_random_schain_data(): - lifetime_seconds = 3600 # 1 hour - type_of_nodes = 4 - return type_of_nodes, lifetime_seconds, generate_random_name() - - def response_mock(status_code=0, json_data=None, cookies=None, headers=None, raw=None): result = MagicMock() @@ -40,11 +15,4 @@ def response_mock(status_code=0, json_data=None, cookies=None, def request_mock(response_mock): - request_mock = Mock(return_value=response_mock) - return request_mock - - -def skip_evm_time(web3, seconds) -> int: - res = web3.provider.make_request("evm_increaseTime", [seconds]) - web3.provider.make_request("evm_mine", []) - return res['result'] + return Mock(return_value=response_mock) From 42c63aa4698e4d7b390c8a80adcbfc08cffc71ac Mon Sep 17 00:00:00 2001 From: Dmytro Tkachuk Date: Mon, 2 Mar 2020 17:34:14 +0200 Subject: [PATCH 3/3] SKALE-2261 Remove unused constants --- skale/utils/contracts_provision/__init__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/skale/utils/contracts_provision/__init__.py b/skale/utils/contracts_provision/__init__.py index 8ef0a8e9..ee8f3695 100644 --- a/skale/utils/contracts_provision/__init__.py +++ b/skale/utils/contracts_provision/__init__.py @@ -28,11 +28,7 @@ D_VALIDATOR_FEE = 10 D_VALIDATOR_MIN_DEL = 1000 -D_DELEGATION_ID = 0 -D_DELEGATION_AMOUNT = 55000000 D_DELEGATION_PERIOD = 3 D_DELEGATION_INFO = 'test' -NOT_EXISTING_ID = 123123 - MONTH_IN_SECONDS = (60 * 60 * 24 * 31) + 100