diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..a43fb2ba --- /dev/null +++ b/.flake8 @@ -0,0 +1,3 @@ +[flake8] +max-line-length = 100 +exclude = .git,__pycache__,docs/source/conf.py,old,build,dist,venv,.venv,node_modules,helper-scripts diff --git a/.gitignore b/.gitignore index 3e068e8d..ddc974e6 100644 --- a/.gitignore +++ b/.gitignore @@ -14,18 +14,19 @@ wallets/* # ansible skale-nodes/ansible/my-inventory skale-nodes/ansible/inventory/ +skale-nodes/ansible/inventory* skale-nodes/ansible/files/base-key*.txt skale-nodes/ansible/files/dev* skale-nodes/ansible/files/authorized_keys skale-nodes/ansible/files/validator-id*.txt skale-nodes/ansible/terraform/do/hosts skale-nodes/ansible/terraform/aws/hosts* -skale-nodes/ansible/ansible.cfg skale-nodes/ansible/sgx/ansible.cfg skale-nodes/ansible/files/base-key.txt skale-nodes/ansible/files/validator-key.txt skale-nodes/ansible/files/validator-id.txt +skale-nodes/ansible/files/passive-id.txt skale-nodes/ansible/files/cert.pem skale-nodes/ansible/files/privkey.pem @@ -54,3 +55,4 @@ bare-metal/ansible/files/restart_vm* bare-metal/ansible/conf* skale-nodes/ansible/group_vars/all +skale-nodes/ansible/roles/base_provision/files/files/authorized_keys diff --git a/README.md b/README.md index 3473c379..05c7d5e6 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,20 @@ -# SKALE Node Provisoning +# SKALE and Fair Node Provisioning [![Discord](https://img.shields.io/discord/534485763354787851.svg)](https://discord.gg/vvUtWJB) -This repo will help deploy and register multiple SKALE nodes in the cloud automatically. +This repo will help deploy and register multiple SKALE and Fair nodes in the cloud automatically. NOTE: This is for QA and testing purposes only. +- [Fair Node Provisoning](#fair-node-provisoning) + - [Fair network creating](#fair-network-creating) + - [Setup Fair boot nodes](#1-prepare-inventory) + - [Prepare inventory](#2-setup-fair-boot-nodes) + - [Create schain](#3-create-schain) + - [Deploy Fair contracts](#4-deploy-fair-contracts) + - [Migrate Fair boot nodes](#5-migrate-fair-boot-nodes) + - [Setup Fair nodes](#6-setup-fair-nodes) + - [SKALE Node Provisoning](#skale-node-provisoning) - [Host requirements](#host-requirements) - [Supported providers](#supported-providers) @@ -21,6 +30,57 @@ NOTE: This is for QA and testing purposes only. - [Run main script without IMA deployment](#run-main-script-without-ima-deployment) - [Run skaled monitor](#run-skaled-monitor) + +# Fair Node Provisioning + +## Fair network creation + +### 1. Prepare inventory +1) Set `node_type=fair_boot` +2) Set `build_type=git` (to use Docker image versions specified in the corresponding branch of the +`skale-node` repository on GitHub), or `build_type=source` (to build from source). In the second +case, set the appropriate local paths to the required cloned repositories and set +`container_configs_dir` variable (usually it's `/root/skale-node`). +3) Don't forget to set all other necessary variables like `eth_private_key`, `endpoint`, etc. + +### 2. Setup Fair boot nodes +```bash +ansible-playbook -i inventory main.yaml +``` +The following playbooks are processed here: _deploy_contracts.yaml, sgx_sim.yaml, setup.yaml, +validator.yaml, signature.yaml, link_addresses.yaml, register.yaml_ + +### 3. Create schain +1) Set the schain name (it must match the name specified in the `fair_static_params.yaml` file for +the corresponding network in the relevant branch of the `skale-node` repository). For example, for +the **devnet**, the typical name is `fair-devnet1`. +2) Set the desired `chain_type` (for example, LARGE4 - for 4-nodes chain ) +3) Run the following playbook: +```bash +ansible-playbook -i inventory create_chain.yaml +``` +### 4. Deploy Fair contracts +1) Set `fair_tag` variable (Fair manager version) +2) Set `boot_endpoint` variable (endpoint of schain that was created before) +3) Run the following playbook: +```bash +ansible-playbook -i inventory deploy_fair_manager.yaml +``` +### 5. Migrate Fair boot nodes +1) Set `node_type=fair` +2) Run the following playbook: +```bash +ansible-playbook -i inventory fair_migrate.yaml +``` +### 6. Setup Fair nodes +1) Set `node_type=fair` +2) Run the following playbook: +```bash +ansible-playbook -i inventory main_fair.yaml +``` + +# SKALE Node Provisioning + ## Host requirements - Terraform >= 0.12 @@ -177,3 +237,4 @@ bash utils/generate_hosts.sh ```bash ansible-playbook -i inventory run_monitor.yaml ``` + diff --git a/bare-metal/README.md b/bare-metal/README.md index f69a309a..5fa2c5e8 100644 --- a/bare-metal/README.md +++ b/bare-metal/README.md @@ -40,7 +40,7 @@ When Vagrant provision is completed `hosts` file will be created in `bare-metal/ ansible-playbook -i inventory -v main.yaml ``` -Default `DISK_MOUNTPOINT` for VirtualBox VMs: `/dev/sdb` +Default `BLOCK_DEVICE` for VirtualBox VMs: `/dev/sdb` ## Destroy machines diff --git a/helper-scripts b/helper-scripts index c253fa60..2e26feb5 160000 --- a/helper-scripts +++ b/helper-scripts @@ -1 +1 @@ -Subproject commit c253fa60f1862753e0546dd9ade72b41e425cf99 +Subproject commit 2e26feb5b7ebaebfb332dd7215fdcba58d095546 diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..d823f4d6 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,4 @@ +line-length = 100 + +[format] +quote-style = "single" diff --git a/skale-nodes/ansible/ansible.cfg b/skale-nodes/ansible/ansible.cfg new file mode 100644 index 00000000..8a02561b --- /dev/null +++ b/skale-nodes/ansible/ansible.cfg @@ -0,0 +1,4 @@ +[defaults] +host_key_checking = False +stdout_callback = yaml +inventory = ./inventory diff --git a/skale-nodes/ansible/archive.yaml b/skale-nodes/ansible/archive.yaml index 224ec687..402ff764 100644 --- a/skale-nodes/ansible/archive.yaml +++ b/skale-nodes/ansible/archive.yaml @@ -4,7 +4,7 @@ roles: - role: sync tags: sync - when: env is defined and env == "dev" + when: build_type == "source" - role: skale_cli tags: cli diff --git a/skale-nodes/ansible/backup.yaml b/skale-nodes/ansible/backup.yaml deleted file mode 100644 index 5082e2fd..00000000 --- a/skale-nodes/ansible/backup.yaml +++ /dev/null @@ -1,2 +0,0 @@ -- import_playbook: backup_nodes.yaml -- import_playbook: backup_schains.yaml diff --git a/skale-nodes/ansible/backup_nodes.yaml b/skale-nodes/ansible/backup_nodes.yaml index 8c9ece62..8cca4105 100644 --- a/skale-nodes/ansible/backup_nodes.yaml +++ b/skale-nodes/ansible/backup_nodes.yaml @@ -1,6 +1,7 @@ -- name: Backup node +- name: Backup SKALE or FAIR nodes hosts: nodes - vars: - - ip_address: "{{ hostvars[inventory_hostname].ansible_host }}" + roles: - - node_backup + - role: node_backup + when: node_type is defined and node_type in ['skale', 'fair'] + tags: backup_node \ No newline at end of file diff --git a/skale-nodes/ansible/backup_schains.yaml b/skale-nodes/ansible/backup_schains.yaml index cc025384..73ad50b2 100644 --- a/skale-nodes/ansible/backup_schains.yaml +++ b/skale-nodes/ansible/backup_schains.yaml @@ -1,13 +1,23 @@ - name: Fetch schain nodes script hosts: localhost + connection: local + gather_facts: false serial: True tasks: + - name: Validate node_type + fail: + msg: > + The 'node_type' variable must be defined and set to 'skale' for sChain backup. + Current value: '{{ node_type | default('undefined') }}' + when: node_type is not defined or node_type != 'skale' + - name: Run fetch schain nodes script script: fetch_node_schains.py -u environment: ETH_PRIVATE_KEY: "{{ eth_private_key }}" ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" BASE_DIR: "files" args: executable: python3 @@ -31,7 +41,7 @@ node_schains: "{{ hostvars['localhost'].node_schains }}" - name: Make snapshot - include: tasks/schains_backup.yaml + include_tasks: tasks/schains_backup.yaml vars: schains: "{{ node_schains[ip_address] }}" when: ip_address in node_schains diff --git a/skale-nodes/ansible/cleanup_contracts.yaml b/skale-nodes/ansible/cleanup_contracts.yaml new file mode 100644 index 00000000..5c5de409 --- /dev/null +++ b/skale-nodes/ansible/cleanup_contracts.yaml @@ -0,0 +1,6 @@ +- name: Cleanup contracts from chains and nodes + hosts: 127.0.0.1 + connection: local + roles: + - role: cleanup_contracts + tags: cleanup_contracts \ No newline at end of file diff --git a/skale-nodes/ansible/cleanup_sgx.yaml b/skale-nodes/ansible/cleanup_sgx.yaml index 8a9d2958..ae5278ed 100644 --- a/skale-nodes/ansible/cleanup_sgx.yaml +++ b/skale-nodes/ansible/cleanup_sgx.yaml @@ -1,5 +1,5 @@ - name: Cleanup sgx - hosts: sgx + hosts: sgx,nodes become: true roles: - name: Remove all sgx skale software from the machines diff --git a/skale-nodes/ansible/create_chain.yaml b/skale-nodes/ansible/create_chain.yaml new file mode 100644 index 00000000..f78b1a4d --- /dev/null +++ b/skale-nodes/ansible/create_chain.yaml @@ -0,0 +1,7 @@ +- name: Create chain on SKALE or Fair nodes + hosts: 127.0.0.1 + connection: local + roles: + - role: create_chain + tags: + - create_chain diff --git a/skale-nodes/ansible/delete_chain.yaml b/skale-nodes/ansible/delete_chain.yaml new file mode 100644 index 00000000..aa198074 --- /dev/null +++ b/skale-nodes/ansible/delete_chain.yaml @@ -0,0 +1,7 @@ +- name: Delete chain on SKALE or Fair nodes + hosts: 127.0.0.1 + connection: local + roles: + - role: delete_chain + tags: + - delete_chain diff --git a/skale-nodes/ansible/deploy_fair_manager.yaml b/skale-nodes/ansible/deploy_fair_manager.yaml new file mode 100644 index 00000000..50702def --- /dev/null +++ b/skale-nodes/ansible/deploy_fair_manager.yaml @@ -0,0 +1,14 @@ +- name: Deploy Fair manager contracts + hosts: 127.0.0.1 + connection: local + pre_tasks: + - name: Fail if node_type is not 'fair_boot' + fail: + msg: "Stopping playbook. This play requires node_type to be 'fair_boot', but it is '{{ node_type }}'." + when: node_type != "fair_boot" + roles: + - role: deploy_fair + tags: + - deploy_fair + + diff --git a/skale-nodes/ansible/fair_migrate.yaml b/skale-nodes/ansible/fair_migrate.yaml new file mode 100644 index 00000000..b9d98d29 --- /dev/null +++ b/skale-nodes/ansible/fair_migrate.yaml @@ -0,0 +1,19 @@ +- name: Migrate Fair boot node to regular Fair node + hosts: nodes + become: true + pre_tasks: + - name: Set node_type to fair for migration + set_fact: + node_type: "fair" + when: node_type is defined and node_type == 'fair_boot' + + roles: + - role: sync + when: build_type == "source" + tags: sync + + - role: config + tags: config + + - role: fair_migrate + tags: fair_migrate diff --git a/skale-nodes/ansible/fair_node.yaml b/skale-nodes/ansible/fair_node.yaml new file mode 100644 index 00000000..d2471746 --- /dev/null +++ b/skale-nodes/ansible/fair_node.yaml @@ -0,0 +1,4 @@ +- import_playbook: sgx_sim.yaml +- import_playbook: setup.yaml +- import_playbook: transfer_funds.yaml +- import_playbook: register.yaml diff --git a/skale-nodes/ansible/fair_node_passive.yaml b/skale-nodes/ansible/fair_node_passive.yaml new file mode 100644 index 00000000..0ac72dbb --- /dev/null +++ b/skale-nodes/ansible/fair_node_passive.yaml @@ -0,0 +1,2 @@ +- import_playbook: register_passive_fair.yaml +- import_playbook: setup.yaml diff --git a/skale-nodes/ansible/fair_pipeline.yaml b/skale-nodes/ansible/fair_pipeline.yaml new file mode 100644 index 00000000..93b9d02b --- /dev/null +++ b/skale-nodes/ansible/fair_pipeline.yaml @@ -0,0 +1,12 @@ +- import_playbook: set_fair_boot_node_type.yaml +- import_playbook: run_anvil.yaml +- import_playbook: deploy_contracts.yaml +- import_playbook: sgx_sim.yaml +- import_playbook: setup.yaml +- import_playbook: validator.yaml +- import_playbook: signature.yaml +- import_playbook: link_addresses.yaml +- import_playbook: register.yaml +- import_playbook: create_chain.yaml +- import_playbook: deploy_fair_manager.yaml +- import_playbook: fair_migrate.yaml \ No newline at end of file diff --git a/skale-nodes/ansible/files/cleanup_contracts.py b/skale-nodes/ansible/files/cleanup_contracts.py index e5c1541f..6df0cf9f 100644 --- a/skale-nodes/ansible/files/cleanup_contracts.py +++ b/skale-nodes/ansible/files/cleanup_contracts.py @@ -1,49 +1,71 @@ import logging import os +import sys +from eth_typing import HexStr -from skale import Skale +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.contracts_provision.main import cleanup_nodes logger = logging.getLogger(__name__) init_default_logger() -BASE_DIR = os.getenv('BASE_DIR') ENDPOINT = os.getenv('ENDPOINT') -ABI_FILEPATH = os.path.join(BASE_DIR, 'manager.json') +MANAGER_CONTRACTS = os.getenv('MANAGER_CONTRACTS') ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') -web3 = init_web3(ENDPOINT) -wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) -skale = Skale(ENDPOINT, ABI_FILEPATH, wallet) +def init_skale_manager( + endpoint: str, alias_or_address: str, eth_private_key: HexStr +) -> SkaleManager: + web3 = init_web3(endpoint) + wallet = Web3Wallet(eth_private_key, web3) + return SkaleManager(endpoint, alias_or_address, wallet) -def remove_active_nodes(): - for node_id in skale.nodes.get_active_node_ids(): - skale.manager.node_exit(node_id, wait_for=True) + +def remove_active_nodes(skale): + logger.info('Removing all active nodes...') + cleanup_nodes(skale) + logger.info('Finished removing active nodes') def get_all_schains_names(skale): schains_ids = skale.schains_internal.get_all_schains_ids() - print(schains_ids) - names = [ - skale.schains.get(sid).get('name') - for sid in schains_ids - ] + logger.info(f'Found chain IDs: {schains_ids}') + names = [skale.schains.get(sid).name for sid in schains_ids] return names -def remove_all_schains(): +def remove_all_schains(skale): + logger.info('Removing all chains...') schain_names = get_all_schains_names(skale) + if not schain_names: + logger.info('No chains found to remove') + return for name in schain_names: + logger.info(f'Deleting chain: {name}') skale.manager.delete_schain(name, wait_for=True) + logger.info('Finished removing chains') -def cleanup(): - remove_all_schains() - remove_active_nodes() +def cleanup(skale): + remove_all_schains(skale) + remove_active_nodes(skale) -if __name__ == "__main__": - cleanup() +if __name__ == '__main__': + skale = init_skale_manager(ENDPOINT, MANAGER_CONTRACTS, HexStr(ETH_PRIVATE_KEY)) + if len(sys.argv) > 1: + action = sys.argv[1] + if action == 'remove_chains': + remove_all_schains(skale) + elif action == 'remove_nodes': + remove_active_nodes(skale) + else: + logger.error(f'Unknown action: {action}. Please use "remove_chains" or "remove_nodes"') + sys.exit(1) + else: + logger.info('No action specified, running full cleanup') + cleanup(skale) diff --git a/skale-nodes/ansible/files/create_chain.py b/skale-nodes/ansible/files/create_chain.py new file mode 100644 index 00000000..783f4cb6 --- /dev/null +++ b/skale-nodes/ansible/files/create_chain.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# +# This file is part of node-provisoning +# +# Copyright (C) 2025-Present SKALE Labs +# +# This program 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 this program. If not, see . + +import os +from eth_typing import HexStr +from enum import Enum +from skale import SkaleManager +from skale.utils.web3_utils import init_web3 +from skale.wallets import Web3Wallet +from skale.utils.contracts_provision.main import add_test_permissions, create_schain +from skale.dataclasses.schain_options import get_default_schain_options + +CHAIN_NAME = os.environ['CHAIN_NAME'] +ENDPOINT = os.environ['ENDPOINT'] +ETH_PRIVATE_KEY = os.environ['ETH_PRIVATE_KEY'] +MANAGER_CONTRACTS = os.environ['MANAGER_CONTRACTS'] +CHAIN_TYPE = os.environ.get('CHAIN_TYPE', 'SMALL2').upper() +MIN_GAS_PRICE = 47619047620 +MAX_GAS_PRICE = 1000000000000000000 +EXTERNAL_GAS_DIFFICULTY = '0x0' + +class SchainType(Enum): + SMALL2 = [1, 2] + SMALL4 = [1, 4] + SMALL = [1, 16] + MEDIUM2 = [16, 2] + MEDIUM4 = [16, 4] + MEDIUM = [16, 16] + LARGE2 = [128, 2] + LARGE4 = [128, 4] + LARGE = [128, 16] + TEST0_4 = [0, 4] + TEST4_4 = [32, 4] + TEST4_2 = [32, 2] + TEST4 = [32, 16] + EMPTY = [0, 0] + + +def get_chain_type_params(chain_type: str) -> list: + try: + return SchainType[chain_type].value + except KeyError: + print(f"Error: '{chain_type}' is not a valid SchainType. " + f"Available types are: {[member.name for member in SchainType]}") + raise + + +def add_schain_type(part_of_node, number_of_nodes): + return skale.schains_internal.add_schain_type( + part_of_node, number_of_nodes + ) + + +def get_schain_type_id(skale, type_parameters): + n = skale.schains_internal.contract.functions.numberOfSchainTypes().call() + for idx in range(1, n + 1): + params = skale.schains_internal.get_schain_type(idx) + print(f'PARAMS: {params}') + if type_parameters == params: + return idx + return None + + +def prepare_and_create_chain(skale, chain_type=CHAIN_TYPE) -> None: + add_test_permissions(skale) + type_params = get_chain_type_params(chain_type) + type_id = get_schain_type_id(skale, type_params) + if type_id is None: + print(f'sChain type {chain_type} ' + f'with {type_params[0]}, {type_params[1]} not found. Adding to contracts...') + add_schain_type(type_params[0], type_params[1]) + type_id = get_schain_type_id(skale, type_params) + + schain_options = get_default_schain_options() + schain_options.min_gas_price = MIN_GAS_PRICE + schain_options.max_gas_price = MAX_GAS_PRICE + schain_options.external_gas_difficulty = HexStr(EXTERNAL_GAS_DIFFICULTY) + + create_schain( + skale, + schain_name=CHAIN_NAME, + schain_type=type_id, + schain_options=schain_options, + ) + + +def init_skale_manager( + endpoint: str, alias_or_address: str, eth_private_key: HexStr +) -> SkaleManager: + web3 = init_web3(endpoint) + wallet = Web3Wallet(eth_private_key, web3) + return SkaleManager(endpoint, alias_or_address, wallet) + + +if __name__ == '__main__': + skale = init_skale_manager( + ENDPOINT, MANAGER_CONTRACTS, HexStr(ETH_PRIVATE_KEY)) + prepare_and_create_chain(skale) diff --git a/skale-nodes/ansible/files/delete_chain.py b/skale-nodes/ansible/files/delete_chain.py new file mode 100644 index 00000000..3efb89b2 --- /dev/null +++ b/skale-nodes/ansible/files/delete_chain.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# +# This file is part of node-provisoning +# +# Copyright (C) 2025-Present SKALE Labs +# +# This program 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 this program. If not, see . + +import os +from eth_typing import HexStr +from skale import SkaleManager +from skale.utils.web3_utils import init_web3 +from skale.wallets import Web3Wallet + +CHAIN_NAME = os.environ['CHAIN_NAME'] +ENDPOINT = os.environ['ENDPOINT'] +ETH_PRIVATE_KEY = os.environ['ETH_PRIVATE_KEY'] +MANAGER_CONTRACTS = os.environ['MANAGER_CONTRACTS'] + + +def init_skale_manager( + endpoint: str, alias_or_address: str, eth_private_key: HexStr +) -> SkaleManager: + web3 = init_web3(endpoint) + wallet = Web3Wallet(eth_private_key, web3) + return SkaleManager(endpoint, alias_or_address, wallet) + + +if __name__ == '__main__': + skale = init_skale_manager(ENDPOINT, MANAGER_CONTRACTS, HexStr(ETH_PRIVATE_KEY)) + skale.manager.delete_schain_by_root(CHAIN_NAME, wait_for=True) + print(f'Schain {CHAIN_NAME} is deleted!') diff --git a/skale-nodes/ansible/files/fetch_node_schains.py b/skale-nodes/ansible/files/fetch_node_schains.py index 080c42ea..f43e6841 100644 --- a/skale-nodes/ansible/files/fetch_node_schains.py +++ b/skale-nodes/ansible/files/fetch_node_schains.py @@ -22,7 +22,7 @@ import logging import os -from skale import Skale +from skale import SkaleManager from skale.wallets import Web3Wallet from skale.utils.helper import ip_from_bytes from skale.utils.web3_utils import init_web3 @@ -31,23 +31,20 @@ BASE_DIR = os.getenv('BASE_DIR') ENDPOINT = os.getenv('ENDPOINT') -ABI_FILEPATH = os.path.join(BASE_DIR, 'manager.json') +MANAGER_CONTRACTS = os.getenv('MANAGER_CONTRACTS') ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') def dropped_irrelevant(node_data): - return { - 'name': node_data['name'], - 'ip': ip_from_bytes(node_data['ip']) - } + return {'name': node_data['name'], 'ip': ip_from_bytes(node_data['ip'])} def get_nodes_by_schain(skale, schain): node_ids = skale.schains_internal.get_node_ids_for_schain(schain) - return sorted([ - dropped_irrelevant(skale.nodes.get(nid)) - for nid in node_ids - ], key=lambda node: node['name']) + return sorted( + [dropped_irrelevant(skale.nodes.get(nid)) for nid in node_ids], + key=lambda node: node['name'], + ) def get_all_schains(skale): @@ -75,11 +72,10 @@ def get_schains_by_nodes(skale, schains, unique_nodes=False): def main(): web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - skale = Skale(ENDPOINT, ABI_FILEPATH, wallet) + skale = SkaleManager(ENDPOINT, MANAGER_CONTRACTS, wallet) parser = argparse.ArgumentParser( - prog='FetchSchainsNodes', - description='Fetch schains by node info from mainnet' + prog='FetchSchainsNodes', description='Fetch schains by node info from mainnet' ) parser.add_argument('-u', '--unique', action='store_true') @@ -87,11 +83,7 @@ def main(): schains = get_all_schains(skale) - schains_by_nodes = get_schains_by_nodes( - skale, - schains, - unique_nodes=args.unique - ) + schains_by_nodes = get_schains_by_nodes(skale, schains, unique_nodes=args.unique) print(json.dumps(schains_by_nodes, indent=4)) diff --git a/skale-nodes/ansible/files/fix_zero_node_fair.py b/skale-nodes/ansible/files/fix_zero_node_fair.py new file mode 100644 index 00000000..a2edbc14 --- /dev/null +++ b/skale-nodes/ansible/files/fix_zero_node_fair.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# +# This file is part of node-provisioning +# +# Copyright (C) 2025-Present SKALE Labs +# +# node-provisioning 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. +# +# node-provisioning 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 node-provisioning. If not, see . + +import os +import time +from eth_typing import HexStr +from skale import SkaleManager +from skale.utils.web3_utils import init_web3 +from skale.wallets import Web3Wallet +from skale.wallets.web3_wallet import generate_wallet +from skale.utils.contracts_provision.fair import ( + link_node_address, register_node, add_test_permissions, init_skale_from_wallet +) +from skale.utils.contracts_provision.main import ( + set_test_msr, create_validator, enable_validator, validator_exist +) +from skale.utils.account_tools import send_eth + +ETH_AMOUNT = 0.2 +ENDPOINT = os.environ['ENDPOINT'] +ETH_PRIVATE_KEY = os.environ['ETH_PRIVATE_KEY'] +MANAGER_CONTRACTS = os.environ['MANAGER_CONTRACTS'] +ALLOWED_TS_DIFF = int(os.getenv('ALLOWED_TS_DIFF')) + + +def init_skale_manager( + endpoint: str, alias_or_address: str, eth_private_key: HexStr +) -> SkaleManager: + web3 = init_web3(endpoint) + wallet = Web3Wallet(eth_private_key, web3) + return SkaleManager(endpoint, alias_or_address, wallet) + + +def setup_validator(skale: SkaleManager): + set_test_msr(skale, msr=0) + print('Address', skale.wallet.address) + if not validator_exist(skale): + create_validator(skale) + else: + print('Skipping default validator creation') + validator_id = skale.validator_service.validator_id_by_address(skale.wallet.address) + if not skale.validator_service.get(validator_id)['trusted']: + enable_validator(skale, validator_id) + + +def wait_for_next_block(web3): + current_block = web3.eth.block_number + print(f'Current block: {current_block}, waiting for next block...') + while web3.eth.block_number == current_block: + time.sleep(1) # Check every second + new_block = web3.eth.block_number + print(f'New block mined: {new_block}') + + +def fix_zero_node(skale): + wallet = generate_wallet(skale.web3) + print(f'Node Address: {wallet.address}') + if ALLOWED_TS_DIFF > 0: + wait_for_next_block(skale.web3) + + send_eth(skale.web3, skale.wallet, wallet.address, ETH_AMOUNT) + add_test_permissions(skale) + setup_validator(skale) + link_node_address(skale, wallet) + node_skale = init_skale_from_wallet(skale, wallet) + register_node(node_skale) + skale.nodes.init_exit(0) + skale.manager.node_exit(0) + + +if __name__ == '__main__': + skale = init_skale_manager(ENDPOINT, MANAGER_CONTRACTS, HexStr(ETH_PRIVATE_KEY)) + fix_zero_node(skale) diff --git a/skale-nodes/ansible/files/generate_ip.py b/skale-nodes/ansible/files/generate_ip.py new file mode 100644 index 00000000..f9f31251 --- /dev/null +++ b/skale-nodes/ansible/files/generate_ip.py @@ -0,0 +1,13 @@ +import ipaddress +import random + + +def generate_random_ip() -> ipaddress.IPv4Address: + random_int = random.randint(0, 2**32 - 1) + ip_object = ipaddress.IPv4Address(random_int) + return ip_object + + +if __name__ == '__main__': + random_ip_object = generate_random_ip() + print(random_ip_object) diff --git a/skale-nodes/ansible/files/link_address.py b/skale-nodes/ansible/files/link_address.py index 248ba6b6..b96c67e6 100644 --- a/skale-nodes/ansible/files/link_address.py +++ b/skale-nodes/ansible/files/link_address.py @@ -1,6 +1,6 @@ import os -from skale import Skale +from skale import SkaleManager from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3, to_checksum_address @@ -9,27 +9,26 @@ ENDPOINT = os.getenv('ENDPOINT') ADDRESS = os.getenv('ADDRESS').strip() SIGNATURE = os.getenv('SIGNATURE').strip() -ABI_FILEPATH = os.path.join(BASE_DIR, 'manager.json') +MANAGER_CONTRACTS = os.getenv('MANAGER_CONTRACTS') ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') def main(): web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - skale = Skale(ENDPOINT, ABI_FILEPATH, wallet) - print(ETH_PRIVATE_KEY) - print(ADDRESS) - print(SIGNATURE) + skale = SkaleManager(ENDPOINT, MANAGER_CONTRACTS, wallet) + print(f'PK: {ETH_PRIVATE_KEY}') + print(f'Node address: {ADDRESS}') + print(f'Signature: {SIGNATURE}') checksum_address = to_checksum_address(ADDRESS) + signature_bytes = web3.to_bytes(hexstr=SIGNATURE) validator_address = skale.wallet.address - linked = skale.validator_service.get_linked_addresses_by_validator_address( - validator_address - ) + linked = skale.validator_service.get_linked_addresses_by_validator_address(validator_address) if checksum_address not in linked: skale.validator_service.link_node_address( node_address=checksum_address, - signature=SIGNATURE, - gas_price=skale.web3.eth.gas_price * 2 + signature=signature_bytes, + gas_price=skale.web3.eth.gas_price * 2, ) diff --git a/skale-nodes/ansible/files/node-side-monitor.sh b/skale-nodes/ansible/files/node-side-monitor.sh index 0b8cbc86..8e6bcefe 100644 --- a/skale-nodes/ansible/files/node-side-monitor.sh +++ b/skale-nodes/ansible/files/node-side-monitor.sh @@ -48,7 +48,7 @@ make_grok_input () { cd .. local INPUT=" type: file - readall: false + readall: true fail_on_missing_logfile: false paths:" for I in ${NAMES[@]} @@ -58,6 +58,7 @@ make_grok_input () { echo "$INPUT" } + create_grok_yml () { INPUT="$INPUT" PORT=9144 PATTERNS="$PATTERNS" envsubst >grok-exporter.yml <<******************************************** global: @@ -73,7 +74,7 @@ input: ${INPUT} metrics: - type: gauge - name: logs_BLOCK_COMMIT + name: logs_BLOCK_COMMITED help: Block committed in bin-consensus match: '%{C_PREFIX_BLOCK}:BLOCK_COMMITED: PRPSR:%{NUMBER:proposer}:BID: %{NUMBER:block_id}' value: '{{.block_id}}' @@ -81,6 +82,15 @@ metrics: node_id: '{{.node_id}}' proposer: '{{.proposer}}' logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: counter + name: logs_PRPSR + help: Total number of proposals sent by each proposer + match: '%{C_PREFIX_BLOCK}:BLOCK_COMMITED: PRPSR:%{NUMBER:proposer}:BID: %{NUMBER:block_id}' + value: 1 + labels: + node_id: '{{.node_id}}' + proposer: '{{.proposer}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' - type: gauge name: logs_addBlockProposal help: Block proposal received @@ -107,9 +117,9 @@ metrics: node_id: '{{.node_id}}' logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' - type: gauge - name: logs_decided + name: logs_BLOCK_DECIDED help: 1 bin-cons ended OK - match: '%{C_PREFIX_BLOCK}:Decided value: %{NUMBER:value} for blockid:%{NUMBER:block_id} proposer:%{NUMBER:proposer}' + match: '%{C_PREFIX_BLOCK}:BLOCK_DECIDED: PRPSR:%{NUMBER:proposer}:BID: %{NUMBER:block_id}' value: '{{.block_id}}' labels: proposer: '{{.proposer}}' @@ -171,6 +181,111 @@ metrics: value: '1' labels: logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_CWT + help: Consensus Wait Time + match: '%{C_PREFIX_BLOCK}:CWT:%{NUMBER:cwt_value}' + value: '{{.cwt_value}}' + labels: + node_id: '{{.node_id}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_TLWT + help: Transaction Latency Wait Time + match: '%{C_PREFIX_BLOCK}:CWT:%{NUMBER:cwt_value}:TLWT:%{NUMBER:tlwt}' + value: '{{.tlwt}}' + labels: + node_id: '{{.node_id}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_SBPT + help: SBPT metric + match: '%{C_PREFIX_BLOCK}:CWT:%{NUMBER:cwt_value}:TLWT:%{NUMBER:tlwt}:SBPT:%{NUMBER:sbpt}' + value: '{{.sbpt}}' + labels: + node_id: '{{.node_id}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_BITE + help: BITE metric + match: '%{C_PREFIX_BLOCK}:CWT:%{NUMBER:cwt_value}:TLWT:%{NUMBER:tlwt}:SBPT:%{NUMBER:sbpt}:BITE_DECRYPTED_TXS:%{NUMBER:bite_decrypted_txs}' + value: '{{.bite_decrypted_txs}}' + labels: + node_id: '{{.node_id}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_BCT + help: Block Commit Time (ms) + match: '%{C_PREFIX_BLOCK}:BCT:%{NUMBER:bct}:BFST:%{NUMBER}:PST:%{NUMBER}' + value: '{{.bct}}' + labels: + node_id: '{{.node_id}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_BFST + help: Block Finalization Stage Time (ms) + match: '%{C_PREFIX_BLOCK}:BCT:%{NUMBER}:BFST:%{NUMBER:bfst}:PST:%{NUMBER}' + value: '{{.bfst}}' + labels: + node_id: '{{.node_id}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_PST + help: Proposal Stage Time (ms) + match: '%{C_PREFIX_BLOCK}:BCT:%{NUMBER}:BFST:%{NUMBER}:PST:%{NUMBER:pst}' + value: '{{.pst}}' + labels: + node_id: '{{.node_id}}' + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_SWT + help: Sync Wait Time + match: 'SWT:%{NUMBER:swt}:BFT:%{NUMBER}:TQBYTES:CTQ:%{NUMBER}:FTQ:%{NUMBER}:TQSIZE:CTQ:%{NUMBER}:FTQ:%{NUMBER}' + value: '{{.swt}}' + labels: + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_BFT + help: Block Finalization Time + match: 'SWT:%{NUMBER}:BFT:%{NUMBER:bft}:TQBYTES:CTQ:%{NUMBER}:FTQ:%{NUMBER}:TQSIZE:CTQ:%{NUMBER}:FTQ:%{NUMBER}' + value: '{{.bft}}' + labels: + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_TQBYTES_CTQ + help: Transaction Queue Bytes - CTQ Value + match: 'SWT:%{NUMBER}:BFT:%{NUMBER}:TQBYTES:CTQ:%{NUMBER:tqbytes_ctq}:FTQ:%{NUMBER}:TQSIZE:CTQ:%{NUMBER}:FTQ:%{NUMBER}' + value: '{{.tqbytes_ctq}}' + labels: + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_TQBYTES_FTQ + help: Transaction Queue Bytes - FTQ Value + match: 'SWT:%{NUMBER}:BFT:%{NUMBER}:TQBYTES:CTQ:%{NUMBER}:FTQ:%{NUMBER:tqbytes_ftq}:TQSIZE:CTQ:%{NUMBER}:FTQ:%{NUMBER}' + value: '{{.tqbytes_ftq}}' + labels: + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_TQSIZE_CTQ + help: Transaction Queue Size - CTQ Value + match: 'SWT:%{NUMBER}:BFT:%{NUMBER}:TQBYTES:CTQ:%{NUMBER}:FTQ:%{NUMBER}:TQSIZE:CTQ:%{NUMBER:tqsize_ctq}:FTQ:%{NUMBER}' + value: '{{.tqsize_ctq}}' + labels: + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_TQSIZE_FTQ + help: Transaction Queue Size - FTQ Value + match: 'SWT:%{NUMBER}:BFT:%{NUMBER}:TQBYTES:CTQ:%{NUMBER}:FTQ:%{NUMBER}:TQSIZE:CTQ:%{NUMBER}:FTQ:%{NUMBER:tqsize_ftq}' + value: '{{.tqsize_ftq}}' + labels: + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' +- type: gauge + name: logs_STET + help: STET - time of creating decryption shares for the block + match: 'STET:%{NUMBER:stet}' + value: '{{.stet}}' + labels: + logfile: '{{gsub .logfile ".*/log_links/(.+)/.*-json.log" "\\\\1"}}' server: port: ${PORT} ******************************************** @@ -195,4 +310,4 @@ do killall grok_exporter ./grok_exporter-*/grok_exporter -config grok-exporter.yml& fi -done +done \ No newline at end of file diff --git a/skale-nodes/ansible/files/prepare_base_wallet.py b/skale-nodes/ansible/files/prepare_base_wallet.py index ccc8dc1f..711a9a5e 100644 --- a/skale-nodes/ansible/files/prepare_base_wallet.py +++ b/skale-nodes/ansible/files/prepare_base_wallet.py @@ -20,7 +20,7 @@ import logging import os -from skale import Skale +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 @@ -31,29 +31,28 @@ BASE_DIR = os.getenv('BASE_DIR') ENDPOINT = os.getenv('ENDPOINT') -ABI_FILEPATH = os.path.join(BASE_DIR, 'manager.json') +MANAGER_CONTRACTS = os.getenv('MANAGER_CONTRACTS') ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') SKALE_AMOUNT = float(os.getenv('SKALE_AMOUNT')) ETH_AMOUNT = float(os.getenv('ETH_AMOUNT')) web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) -skale = Skale(ENDPOINT, ABI_FILEPATH, wallet) +skale = SkaleManager(ENDPOINT, MANAGER_CONTRACTS, wallet) def save_wallet_info(i, account): - filepath = os.path.join(BASE_DIR, f'wallet.txt') + filepath = os.path.join(BASE_DIR, 'wallet.txt') with open(filepath, 'w') as outfile: logger.info(f'Saving info to {filepath}') - outfile.write(account["private_key"]) + outfile.write(account['private_key']) def prepare_wallet(): - accounts = generate_accounts(skale, skale.wallet, 1, - SKALE_AMOUNT, ETH_AMOUNT, True) + accounts = generate_accounts(skale, skale.wallet, 1, SKALE_AMOUNT, ETH_AMOUNT, True) for i, account in enumerate(accounts): save_wallet_info(i, account) -if __name__ == "__main__": +if __name__ == '__main__': prepare_wallet() diff --git a/skale-nodes/ansible/files/register_passive_fair.py b/skale-nodes/ansible/files/register_passive_fair.py new file mode 100644 index 00000000..9b77e6a8 --- /dev/null +++ b/skale-nodes/ansible/files/register_passive_fair.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# +# This file is part of node-provisioning +# +# Copyright (C) 2025-Present SKALE Labs +# +# node-provisioning 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. +# +# node-provisioning 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 node-provisioning. If not, see . + +import codecs +import logging +import os + +from eth_keys import keys +from eth_typing import HexStr +from skale import FairManager +from skale.utils.helper import init_default_logger +from skale.utils.web3_utils import init_web3 +from skale.wallets import Web3Wallet + +logger = logging.getLogger(__name__) +init_default_logger() + +BASE_DIR = os.getenv('BASE_DIR') +ENDPOINT = os.getenv('ENDPOINT') +FAIR_CONTRACTS = os.getenv('FAIR_CONTRACTS') +ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') +PASSIVE_FAIR_IP = os.getenv('PASSIVE_FAIR_IP') +PASSIVE_FAIR_PORT = 10000 +PASSIVE_ID_FILEPATH = os.path.join(BASE_DIR, 'passive-id.txt') + + +def init_fair() -> FairManager: + web3 = init_web3(ENDPOINT) + wallet = Web3Wallet(HexStr(ETH_PRIVATE_KEY), web3) + return FairManager(ENDPOINT, FAIR_CONTRACTS, wallet) + + +if __name__ == '__main__': + fair = init_fair() + fair.nodes.register_passive(PASSIVE_FAIR_IP, PASSIVE_FAIR_PORT) + pk = ETH_PRIVATE_KEY + if pk and pk.startswith('0x'): + pk = pk[2:] + private_key_bytes = codecs.decode(pk, 'hex') + priv_key = keys.PrivateKey(private_key_bytes) + pub_key = priv_key.public_key + address = pub_key.to_checksum_address() + passive_ids = fair.nodes.get_passive_node_ids_for_address(address) + logger.info(f'All passive nodes for current address: {passive_ids}') + if len(passive_ids): + new_passive_node_id = passive_ids[-1] + logger.info(f'New passive node ID: {new_passive_node_id}') + with open(PASSIVE_ID_FILEPATH, 'w') as passive_id_file: + passive_id_file.write(str(new_passive_node_id)) diff --git a/skale-nodes/ansible/files/set_rng.py b/skale-nodes/ansible/files/set_rng.py new file mode 100644 index 00000000..190580cd --- /dev/null +++ b/skale-nodes/ansible/files/set_rng.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# +# This file is part of node-provisioning +# +# Copyright (C) 2025-Present SKALE Labs +# +# node-provisioning 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. +# +# node-provisioning 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 node-provisioning. If not, see . + +import os +from eth_typing import HexStr +from skale.utils.web3_utils import init_web3 +from skale.wallets import Web3Wallet +from skale import FairManager + + +ENDPOINT = os.getenv('ENDPOINT') +FAIR_CONTRACTS = os.getenv('FAIR_CONTRACTS') +ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') +RNG_ADDRESS = '0x0000000000000000000000000000000000000018' + + +def init_fair() -> FairManager: + web3 = init_web3(ENDPOINT) + wallet = Web3Wallet(HexStr(ETH_PRIVATE_KEY), web3) + return FairManager(ENDPOINT, FAIR_CONTRACTS, wallet) + + +if __name__ == '__main__': + fair = init_fair() + skale_rng = fair.committee.skale_rng() + fair.committee.set_rng(RNG_ADDRESS, skip_dry_run=True) diff --git a/skale-nodes/ansible/files/setup_validator.py b/skale-nodes/ansible/files/setup_validator.py index ac356b6f..6ff730bc 100644 --- a/skale-nodes/ansible/files/setup_validator.py +++ b/skale-nodes/ansible/files/setup_validator.py @@ -22,7 +22,7 @@ import random import string -from skale import Skale +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 @@ -34,7 +34,7 @@ BASE_DIR = os.getenv('BASE_DIR') ENDPOINT = os.getenv('ENDPOINT') -ABI_FILEPATH = os.path.join(BASE_DIR, 'manager.json') +MANAGER_CONTRACTS = os.getenv('MANAGER_CONTRACTS') ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') ETH_AMOUNT = float(os.getenv('ETH_AMOUNT')) MIN_DELEGATION_AMOUNT = int(os.getenv('MIN_DELEGATION_AMOUNT')) @@ -46,7 +46,7 @@ web3 = init_web3(ENDPOINT) wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) -skale = Skale(ENDPOINT, ABI_FILEPATH, wallet) +skale = SkaleManager(ENDPOINT, MANAGER_CONTRACTS, wallet) def create_base_account_for_validator(validator_web3) -> dict: @@ -55,10 +55,9 @@ def create_base_account_for_validator(validator_web3) -> dict: return account_data -def create_skale_for_validator(account_dict, validator_web3) -> Skale: - validator_skale = Skale( - ENDPOINT, ABI_FILEPATH, - Web3Wallet(account_dict['private_key'], validator_web3) +def create_skale_for_validator(account_dict, validator_web3) -> SkaleManager: + validator_skale = SkaleManager( + ENDPOINT, MANAGER_CONTRACTS, Web3Wallet(account_dict['private_key'], validator_web3) ) return validator_skale @@ -66,15 +65,14 @@ def create_skale_for_validator(account_dict, validator_web3) -> Skale: def create_validator(name): validator_web3 = init_web3(ENDPOINT) validator_base_account = create_base_account_for_validator(validator_web3) - validator_skale = create_skale_for_validator(validator_base_account, - validator_web3) + validator_skale = create_skale_for_validator(validator_base_account, validator_web3) tx_res = validator_skale.validator_service.register_validator( name=name, description=f'Validator for node {name}', fee_rate=COMMISSION_RATE, min_delegation_amount=MIN_DELEGATION_AMOUNT, - wait_for=True + wait_for=True, ) tx_res.raise_for_status() @@ -85,8 +83,7 @@ def create_validator(name): def whitelist_validator(validator_id): if not skale.validator_service._is_authorized_validator(validator_id): - tx_res = skale.validator_service._enable_validator(validator_id, - wait_for=True) + tx_res = skale.validator_service._enable_validator(validator_id, wait_for=True) tx_res.raise_for_status() @@ -99,10 +96,7 @@ def setup_validator(): vid, pkey = create_validator(name) whitelist_validator(vid) - skale.constants_holder._set_msr( - new_msr=0, - wait_for=True - ) + skale.constants_holder._set_msr(new_msr=0, wait_for=True) with open(BASE_KEY_FILEPATH, 'w') as pkey_file: pkey_file.write(pkey) with open(VALIDATOR_ID_FILEPATH, 'w') as vid_file: @@ -114,5 +108,5 @@ def main(): setup_validator() -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/skale-nodes/ansible/files/transfer_funds.py b/skale-nodes/ansible/files/transfer_funds.py index 80ffef4d..784d3341 100644 --- a/skale-nodes/ansible/files/transfer_funds.py +++ b/skale-nodes/ansible/files/transfer_funds.py @@ -19,8 +19,9 @@ import os import logging +import sys -from skale import Skale +from eth_typing import HexStr from skale.wallets import Web3Wallet from skale.utils.web3_utils import init_web3 from skale.utils.helper import init_default_logger @@ -30,26 +31,46 @@ BASE_DIR = os.getenv('BASE_DIR') ENDPOINT = os.getenv('ENDPOINT') -ABI_FILEPATH = os.path.join(BASE_DIR, 'manager.json') ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') ADDRESS = os.getenv('ADDRESS') AMOUNT = float(os.getenv('AMOUNT')) +TARGET_PRIVATE_KEY = os.getenv('TARGET_PRIVATE_KEY') +ALLOWED_TS_DIFF = int(os.getenv('ALLOWED_TS_DIFF', 300)) logger = logging.getLogger(__name__) init_default_logger() -def init_web3_skale(): +def main(): web3 = init_web3(ENDPOINT) - wallet = Web3Wallet(ETH_PRIVATE_KEY, web3) - return Skale(ENDPOINT, ABI_FILEPATH, wallet) + # If using anvil, disable the stale check middleware to prevent StaleBlockchain errors + if ALLOWED_TS_DIFF < 0: + if 'stalecheck' in web3.middleware_onion: + logger.info("Disabling stalecheck middleware for anvil.") + web3.middleware_onion.remove('stalecheck') + else: + logger.info("Stalecheck middleware not found, no action needed.") -def main(): - skale = init_web3_skale() - address = to_checksum_address(ADDRESS) - send_eth(skale.web3, skale.wallet, address, AMOUNT) + wallet = Web3Wallet(HexStr(ETH_PRIVATE_KEY), web3) + + target_address = None + if ADDRESS: + target_address = ADDRESS + elif TARGET_PRIVATE_KEY: + logger.info("ADDRESS not provided, deriving from TARGET_PRIVATE_KEY.") + target_wallet = Web3Wallet(HexStr(TARGET_PRIVATE_KEY), web3) + target_address = target_wallet.address + + if not target_address: + logger.critical("Error: Neither ADDRESS nor TARGET_PRIVATE_KEY environment variables were provided.") + sys.exit(1) + + checksum_address = to_checksum_address(target_address) + logger.info(f"Sending {AMOUNT} ETH to {checksum_address}...") + send_eth(web3, wallet, checksum_address, AMOUNT) + logger.info("Transfer successful.") -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/skale-nodes/ansible/files/whitelist_and_stake.py b/skale-nodes/ansible/files/whitelist_and_stake.py new file mode 100644 index 00000000..43e29a0c --- /dev/null +++ b/skale-nodes/ansible/files/whitelist_and_stake.py @@ -0,0 +1,74 @@ +import logging +import os +import sys + +from eth_typing import HexStr +from skale import FairManager +from skale.types.node import NodeId +from skale.utils.web3_utils import init_web3 +from skale.wallets import Web3Wallet + +ENDPOINT = os.getenv('ENDPOINT') +FAIR_CONTRACTS = os.getenv('FAIR_CONTRACTS') +ETH_PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY') +WEI_AMOUNT = int(os.getenv('WEI_AMOUNT')) + +logger = logging.getLogger(__name__) + + +def init_fair_manager() -> FairManager: + web3 = init_web3(ENDPOINT) + wallet = Web3Wallet(HexStr(ETH_PRIVATE_KEY), web3) + return FairManager(ENDPOINT, FAIR_CONTRACTS, wallet=wallet) + + +def process_node(fair_manager: FairManager, node_id: NodeId) -> list[str]: + node_errors = [] + try: + if fair_manager.status.is_whitelisted(node_id): + logger.info(f'Node {node_id} is already whitelisted. Skipping whitelisting.') + else: + fair_manager.status.whitelist_node(node_id) + logger.info(f'Node {node_id} was successfully whitelisted.') + except Exception as e: + error_msg = f'Could not whitelist node {node_id}: {e}' + node_errors.append(error_msg) + + try: + fair_manager.staking.stake(node_id, value=WEI_AMOUNT) + logger.info(f'Node {node_id} was successfully staked with {WEI_AMOUNT} Wei.') + except Exception as e: + error_msg = f'Could not stake node {node_id}: {e}' + node_errors.append(error_msg) + return node_errors + + +def main() -> None: + logging.basicConfig( + level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', stream=sys.stdout + ) + fair_manager = init_fair_manager() + try: + nodes_to_process = fair_manager.nodes.get_active_node_ids() + if not nodes_to_process: + logger.info('No active nodes found') + return + logger.info(f'Found active nodes: {nodes_to_process}') + except Exception as e: + sys.stderr.write(f"CRITICAL: Failed to get active node IDs: {e}\n") + sys.exit(1) + + errors = [] + for node_id in nodes_to_process: + node_errors = process_node(fair_manager, node_id) + if node_errors: + errors.extend(node_errors) + + if errors: + sys.stderr.write("Errors occurred during script execution:\n") + for err in errors: + sys.stderr.write(f"- {err}\n") + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/skale-nodes/ansible/inventory-template/dev b/skale-nodes/ansible/inventory-template/dev index b24e56fd..e74b0c52 100644 --- a/skale-nodes/ansible/inventory-template/dev +++ b/skale-nodes/ansible/inventory-template/dev @@ -1,56 +1,94 @@ [all:vars] ansible_ssh_user='root' ansible_python_interpreter=/usr/bin/python3 -env=test + +# build_type should be 'git' or 'source' +build_type=source + base_path=/root +container_configs_dir='/root/skale-node' + +# node_type should be be one of these - 'skale', 'fair_boot', 'fair' +node_type=skale + +bite=False +env_type=devnet +passive_node=False +snapshot=any + +anvil=True + +chain_name='' +chain_type='' + +node_version='' +sgx_version='' sgx_url='' +sgx_simulator=True +cleanup_sgx=True + block_device='' eth_private_key='' endpoint='' -ima_endpoint='' -db_user='' -db_password='' -db_root_password='' -db_port='' -docker_username='' -docker_password='' -filebeat_host='' +boot_endpoint='' + +###################################################################### +# Change this part with correct addresses after deployment if needed # +###################################################################### manager_contracts='' ima_contracts='' -container_configs_stream='' +fair_contracts='' +###################################################################### + +filebeat_host='' +influx_url='http://example.com' docker_lvmpy_stream='' -container_configs_dir='' -skale_cli_url='' -pem_cert_path='' tg_api_key='' tg_chat_id='' -monitoring_containers='' -base_domain_name='' -env_type='' -sgx_version='' -cert_mode='certbot/custom' +monitoring_containers=True +default_gas_price_wei='' +base_domain_name==skalenodes.com -## dev variables (skip if env=test) +cert_mode='certbot' + +skale_cli_url='' +fair_cli_url='' +######################################################################################### +# Change this part with your cloned repo filepaths (you can skip it if build_type=git) # +######################################################################################### skale_admin_path='' transaction_manager_path='' skale_node_path='' skale_node_cli_path='' +bounty_agent_path='' +skale_watchdog_path=' +######################################################################################### + +## contracts deployment + +manager_tag='' +fair_tag='' +ima_tag='' +deploy_gas_price='2000000000' # 2 gwei -# optional parameters +## optional parameters -email= -do_token= +email='' +do_token='' +docker_username='' +docker_password='' -## skale-node -disable_ima='' +## geth parameters -## contracts deployment +geth_image=ethereum/client-go:alltools-v1.13.11 +geth_password=12345 +etherbase="0x1aa5a64A25d58924a2A1059eE66Df835D6dB7Ce6" +geth_subnet="10.3.155.0/24" -manager_tag='' -deploy_gas_price='2000000000' # 2 gwei +## aws parameters aws_key='' aws_secret='' diff --git a/skale-nodes/ansible/nodes.yaml b/skale-nodes/ansible/nodes.yaml deleted file mode 100644 index e8108dc1..00000000 --- a/skale-nodes/ansible/nodes.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- import_playbook: upload_authorized_keys.yaml -- import_playbook: base.yaml -- import_playbook: setup.yaml -- import_playbook: validator.yaml -- import_playbook: signature.yaml -- import_playbook: link_addresses.yaml -- import_playbook: register.yaml -- import_playbook: ssl.yaml diff --git a/skale-nodes/ansible/register_passive_fair.yaml b/skale-nodes/ansible/register_passive_fair.yaml new file mode 100644 index 00000000..4912c8a5 --- /dev/null +++ b/skale-nodes/ansible/register_passive_fair.yaml @@ -0,0 +1,8 @@ +- name: Register passive FAIR node + hosts: 127.0.0.1 + connection: local + roles: + - role: register_passive_fair + tags: + - register_passive_fair + when: passive_node is defined and passive_node diff --git a/skale-nodes/ansible/requirements.txt b/skale-nodes/ansible/requirements.txt index 24bb1c27..14202f97 100644 --- a/skale-nodes/ansible/requirements.txt +++ b/skale-nodes/ansible/requirements.txt @@ -1,4 +1,3 @@ -ansible==4.2.0 -skale.py==5.1dev7 +ansible==11.3.0 +skale.py==7.11dev6 boto3==1.17.34 -eth-account==0.5.3 diff --git a/skale-nodes/ansible/restore.yaml b/skale-nodes/ansible/restore.yaml deleted file mode 100644 index cec96865..00000000 --- a/skale-nodes/ansible/restore.yaml +++ /dev/null @@ -1,7 +0,0 @@ -- import_playbook: restore_node.yaml - vars: - config_only: True - -- import_playbook: restore_schain.yaml - -- import_playbook: update.yaml diff --git a/skale-nodes/ansible/restore_node.yaml b/skale-nodes/ansible/restore_node.yaml index f6c6f2a3..ff565b8e 100644 --- a/skale-nodes/ansible/restore_node.yaml +++ b/skale-nodes/ansible/restore_node.yaml @@ -1,8 +1,7 @@ -- name: Restore node from backup tarball +- name: Restore SKALE or FAIR nodes from backup tarball hosts: nodes - vars: - - ip_address: "{{ hostvars[inventory_hostname].ansible_host }}" roles: - role: node_restore + when: node_type is defined and node_type in ['skale', 'fair'] tags: restore_node diff --git a/skale-nodes/ansible/restore_schain.yaml b/skale-nodes/ansible/restore_schain.yaml index 5ff01e1a..1a85bd7c 100644 --- a/skale-nodes/ansible/restore_schain.yaml +++ b/skale-nodes/ansible/restore_schain.yaml @@ -1,13 +1,23 @@ - name: Fetch schain nodes script hosts: localhost + connection: local + gather_facts: false serial: True tasks: - - name: Fetch nodes schains script + - name: Validate node_type + fail: + msg: > + The 'node_type' variable must be defined and set to 'skale' for sChain restore. + Current value: '{{ node_type | default('undefined') }}' + when: node_type is not defined or node_type != 'skale' + + - name: Run fetch schain nodes script script: fetch_node_schains.py environment: ETH_PRIVATE_KEY: "{{ eth_private_key }}" ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" BASE_DIR: "files" args: executable: python3 diff --git a/skale-nodes/ansible/roles/cleanup_artifacts/tasks/main.yaml b/skale-nodes/ansible/roles/cleanup_artifacts/tasks/main.yaml index 6a448e15..20abbbc2 100644 --- a/skale-nodes/ansible/roles/cleanup_artifacts/tasks/main.yaml +++ b/skale-nodes/ansible/roles/cleanup_artifacts/tasks/main.yaml @@ -4,37 +4,52 @@ path: "{{ playbook_dir}}/files/node-info/" tags: node_info_cleanup - -- name: Cleanup group_vars/all from contracts links +- name: Cleanup group_vars/all lineinfile: state: absent regexp: "{{ item }}" path: "{{ playbook_dir }}/group_vars/all" - loop: ["^sm_url", "^ima_url"] - tags: group_vars_cleanup - + loop: ["^manager_contracts", "^ima_contracts", "^fair_contracts", "^allowed_ts_diff", "^anvil_private_key", "^endpoint", "^node_type"] + tags: + - group_vars_cleanup + - contract_data_cleanup - name: Find all abis find: paths: ["{{ playbook_dir }}/../../helper-scripts/contracts_data"] patterns: ["*.json"] register: abi_files - + tags: contract_data_cleanup - name: Cleanup contract abis file: state: absent path: "{{ item.path }}" loop: "{{ abi_files.files }}" - + tags: contract_data_cleanup - name: Cleanup manager manifests file: state: absent path: "{{ playbook_dir }}/../../helper-scripts/contracts_data/openzeppelin" - + tags: contract_data_cleanup - name: Cleanup ima manifests file: state: absent path: "{{ playbook_dir }}/../../helper-scripts/contracts_data/ima-openzeppelin" + tags: contract_data_cleanup + +- name: Cleanup contracts data + file: + state: absent + path: "{{ playbook_dir }}/../../helper-scripts/contracts_data/.openzeppelin" + tags: contract_data_cleanup + +- name: Remove validator-id and validator-key files + file: + path: "{{ item }}" + state: absent + with_fileglob: + - "{{ playbook_dir}}/files/validator-*.txt" + tags: validator_data_cleanup \ No newline at end of file diff --git a/skale-nodes/ansible/roles/cleanup_contracts/tasks/main.yaml b/skale-nodes/ansible/roles/cleanup_contracts/tasks/main.yaml index f6a10441..e25cdfd4 100644 --- a/skale-nodes/ansible/roles/cleanup_contracts/tasks/main.yaml +++ b/skale-nodes/ansible/roles/cleanup_contracts/tasks/main.yaml @@ -1,12 +1,27 @@ -- name: Cleanup contracts - script: cleanup_contracts.py +- name: Cleanup contracts - remove all chains + script: + cmd: cleanup_contracts.py remove_chains run_once: yes environment: BASE_DIR: "files" ETH_PRIVATE_KEY: "{{ eth_private_key }}" ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" args: executable: python3 tags: - - cleanup - - cleanup_contracts + - cleanup_chains + +- name: Cleanup contracts - remove all active nodes + ansible.builtin.script: + cmd: cleanup_contracts.py remove_nodes + run_once: yes + environment: + BASE_DIR: "files" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" + args: + executable: python3 + tags: + - cleanup_nodes diff --git a/skale-nodes/ansible/roles/cleanup_nodes/tasks/change_ip.yaml b/skale-nodes/ansible/roles/cleanup_nodes/tasks/change_ip.yaml new file mode 100644 index 00000000..7d0178db --- /dev/null +++ b/skale-nodes/ansible/roles/cleanup_nodes/tasks/change_ip.yaml @@ -0,0 +1,21 @@ +- name: Generate random IP address + script: generate_ip.py + environment: + BASE_DIR: "files" + args: + executable: python3 + register: random_ip + changed_when: false + +- name: Show generated IP + debug: + msg: "{{ random_ip }}" + +- name: Change node IP + command: + cmd: "fair node change-ip {{ random_ip.stdout | trim }}" + register: change_ip_cmd + +- name: Show change-ip command output + debug: + msg: "{{ change_ip_cmd.stdout }}" diff --git a/skale-nodes/ansible/roles/cleanup_nodes/tasks/cli_cleanup.yaml b/skale-nodes/ansible/roles/cleanup_nodes/tasks/cli_cleanup.yaml new file mode 100644 index 00000000..89b47d22 --- /dev/null +++ b/skale-nodes/ansible/roles/cleanup_nodes/tasks/cli_cleanup.yaml @@ -0,0 +1,13 @@ +- name: Build and execute cleanup command + command: + cmd: "{{ command_prefixes[node_type] }} cleanup --yes" + vars: + command_prefixes: + fair: "{{ 'fair passive-node' if (passive_node | default(false) | bool) else 'fair node' }}" + skale: "{{ 'skale passive-node' if (passive_node | default(false) | bool) else 'skale node' }}" + when: node_type in command_prefixes + register: cleanup_cmd + +- name: Show cleanup command output + debug: + msg: "{{ cleanup_cmd.stdout }}" diff --git a/skale-nodes/ansible/roles/cleanup_nodes/tasks/containers.yaml b/skale-nodes/ansible/roles/cleanup_nodes/tasks/containers.yaml index dee99ef5..88836bc1 100644 --- a/skale-nodes/ansible/roles/cleanup_nodes/tasks/containers.yaml +++ b/skale-nodes/ansible/roles/cleanup_nodes/tasks/containers.yaml @@ -1,15 +1,13 @@ - name: Get monitoring container ids - command: 'docker ps -a -q --filter="name=monitoring_"' + command: 'docker ps -a -q --filter="name=monitor_"' become: true register: containers_output - - name: Split monitoring container ids output register: containers_output set_fact: monitoring_container_ids: "{{ containers_output.stdout.split('\n') }}" - - name: Destroy monitoring container ids become: true docker_container: @@ -19,29 +17,36 @@ keep_volumes: no with_items: "{{ monitoring_container_ids | default([]) }}" - - name: Get all container ids - command: 'docker ps -a -q --filter="name=skale_"' + command: 'docker ps -a -q --filter="name=sk_"' become: true register: containers_output tags: containers_ids - - name: Split containers ids output register: containers_output set_fact: skale_container_ids: "{{ containers_output.stdout.split('\n') }}" - -- name: Destroy admin container +- name: Destroy skale/fair admin container become: true docker_container: - name: "skale_admin" + name: "sk_admin" state: absent force_kill: yes keep_volumes: no tags: admin + when: node_type == "skale" or node_type == "fair" +- name: Destroy fair boot admin container + become: true + docker_container: + name: "sk_boot_admin" + state: absent + force_kill: yes + keep_volumes: no + tags: admin + when: node_type == "fair_boot" - name: Destroy all containers become: true @@ -52,11 +57,10 @@ keep_volumes: no with_items: "{{ skale_container_ids | default([]) }}" - - name: Prune docker command: cmd: "docker system prune -af" - + when: prune_docker is defined and prune_docker - name: Umount shared-space command: @@ -64,7 +68,6 @@ failed_when: False tags: umount - - name: Register /mnt folders find: paths: "/mnt/" @@ -73,7 +76,6 @@ tags: - mounts - - name: Cleanup /mnt dir file: path: "{{ item.path }}" @@ -82,7 +84,6 @@ tags: - mounts - - name: Remove all data-dir volumes lvg: vg: "schains" @@ -90,3 +91,19 @@ force: yes tags: - lvm_artifacts + +- name: Clean up anvil resources + delegate_to: "{{ groups['nodes'][0] }}" + run_once: true + when: anvil is defined and anvil + tags: stop_anvil + block: + - name: Stop and remove anvil container + docker_container: + name: anvil + state: absent + + - name: Remove anvil state directory + file: + path: /var/lib/anvil-state + state: absent diff --git a/skale-nodes/ansible/roles/cleanup_nodes/tasks/docker_lvmpy.yaml b/skale-nodes/ansible/roles/cleanup_nodes/tasks/docker_lvmpy.yaml index 548c09cd..fa9f4a14 100644 --- a/skale-nodes/ansible/roles/cleanup_nodes/tasks/docker_lvmpy.yaml +++ b/skale-nodes/ansible/roles/cleanup_nodes/tasks/docker_lvmpy.yaml @@ -1,7 +1,16 @@ +- name: Check if docker-lvmpy service exists + stat: + path: /etc/systemd/system/docker-lvmpy.service + register: docker_lvmpy_service + when: node_type == "skale" + - name: Disable docker-lvmpy systemd: state: stopped name: docker-lvmpy + when: + - node_type == "skale" + - docker_lvmpy_service.stat.exists - name: Remove docker-lvmpy artifacts file: @@ -12,3 +21,4 @@ - "/opt/docker-lvmpy" - "/etc/docker-lvmpy" - "/etc/systemd/system/docker-lvmpy.service" + when: node_type == "skale" diff --git a/skale-nodes/ansible/roles/cleanup_nodes/tasks/main.yaml b/skale-nodes/ansible/roles/cleanup_nodes/tasks/main.yaml index 5277d9e4..60f01129 100644 --- a/skale-nodes/ansible/roles/cleanup_nodes/tasks/main.yaml +++ b/skale-nodes/ansible/roles/cleanup_nodes/tasks/main.yaml @@ -1,3 +1,12 @@ +# - name: Change Fair node IP +# import_tasks: change_ip.yaml +# tags: change_ip +# when: node_type == "fair" + +- name: Cli cleanup command + import_tasks: cli_cleanup.yaml + tags: cli_cleanup + - name: Run container cleanup import_tasks: containers.yaml tags: container_cleanup diff --git a/skale-nodes/ansible/roles/cleanup_nodes/tasks/node_artifacts.yaml b/skale-nodes/ansible/roles/cleanup_nodes/tasks/node_artifacts.yaml index fa136f8d..35405096 100644 --- a/skale-nodes/ansible/roles/cleanup_nodes/tasks/node_artifacts.yaml +++ b/skale-nodes/ansible/roles/cleanup_nodes/tasks/node_artifacts.yaml @@ -7,6 +7,16 @@ - "{{ base_path }}/.skale" - "{{ base_path }}/init-env" +- name: Unmount schains directory + ansible.builtin.mount: + path: /var/lib/skale/schains + state: unmounted + +- name: Remove schains directory + file: + path: /var/lib/skale/schains + state: absent + - name: Remove node artifacts from /var and /etc file: path: "{{ item }}" @@ -24,4 +34,10 @@ ansible.builtin.iptables: chain: "{{ item }}" flush: yes - with_items: [ 'INPUT', 'FORWARD', 'OUTPUT' ] + with_items: ["INPUT", "FORWARD", "OUTPUT"] + +- name: Load firewall rules from configuration file + ansible.builtin.command: + cmd: "nft -f /etc/nftables.conf" + register: nft_load_result + tags: cleanup_firewall diff --git a/skale-nodes/ansible/roles/cleanup_sgx/tasks/main.yaml b/skale-nodes/ansible/roles/cleanup_sgx/tasks/main.yaml index 39d9818c..453aac83 100644 --- a/skale-nodes/ansible/roles/cleanup_sgx/tasks/main.yaml +++ b/skale-nodes/ansible/roles/cleanup_sgx/tasks/main.yaml @@ -8,10 +8,10 @@ tags: sgx when: sgx_simulator is not defined or not sgx_simulator -- name: Destroy sgx container +- name: Destroy sgx-sim container become: true docker_container: - name: "sgx_sim" + name: "sgx-sim" state: absent force_kill: yes keep_volumes: no diff --git a/skale-nodes/ansible/roles/config/tasks/main.yaml b/skale-nodes/ansible/roles/config/tasks/main.yaml index 931cfda4..345102b0 100644 --- a/skale-nodes/ansible/roles/config/tasks/main.yaml +++ b/skale-nodes/ansible/roles/config/tasks/main.yaml @@ -1,85 +1,95 @@ - # - name: Get block device from lvm-block-device file created by terraform - # shell: cat "{{ base_path }}/lvm-block-device" - # register: block_device - -- name: Set SM download URL - set_fact: - manager_contracts: "{{ sm_url }}" - when: manager_contracts is undefined - tags: contracts - -- name: Crash if no SM ABIs URL provided - fail: - msg: manager_contracts is undefined - when: manager_contracts is undefined - tags: contracts - -- name: Set IMA download URL +- name: Set IMA contract address set_fact: - ima_contracts: "{{ ima_url }}" + ima_contracts: "{{ hostvars['localhost']['ima_contracts'] }}" when: ima_contracts is undefined tags: contracts -- name: Crash if no IMA ABIs URL provided +- name: Crash if no IMA contract address provided fail: msg: ima_contracts is undefined when: ima_contracts is undefined tags: contracts -- name: Download contracts - get_url: - url: "{{ manager_contracts }}" - dest: "{{ base_path }}/manager.json" - mode: 0644 - force: true - tags: contracts +- name: Set env options for Fair boot node + set_fact: + env_options: | + MANAGER_CONTRACTS="{{ manager_contracts }}" + IMA_CONTRACTS="{{ ima_contracts }}" + NODE_VERSION="{{ node_version }}" + ENDPOINT="{{ endpoint }}" + CONTAINER_CONFIGS_DIR="{{ container_configs_dir if (build_type | default('')) == 'source' else ''}}" + BLOCK_DEVICE="{{ block_device }}" + SGX_URL="{{ sgx_url }}" + ENV_TYPE="{{ env_type }}" + FILEBEAT_HOST="{{ filebeat_host }}" + ENFORCE_BTRFS='False' + when: node_type == "fair_boot" + tags: env -- name: Set sgx url +- name: Set common env options for regular Fair node set_fact: - sgx_url: "https://{{ hostvars['sgx0'].ansible_host }}:1026" - when: sgx_url is not defined or sgx_url == '' + env_options: | + FAIR_CONTRACTS="{{ fair_contracts }}" + NODE_VERSION="{{ node_version }}" + BOOT_ENDPOINT="{{ boot_endpoint }}" + CONTAINER_CONFIGS_DIR="{{ container_configs_dir if (build_type | default('')) == 'source' else ''}}" + BLOCK_DEVICE="{{ block_device }}" + ENV_TYPE="{{ env_type }}" + FILEBEAT_HOST="{{ filebeat_host }}" + ENFORCE_BTRFS='False' + when: node_type == "fair" + tags: env -- name: Set env options +- name: Add SGX_URL to env options if not passive + set_fact: + env_options: "{{ env_options }}\nSGX_URL={{ sgx_url }}" + when: + - node_type == "fair" + - passive_node is not defined or not passive_node + tags: env + +- name: Set env options for regular SKALE node set_fact: env_options: | ENDPOINT="{{ endpoint }}" - IMA_ENDPOINT="{{ ima_endpoint }}" - CONTAINER_CONFIGS_STREAM="{{ container_configs_stream }}" + NODE_VERSION="{{ node_version }}" FILEBEAT_HOST="{{ filebeat_host }}" - MANAGER_CONTRACTS_ABI_URL="{{ manager_contracts }}" - IMA_CONTRACTS_ABI_URL="{{ ima_contracts }}" - CONTAINER_CONFIGS_DIR="{{ container_configs_dir }}" - DOCKER_LVMPY_STREAM="{{ docker_lvmpy_stream }}" - DISK_MOUNTPOINT="{{ block_device }}" - SGX_SERVER_URL="{{ sgx_url }}" + MANAGER_CONTRACTS="{{ manager_contracts }}" + IMA_CONTRACTS="{{ ima_contracts }}" + CONTAINER_CONFIGS_DIR="{{ container_configs_dir if (build_type | default('')) == 'source' else ''}}" + DOCKER_LVMPY_VERSION="{{ docker_lvmpy_version }}" + BLOCK_DEVICE="{{ block_device }}" + SGX_URL="{{ sgx_url }}" TG_API_KEY="{{ tg_api_key }}" TG_CHAT_ID="{{ tg_chat_id }}" MONITORING_CONTAINERS="{{ monitoring_containers }}" DEFAULT_GAS_PRICE_WEI="{{ default_gas_price_wei }}" ENV_TYPE="{{ env_type }}" - DISABLE_IMA="{{ disable_ima }}" INFLUX_URL="{{ influx_url }}" - TELEGRAF="{{ telegraf }}" - - when: sync_node is not defined or not sync_node + BITE="{{ bite }}" + when: + - node_type == "skale" + - (passive_node is not defined or not passive_node) tags: env -- name: Set env options sync node +- name: Set env options for SKALE sync node set_fact: env_options: | - CONTAINER_CONFIGS_STREAM="{{ container_configs_stream }}" + NODE_VERSION="{{ node_version }}" CONTAINER_CONFIGS_DIR="{{ container_configs_dir }}" ENDPOINT={{ endpoint }} ENFORCE_BTRFS='True' - DOCKER_LVMPY_STREAM="{{ docker_lvmpy_stream }}" ENV_TYPE="{{ env_type }}" - SCHAIN_NAME="{{ schain_name }}" - MANAGER_CONTRACTS_ABI_URL={{ manager_contracts }} - IMA_CONTRACTS_ABI_URL={{ ima_contracts }} - DISK_MOUNTPOINT={{ block_device }} - INFLUX_URL="{{ influx_url }}" - TELEGRAF="{{ telegraf }}" - when: sync_node is defined and sync_node + SCHAIN_NAME="{{ chain_name }}" + MANAGER_CONTRACTS={{ manager_contracts }} + IMA_CONTRACTS={{ ima_contracts }} + BLOCK_DEVICE={{ block_device }} + FILEBEAT_HOST="{{ filebeat_host }}" + BITE="{{ bite }}" + when: + - node_type == "skale" + - (passive_node is defined and passive_node) + tags: env - name: Show env debug: diff --git a/skale-nodes/ansible/roles/create_chain/tasks/main.yaml b/skale-nodes/ansible/roles/create_chain/tasks/main.yaml new file mode 100644 index 00000000..a46e1f84 --- /dev/null +++ b/skale-nodes/ansible/roles/create_chain/tasks/main.yaml @@ -0,0 +1,13 @@ +- name: Execute create_chain script + script: create_chain.py + environment: + BASE_DIR: "files" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" + CHAIN_NAME: "{{ chain_name }}" + CHAIN_TYPE: "{{ chain_type }}" + ALLOWED_TS_DIFF: "{{ allowed_ts_diff }}" + args: + executable: python3 + tags: create_chain diff --git a/skale-nodes/ansible/roles/delete_chain/tasks/main.yaml b/skale-nodes/ansible/roles/delete_chain/tasks/main.yaml new file mode 100644 index 00000000..a1ad047e --- /dev/null +++ b/skale-nodes/ansible/roles/delete_chain/tasks/main.yaml @@ -0,0 +1,11 @@ +- name: Execute delete_chain script + script: delete_chain.py + environment: + BASE_DIR: "files" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" + CHAIN_NAME: "{{ chain_name }}" + args: + executable: python3 + tags: delete_chain diff --git a/skale-nodes/ansible/roles/deploy_contracts/tasks/ima.yaml b/skale-nodes/ansible/roles/deploy_contracts/tasks/ima.yaml index e5949f05..a18725e4 100644 --- a/skale-nodes/ansible/roles/deploy_contracts/tasks/ima.yaml +++ b/skale-nodes/ansible/roles/deploy_contracts/tasks/ima.yaml @@ -9,45 +9,24 @@ tags: - deploy_ima -- name: Generate random string - set_fact: - random_str: "{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=15') }}" - tags: - - upload_ima - -- name: Upload IMA ABI to S3 - aws_s3: - aws_access_key: "{{ aws_key }}" - aws_secret_key: "{{ aws_secret }}" - bucket: "skale-abis" - src: "{{ playbook_dir }}/../../helper-scripts/contracts_data/ima.json" - object: 'ima-abi-{{ ima_tag }}-{{ random_str }}.json' - region: 'eu-central-1' - mode: put - permission: "public-read" +- name: Get IMA Contract Address + shell: "jq -r '.message_proxy_mainnet_address' {{ playbook_dir }}/../../helper-scripts/contracts_data/ima.json" + register: ima_address_output + changed_when: false tags: - upload_ima - register: url_output -- name: Format download URL - shell: echo "{{ url_output.url }}" | cut -f1 -d"?" - register: ima_url - tags: - - upload_ima - -- name: Show ABIs download URL - debug: - msg: >- - ABIs download URL: {{ ima_url.stdout }} - tags: - - upload_ima +- name: Save IMA Contract Address to variable + set_fact: + ima_contracts: "{{ ima_address_output.stdout }}" + tags: upload_ima - name: Save IMA URL to group vars lineinfile: path: "{{ playbook_dir }}/group_vars/all" - insertafter: EOF - regexp: '^ima_url:' - line: "ima_url: {{ ima_url.stdout }}" - state: present + create: yes + regexp: "^ima_contracts:" + line: "ima_contracts: '{{ ima_contracts }}'" + run_once: yes tags: - upload_ima diff --git a/skale-nodes/ansible/roles/deploy_contracts/tasks/main.yaml b/skale-nodes/ansible/roles/deploy_contracts/tasks/main.yaml index a6d907a3..ce37a0ae 100644 --- a/skale-nodes/ansible/roles/deploy_contracts/tasks/main.yaml +++ b/skale-nodes/ansible/roles/deploy_contracts/tasks/main.yaml @@ -1,2 +1,4 @@ +- import_tasks: transfer_funds.yaml + when: anvil is defined and anvil - import_tasks: manager.yaml -- import_tasks: ima.yaml \ No newline at end of file +- import_tasks: ima.yaml diff --git a/skale-nodes/ansible/roles/deploy_contracts/tasks/manager.yaml b/skale-nodes/ansible/roles/deploy_contracts/tasks/manager.yaml index 68bff0ba..328a8ae7 100644 --- a/skale-nodes/ansible/roles/deploy_contracts/tasks/manager.yaml +++ b/skale-nodes/ansible/roles/deploy_contracts/tasks/manager.yaml @@ -7,62 +7,60 @@ ENDPOINT: "{{ endpoint }}" GAS_PRICE: "{{ deploy_gas_price }}" NETWORK: "custom" + ETHERSCAN: "{{ etherscan }}" tags: deploy_sm - -- name: Save SM URL to group vars +- name: Copy SM ABI copy: src: "{{ playbook_dir }}/../../helper-scripts/contracts_data/manager.json" dest: "{{ playbook_dir }}/../../helper-scripts/contracts_data/skaleManagerComponents.json" tags: upload_sm - -- name: Generate random string - set_fact: - random_str: "{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=15') }}" +- name: Get SM Contract Address + shell: "jq -r '.skale_manager_address' {{ playbook_dir }}/../../helper-scripts/contracts_data/manager.json" + register: sm_address_output + changed_when: false tags: upload_sm - -- name: Upload SM ABI to S3 - aws_s3: - aws_access_key: "{{ aws_key }}" - aws_secret_key: "{{ aws_secret }}" - bucket: "skale-abis" - src: "{{ playbook_dir }}/../../helper-scripts/contracts_data/manager.json" - object: "skale-manager-abi-{{ manager_tag }}-{{ random_str }}.json" - region: "eu-central-1" - mode: put - permission: "public-read" - tags: upload_sm - register: url_output - - -- name: Format download URL - shell: echo "{{ url_output.url }}" | cut -f1 -d"?" - register: sm_url +- name: Save SM Contract Address to variable + set_fact: + manager_contracts: "{{ sm_address_output.stdout }}" tags: upload_sm - -- name: Show ABIs download URL - debug: - msg: >- - ABIs download URL: {{ sm_url.stdout }} - tags: - - upload_sm - - -- name: Ensure group vars all - file: - state: touch +- name: Save SM URL to group vars + lineinfile: path: "{{ playbook_dir }}/group_vars/all" + create: yes + regexp: "^manager_contracts:" + line: "manager_contracts: '{{ manager_contracts }}'" tags: upload_sm +- name: Set allowed_ts_diff based on anvil variable + set_fact: + allowed_ts_diff: "{{ -1 if anvil is defined and anvil else 300 }}" + run_once: yes + tags: fix_zero_node -- name: Save SM URL to group vars +- name: Save allowed_ts_diff to group vars lineinfile: path: "{{ playbook_dir }}/group_vars/all" - insertafter: EOF - regexp: '^sm_url:' - line: "sm_url: {{ sm_url.stdout }}" - state: present - tags: upload_sm + create: yes + regexp: "^allowed_ts_diff:" + line: "allowed_ts_diff: {{ allowed_ts_diff }}" + run_once: yes + tags: fix_zero_node + + +- name: Hotfix for zero node in Fair + run_once: yes + script: fix_zero_node_fair.py + environment: + BASE_DIR: "files" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" + ALLOWED_TS_DIFF: "{{ allowed_ts_diff }}" + args: + executable: python3 + tags: fix_zero_node + when: node_type == "fair_boot" or node_type == "fair" diff --git a/skale-nodes/ansible/roles/deploy_contracts/tasks/transfer_funds.yaml b/skale-nodes/ansible/roles/deploy_contracts/tasks/transfer_funds.yaml new file mode 100644 index 00000000..c4e9979a --- /dev/null +++ b/skale-nodes/ansible/roles/deploy_contracts/tasks/transfer_funds.yaml @@ -0,0 +1,61 @@ +- name: Set allowed_ts_diff based on anvil variable + set_fact: + allowed_ts_diff: "{{ -1 if anvil is defined and anvil else 300 }}" + run_once: yes + tags: + - anvil + +- name: Save allowed_ts_diff to group vars + lineinfile: + path: "{{ playbook_dir }}/group_vars/all" + create: yes + regexp: "^allowed_ts_diff:" + line: "allowed_ts_diff: {{ allowed_ts_diff }}" + run_once: yes + tags: + - anvil + +- name: Show anvil_private_key + debug: + msg: "{{ anvil_private_key }}" + +- name: Set endpoint for anvil + set_fact: + endpoint: "http://{{ hostvars[groups['nodes'][0]].ansible_host }}:8545" + run_once: true + when: anvil is defined and anvil + tags: [anvil] + +- name: Save endpoint for anvil to group vars + lineinfile: + path: "{{ playbook_dir }}/group_vars/all" + create: yes + regexp: "^endpoint:" + line: "endpoint: {{ endpoint }}" + run_once: yes + when: anvil is defined and anvil + tags: [anvil] + +- name: Publish endpoint to all nodes for subsequent plays + set_fact: + endpoint: "{{ endpoint }}" + delegate_to: "{{ item }}" + delegate_facts: true + loop: "{{ groups['nodes'] }}" + run_once: true + when: anvil is defined and anvil + tags: [anvil] + +- name: Transfer funds from the base anvil account to main one + run_once: yes + tags: anvil_funds + script: transfer_funds.py + environment: + ETH_PRIVATE_KEY: "{{ anvil_private_key }}" + TARGET_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ endpoint }}" + BASE_DIR: "files" + AMOUNT: "{{ anvil_eth_amount | default(10) }}" + ALLOWED_TS_DIFF: "{{ allowed_ts_diff }}" + args: + executable: python3 diff --git a/skale-nodes/ansible/roles/deploy_fair/tasks/deploy_fair.yaml b/skale-nodes/ansible/roles/deploy_fair/tasks/deploy_fair.yaml new file mode 100644 index 00000000..70743fed --- /dev/null +++ b/skale-nodes/ansible/roles/deploy_fair/tasks/deploy_fair.yaml @@ -0,0 +1,68 @@ +- name: Wait for chain to start on boot nodes + uri: + url: "{{ boot_endpoint }}" + method: POST + body: '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' + body_format: json + headers: + Content-Type: "application/json" + status_code: 200 + register: block_number_response + until: "block_number_response.json.result is defined and (block_number_response.json.result | int(base=16)) > 1" + retries: 90 + delay: 10 + run_once: true + tags: deploy_fair + +- name: Deploy Fair manager contracts (this may take a while, logs - {{ playbook_dir }}/logs/fair-deploy.log) + shell: bash {{ playbook_dir }}/../../helper-scripts/deploy_fair.sh 2>&1 | tee {{ playbook_dir }}/logs/fair-deploy.log + run_once: yes + environment: + FAIR_TAG: "{{ fair_tag }}" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + MAINNET_ENDPOINT: "{{ endpoint }}" + ENDPOINT: "{{ boot_endpoint }}" + CHAIN_NAME: "{{ chain_name }}" + TARGET: "{{ manager_contracts }}" + EXPLORER_URL: "{{ explorer_url | default('') }}" + tags: deploy_fair + +- name: Copy Fair ABI + copy: + src: "{{ playbook_dir }}/../../helper-scripts/contracts_data/fair.json" + dest: "{{ playbook_dir }}/../../helper-scripts/contracts_data/fairManagerComponents.json" + tags: upload_fair + +- name: Ensure group vars all + file: + state: touch + path: "{{ playbook_dir }}/group_vars/all" + tags: upload_fair + +- name: Get Fair Contract Address + shell: "jq -r '.Committee' {{ playbook_dir }}/../../helper-scripts/contracts_data/fair.json" + register: mm_address_output + changed_when: false + tags: upload_fair + +- name: Save Fair Contract Address to variable + set_fact: + fair_contracts: "{{ mm_address_output.stdout }}" + tags: upload_fair + +- name: Save Fair Contract Address to group vars + lineinfile: + path: "{{ playbook_dir }}/group_vars/all" + insertafter: EOF + regexp: "^fair_contracts:" + line: 'fair_contracts: "{{ fair_contracts }}"' + state: present + tags: upload_fair + +- name: Publish fair_contracts to all nodes for subsequent plays + set_fact: + fair_contracts: "{{ fair_contracts }}" + delegate_to: "{{ item }}" + delegate_facts: true + loop: "{{ groups['nodes'] }}" + run_once: true \ No newline at end of file diff --git a/skale-nodes/ansible/roles/deploy_fair/tasks/main.yaml b/skale-nodes/ansible/roles/deploy_fair/tasks/main.yaml new file mode 100644 index 00000000..991a2103 --- /dev/null +++ b/skale-nodes/ansible/roles/deploy_fair/tasks/main.yaml @@ -0,0 +1,5 @@ +- import_tasks: deploy_fair.yaml + tags: [deploy_fair] +- import_tasks: whitelist_and_stake.yaml + tags: [whitelist_and_stake] + diff --git a/skale-nodes/ansible/roles/deploy_fair/tasks/whitelist_and_stake.yaml b/skale-nodes/ansible/roles/deploy_fair/tasks/whitelist_and_stake.yaml new file mode 100644 index 00000000..8ca2612a --- /dev/null +++ b/skale-nodes/ansible/roles/deploy_fair/tasks/whitelist_and_stake.yaml @@ -0,0 +1,10 @@ +- name: Execute whitelist_and_stake script + script: whitelist_and_stake.py + environment: + BASE_DIR: "files" + WEI_AMOUNT: "1" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ boot_endpoint }}" + FAIR_CONTRACTS: "{{ fair_contracts }}" + args: + executable: python3 \ No newline at end of file diff --git a/skale-nodes/ansible/roles/fair_migrate/tasks/main.yaml b/skale-nodes/ansible/roles/fair_migrate/tasks/main.yaml new file mode 100644 index 00000000..6c25daed --- /dev/null +++ b/skale-nodes/ansible/roles/fair_migrate/tasks/main.yaml @@ -0,0 +1,51 @@ +- name: Set node_type to fair for migration + set_fact: + node_type: "fair" + +- name: Fair migrate + command: + cmd: "fair node migrate {{ base_path }}/init-env --yes" + register: migrate_cmd + +- name: Show migrate command output + debug: + msg: "{{ migrate_cmd.stdout }}" + +- name: Clean up anvil resources + delegate_to: "{{ groups['nodes'][0] }}" + run_once: true + when: anvil is defined and anvil + tags: stop_anvil + block: + - name: Stop and remove anvil container + docker_container: + name: anvil + state: absent + + - name: Remove anvil state directory + file: + path: /var/lib/anvil-state + state: absent + +- name: Execute set_rng script + script: set_rng.py + environment: + BASE_DIR: "files" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ boot_endpoint }}" + FAIR_CONTRACTS: "{{ fair_contracts }}" + args: + executable: python3 + delegate_to: localhost + run_once: true + become: false + tags: set_rng + +- name: Remove node_type from group_vars/all + delegate_to: localhost + run_once: true + become: false + lineinfile: + path: "{{ playbook_dir }}/group_vars/all" + regexp: '^node_type' + state: absent diff --git a/skale-nodes/ansible/roles/init/tasks/main.yaml b/skale-nodes/ansible/roles/init/tasks/main.yaml index 26a115df..45693b11 100644 --- a/skale-nodes/ansible/roles/init/tasks/main.yaml +++ b/skale-nodes/ansible/roles/init/tasks/main.yaml @@ -1,39 +1,54 @@ -- name: Define cmd for regular node +- name: Get FAIR passive node ID (for passive FAIR nodes only) + run_once: yes set_fact: - skale_cmd: "skale node init {{ base_path }}/init-env" - when: sync_node is not defined or not sync_node + passive_node_id: "{{ lookup('file', 'files/passive-id.txt') }}" + when: + - node_type == 'fair' + - passive_node is defined and passive_node -- name: Define cmd for sync node +- name: Set sync_flags based on passive_node status set_fact: - skale_cmd: "skale sync-node init {{ base_path }}/init-env" - when: sync_node is defined and sync_node + sync_flags: "{{ '--id ' ~ passive_node_id if node_type == 'fair' and (passive_node | default(false) | bool) else '' }}" -- name: Add --catchup if needed +- name: Add --indexer if needed set_fact: - skale_cmd: "{{ skale_cmd }} --catchup" - when: sync_node is defined and sync_node and catchup is defined and catchup + sync_flags: "{{ sync_flags }} --indexer" + when: + - passive_node is defined and passive_node + - indexer is defined and indexer - name: Add --archive if needed set_fact: - skale_cmd: "{{ skale_cmd }} --archive" - when: sync_node is defined and sync_node and archive is defined and archive + sync_flags: "{{ sync_flags }} --archive" + when: + - passive_node is defined and passive_node + - archive is defined and archive -- name: Add --historic-state if needed +- name: Add --snapshot if needed set_fact: - skale_cmd: "{{ skale_cmd }} --historic-state" - when: sync_node is defined and sync_node and historic_state is defined and historic_state -- name: Show skale_cmd - debug: - msg: "{{ skale_cmd }}" + sync_flags: "{{ sync_flags }} --snapshot {{ snapshot }}" + when: + - node_type == 'fair' + - passive_node is defined and passive_node + - snapshot is defined + - snapshot == 'any' or 'http' in snapshot -- name: Execute skale_cmd +- name: Build and execute init command command: - cmd: "{{ skale_cmd }}" - environment: - LANG: en_US.utf-8 - LC_ALL: en_US.utf-8 + cmd: "{{ command_prefixes[node_type] }} init {{ base_path }}/init-env {{ sync_flags }}" + vars: + command_prefixes: + fair_boot: "fair boot" + fair: "{{ 'fair passive-node' if (passive_node | default(false) | bool) else 'fair node' }}" + skale: "{{ 'skale passive-node' if (passive_node | default(false) | bool) else 'skale node' }}" + when: node_type in command_prefixes + register: init_cmd + +- name: Show init command output + debug: + msg: "{{ init_cmd.stdout }}" - name: Pause to make sure skale-admin exchange certs with sgx server pause: seconds: 120 - tags: init + when: passive_node is not defined or not passive_node diff --git a/skale-nodes/ansible/roles/link_addresses/tasks/link_addresses.yaml b/skale-nodes/ansible/roles/link_addresses/tasks/link_addresses.yaml index 688547ca..cbdeb1ba 100644 --- a/skale-nodes/ansible/roles/link_addresses/tasks/link_addresses.yaml +++ b/skale-nodes/ansible/roles/link_addresses/tasks/link_addresses.yaml @@ -11,7 +11,9 @@ ADDRESS: "{{ lookup('file', '{{ item }}').split()[0].strip() }}" SIGNATURE: "{{ lookup('file', '{{ item }}').split()[1].strip() }}" ENDPOINT: "{{ endpoint }}" + MANAGER_CONTRACTS: "{{ manager_contracts }}" BASE_DIR: "files" + ALLOWED_TS_DIFF: "{{ allowed_ts_diff }}" args: executable: python3 with_fileglob: "node-info/*" diff --git a/skale-nodes/ansible/roles/link_addresses/tasks/transfer_funds.yaml b/skale-nodes/ansible/roles/link_addresses/tasks/transfer_funds.yaml index 8aa11a08..eed87d55 100644 --- a/skale-nodes/ansible/roles/link_addresses/tasks/transfer_funds.yaml +++ b/skale-nodes/ansible/roles/link_addresses/tasks/transfer_funds.yaml @@ -1,13 +1,27 @@ - name: Transfer funds to node wallets run_once: yes - script: transfer_funds.py + tags: node_funds + ansible.builtin.script: transfer_funds.py environment: ETH_PRIVATE_KEY: "{{ eth_private_key }}" - ADDRESS: "{{ lookup('file', '{{ item }}').split()[0].strip() }}" - ENDPOINT: "{{ endpoint }}" + ADDRESS: "{{ lookup('file', item).split()[0].strip() }}" + ENDPOINT: "{{ transfer_map[node_type].endpoint }}" + MANAGER_CONTRACTS: "{{ transfer_map[node_type].contracts }}" BASE_DIR: "files" AMOUNT: 0.2 + ALLOWED_TS_DIFF: "{{ allowed_ts_diff }}" args: executable: python3 with_fileglob: "node-info/*" - tags: node_funds + vars: + transfer_map: + fair: + endpoint: "{{ boot_endpoint | default('') }}" + contracts: "{{ fair_contracts | default('') }}" + fair_boot: + endpoint: "{{ endpoint }}" + contracts: "{{ manager_contracts }}" + skale: + endpoint: "{{ endpoint }}" + contracts: "{{ manager_contracts }}" + when: node_type in transfer_map \ No newline at end of file diff --git a/skale-nodes/ansible/roles/node_backup/tasks/main.yaml b/skale-nodes/ansible/roles/node_backup/tasks/main.yaml index 969745bc..54347346 100644 --- a/skale-nodes/ansible/roles/node_backup/tasks/main.yaml +++ b/skale-nodes/ansible/roles/node_backup/tasks/main.yaml @@ -1,4 +1,2 @@ -- name: Backup node - import_tasks: - file: node.yaml - tags: node +- import_tasks: node.yaml + tags: [backup_node] \ No newline at end of file diff --git a/skale-nodes/ansible/roles/node_backup/tasks/node.yaml b/skale-nodes/ansible/roles/node_backup/tasks/node.yaml index 66913e92..0055b1ae 100644 --- a/skale-nodes/ansible/roles/node_backup/tasks/node.yaml +++ b/skale-nodes/ansible/roles/node_backup/tasks/node.yaml @@ -1,9 +1,20 @@ +- name: Validate node_type + fail: + msg: > + The 'node_type' variable must be defined and set to either 'skale' or 'fair'. + Current value: '{{ node_type | default('undefined') }}' + when: node_type is not defined or node_type not in ['skale', 'fair'] + - name: Setting backup archive folder set_fact: backup_path="{{ base_path }}/backup" +- name: Set node command prefix + set_fact: + node_cmd_prefix: "{{ 'fair' if node_type == 'fair' else 'skale' }}" + - name: Turn off the node command: - cmd: "skale node turn-off --yes" + cmd: "{{ node_cmd_prefix }} node turn-off --yes" when: not no_downtime is defined or not no_downtime become: true @@ -15,7 +26,7 @@ - name: Create backup archive command: - cmd: "skale node backup {{ backup_path }}" + cmd: "{{ node_cmd_prefix }} node backup {{ backup_path }}" become: true - name: Create sgx sim backup @@ -28,7 +39,7 @@ - name: Turn on the node back command: - cmd: "skale node turn-on {{ base_path }}/init-env --yes" + cmd: "{{ node_cmd_prefix }} node turn-on {{ base_path }}/init-env --yes" when: not no_downtime is defined or not no_downtime become: true diff --git a/skale-nodes/ansible/roles/node_restore/tasks/main.yaml b/skale-nodes/ansible/roles/node_restore/tasks/main.yaml index 0eb30ab4..d5134f58 100644 --- a/skale-nodes/ansible/roles/node_restore/tasks/main.yaml +++ b/skale-nodes/ansible/roles/node_restore/tasks/main.yaml @@ -1 +1,2 @@ -- include: node.yaml +- import_tasks: node.yaml + tags: [restore_node] diff --git a/skale-nodes/ansible/roles/node_restore/tasks/node.yaml b/skale-nodes/ansible/roles/node_restore/tasks/node.yaml index 59817262..c6727931 100644 --- a/skale-nodes/ansible/roles/node_restore/tasks/node.yaml +++ b/skale-nodes/ansible/roles/node_restore/tasks/node.yaml @@ -1,3 +1,14 @@ +- name: Validate node_type + fail: + msg: > + The 'node_type' variable must be defined and set to either 'skale' or 'fair'. + Current value: '{{ node_type | default('undefined') }}' + when: node_type is not defined or node_type not in ['skale', 'fair'] + +- name: Set node command prefix + set_fact: + node_cmd_prefix: "{{ 'fair' if node_type == 'fair' else 'skale' }}" + - name: Lookup backupfile delegate_to: localhost find: @@ -11,7 +22,7 @@ - name: Get latest backup set_fact: - backup_name: "{{ (search_result.files | sort(attribute='mtime'))[-1].path | basename }}" + backup_name: "{{ (search_result.files | sort(attribute='mtime', reverse=true) | first).path | basename }}" - name: Upload node backup file copy: @@ -25,19 +36,18 @@ - name: Compose regular cmd set_fact: - cmd: "skale node restore {{ base_path }}/backup.tar.gz {{ base_path }}/init-env" + cmd: "{{ node_cmd_prefix }} node restore {{ base_path }}/backup.tar.gz {{ base_path }}/init-env" when: config_only is not defined or not config_only - name: Compose cmd with config only set_fact: - cmd: "skale node restore --config-only {{ base_path }}/backup.tar.gz {{ base_path }}/init-env" - when: config_only is defined and config_only + cmd: "{{ node_cmd_prefix }} node restore --config-only {{ base_path }}/backup.tar.gz {{ base_path }}/init-env" + when: + - node_type == "skale" + - config_only is defined and config_only -- name: Run skale node restore +- name: Run skale/fair node restore shell: cmd: "{{ cmd }}" environment: - LANG: en_US.utf-8 - LC_ALL: en_US.utf-8 HOME_DIR: "{{ base_path }}" - tags: skale_restore diff --git a/skale-nodes/ansible/roles/register/tasks/main.yaml b/skale-nodes/ansible/roles/register/tasks/main.yaml index 2d222c7c..71744a2c 100644 --- a/skale-nodes/ansible/roles/register/tasks/main.yaml +++ b/skale-nodes/ansible/roles/register/tasks/main.yaml @@ -1,11 +1,14 @@ -- name: Register ip address - set_fact: - # ip_address: "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}" # private ip - ip_address: "{{ hostvars[inventory_hostname].ansible_host }}" # public ip - -- name: Run skale node register +- name: Register node command: - cmd: "skale node register --name {{ inventory_hostname }} --ip {{ ip_address }} --port 10000 --domain {{ ip_address }}.{{ base_domain_name }}" - environment: - LANG: en_US.utf-8 - LC_ALL: en_US.utf-8 + cmd: "{{ node_commands[node_type] }}" + vars: + node_commands: + fair_boot: "fair boot register -n {{ inventory_hostname }} --ip {{ hostvars[inventory_hostname].ansible_host }} -p 10000 -d {{ inventory_hostname }}.{{ base_domain_name }}" + fair: "fair node register --ip {{ hostvars[inventory_hostname].ansible_host }}" + skale: "skale node register -n {{ inventory_hostname }} --ip {{ hostvars[inventory_hostname].ansible_host }} -p 10000 -d {{ inventory_hostname }}.{{ base_domain_name }}" + when: node_type in node_commands + register: register_cmd + +- name: Show register command output + debug: + msg: "{{ register_cmd.stdout }}" diff --git a/skale-nodes/ansible/roles/register_passive_fair/tasks/main.yaml b/skale-nodes/ansible/roles/register_passive_fair/tasks/main.yaml new file mode 100644 index 00000000..488017ad --- /dev/null +++ b/skale-nodes/ansible/roles/register_passive_fair/tasks/main.yaml @@ -0,0 +1,10 @@ +- name: Execute register_passive_fair script + script: register_passive_fair.py + environment: + BASE_DIR: "files" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ boot_endpoint }}" + FAIR_CONTRACTS: "{{ fair_contracts }}" + PASSIVE_FAIR_IP: "{{ hostvars[groups['nodes'][0]]['ansible_host'] }}" + args: + executable: python3 \ No newline at end of file diff --git a/skale-nodes/ansible/roles/run_anvil/tasks/main.yaml b/skale-nodes/ansible/roles/run_anvil/tasks/main.yaml new file mode 100644 index 00000000..458f370b --- /dev/null +++ b/skale-nodes/ansible/roles/run_anvil/tasks/main.yaml @@ -0,0 +1,86 @@ +- name: Manage anvil container on the first remote node + run_once: true + tags: + - anvil + block: + - name: Ensure previous anvil container is removed + docker_container: + name: anvil + state: absent + + - name: Create directory for anvil state on host + file: + path: /var/lib/anvil-state + state: directory + owner: '1000' + group: '1000' + mode: '0755' + + - name: Define base anvil command + set_fact: + anvil_cmd: + - --host + - 0.0.0.0 + - --gas-price + - "0" + - --block-base-fee-per-gas + - "0" + - --state + - /state/anvil-state.json + - --state-interval + - "10" + - --disable-min-priority-fee + - -vvvv + + - name: Add block-time for skale node type + set_fact: + anvil_cmd: "{{ anvil_cmd + ['--block-time', '1'] }}" + when: node_type == 'skale' + + - name: Run anvil container + docker_container: + name: anvil + image: "ghcr.io/foundry-rs/foundry:v1.4.0" + restart_policy: always + entrypoint: anvil + command: "{{ anvil_cmd }}" + published_ports: + - "8545:8545" + volumes: + - /var/lib/anvil-state:/state + detach: true + state: started + + - name: Wait for anvil to start + pause: + seconds: 15 + + - name: Get private key from anvil logs + shell: "docker logs anvil 2>&1 | grep -A 10 'Private Keys' | grep '(0)' | awk '{print $2}'" + register: key_output + changed_when: false + +- name: Set anvil_private_key fact + run_once: true + set_fact: + anvil_private_key: "{{ key_output.stdout | trim }}" + tags: + - anvil + +- name: Expose anvil_private_key to 127.0.0.1 for subsequent plays + set_fact: + anvil_private_key: "{{ anvil_private_key }}" + delegate_to: 127.0.0.1 + delegate_facts: true + run_once: true + +- name: Save anvil_private_key to group vars + lineinfile: + path: "{{ playbook_dir }}/group_vars/all" + create: yes + regexp: "^anvil_private_key:" + line: "anvil_private_key: '{{ anvil_private_key }}'" + run_once: yes + delegate_to: localhost + tags: + - anvil \ No newline at end of file diff --git a/skale-nodes/ansible/roles/set_fair_boot_node_type/tasks/main.yaml b/skale-nodes/ansible/roles/set_fair_boot_node_type/tasks/main.yaml new file mode 100644 index 00000000..922eb8b1 --- /dev/null +++ b/skale-nodes/ansible/roles/set_fair_boot_node_type/tasks/main.yaml @@ -0,0 +1,18 @@ +- name: Set node_type to fair_boot + set_fact: + node_type: "fair_boot" + +- name: Publish node_type to all nodes for subsequent plays + set_fact: + node_type: "fair_boot" + delegate_to: "{{ item }}" + delegate_facts: true + loop: "{{ groups['nodes'] }}" + run_once: true + +- name: Save node_type to group_vars/all for future runs + lineinfile: + path: "{{ playbook_dir }}/group_vars/all" + create: yes + regexp: "^node_type:" + line: "node_type: fair_boot" diff --git a/skale-nodes/ansible/roles/setup_validator/tasks/main.yaml b/skale-nodes/ansible/roles/setup_validator/tasks/main.yaml new file mode 100644 index 00000000..b58357e3 --- /dev/null +++ b/skale-nodes/ansible/roles/setup_validator/tasks/main.yaml @@ -0,0 +1,18 @@ +- name: Set hosts + set_fact: hosts="{{ hosts|default([]) + [ item.value['ansible_host'] ] }}" + with_dict: "{{ hostvars }}" + +- name: Execute setup_validator script + script: setup_validator.py + environment: + BASE_DIR: "files" + ETH_AMOUNT: "0.2" + ETH_PRIVATE_KEY: "{{ eth_private_key }}" + ENDPOINT: "{{ endpoint }}" + MIN_DELEGATION_AMOUNT: "0" + MANAGER_CONTRACTS: "{{ manager_contracts }}" + COMMISSION_RATE: "1" + NODES_NUMBER: "{{ hosts|length }}" + ALLOWED_TS_DIFF: "{{ allowed_ts_diff }}" + args: + executable: python3 diff --git a/skale-nodes/ansible/roles/sgx/tasks/sgx_sim.yaml b/skale-nodes/ansible/roles/sgx/tasks/sgx_sim.yaml index ecf538e9..de5f0c55 100644 --- a/skale-nodes/ansible/roles/sgx/tasks/sgx_sim.yaml +++ b/skale-nodes/ansible/roles/sgx/tasks/sgx_sim.yaml @@ -13,5 +13,5 @@ command: -s -y -d -V log_driver: json-file log_opt: - max-size: "10m" - max-file: "4" + max-size: "10m" + max-file: "4" diff --git a/skale-nodes/ansible/roles/signature/tasks/main.yaml b/skale-nodes/ansible/roles/signature/tasks/main.yaml index f8d6dd79..89b0e4ae 100644 --- a/skale-nodes/ansible/roles/signature/tasks/main.yaml +++ b/skale-nodes/ansible/roles/signature/tasks/main.yaml @@ -2,7 +2,7 @@ set_fact: node_info_dir: "files/node-info" -- name: Create foder for nodes addresses info +- name: Create folder for nodes addresses info file: path: "{{ node_info_dir }}" state: directory @@ -13,29 +13,47 @@ set_fact: validator_id: "{{ lookup('file', 'files/validator-id.txt') }}" -- debug: msg="{{ validator_id }}" - -- name: Get skale wallet info output - command: "sudo skale wallet info -f json" - register: wallet_cmd_result - environment: - LC_ALL: "C.UTF-8" - LANG: "C.UTF-8" +- name: Show Validator Id + debug: + msg: "{{ validator_id }}" + +- name: Get wallet info + command: + cmd: "{{ node_commands[node_type] }}" + vars: + node_commands: + fair_boot: "sudo fair wallet info -f json" + skale: "sudo skale wallet info -f json" + when: node_type in node_commands + register: wallet_info_cmd + changed_when: false + +- name: Show wallet info command output + debug: + msg: "{{ wallet_info_cmd.stdout }}" - name: Get wallet data from json set_fact: - wallet_data: "{{ wallet_cmd_result.stdout | to_json | from_json }}" + wallet_data: "{{ wallet_info_cmd.stdout | to_json | from_json }}" - name: Get node signature - command: "sudo skale node signature {{ validator_id }}" - register: signature_cmd_result - environment: - LC_ALL: "C.UTF-8" - LANG: "C.UTF-8" + command: + cmd: "{{ node_commands[node_type] }}" + vars: + node_commands: + fair_boot: "sudo fair boot signature {{ validator_id }}" + skale: "sudo skale node signature {{ validator_id }}" + when: node_type in node_commands + register: get_signature_cmd + changed_when: false + +- name: Display node signature + debug: + msg: "{{ get_signature_cmd.stdout }}" - name: Get wallet data from json set_fact: - signature: "{{ signature_cmd_result.stdout.split()[1] }}" + signature: "{{ get_signature_cmd.stdout.split()[1] }}" - name: Save address and signature to a file copy: diff --git a/skale-nodes/ansible/roles/skale_cli/tasks/main.yaml b/skale-nodes/ansible/roles/skale_cli/tasks/main.yaml index e0cae154..c0c21c5c 100644 --- a/skale-nodes/ansible/roles/skale_cli/tasks/main.yaml +++ b/skale-nodes/ansible/roles/skale_cli/tasks/main.yaml @@ -1,36 +1,75 @@ -- name: Makedir dist +# --- Download binary --- + +- name: Download the correct binary based on node type + when: build_type == "git" + tags: binary + get_url: + url: "{{ download_map[base_node_type].url }}" + dest: "{{ download_map[base_node_type].dest }}" + force: yes + mode: "0755" + vars: + base_node_type: "{{ 'fair' if node_type == 'fair_boot' else node_type }}" + download_map: + skale: + url: "{{ skale_cli_url }}" + dest: "/usr/local/bin/skale" + fair: + url: "{{ fair_cli_url }}" + dest: "/usr/local/bin/fair" + +# --- Build binary from source --- + +- name: Makedir dist for CLI build file: state: directory path: "{{ base_path }}/node-cli/dist" - when: env is defined and env == "dev" + when: + - build_type == "source" +- name: Ensure builder container is removed before image operations + docker_container: + name: "node-cli-builder" + state: absent + when: + - build_type == "source" - name: Remove old binary builder image community.docker.docker_image: name: "node-cli-builder" state: absent - when: env is defined and env == "dev" - + force_source: true + when: + - build_type == "source" - name: Build binary builder image community.docker.docker_image_build: name: "node-cli-builder" network: host path: "{{ base_path }}/node-cli" - when: env is defined and env == "dev" - - -- name: Set build command - set_fact: - build_cmd: "scripts/build.sh test test normal" - when: env is defined and env == "dev" and sync_node is not defined or not sync_node - - -- name: Add sync option to command - set_fact: - build_cmd: "scripts/build.sh test test sync" - when: env is defined and env == "dev" and sync_node is defined and sync_node - + when: + - build_type == "source" + +- name: Determine and set build command based on node type + when: build_type == "source" + block: + - name: Determine build target from a simple map + set_fact: + _build_target: "{{ build_target_map[base_node_type] | default('') }}" + vars: + base_node_type: "{{ 'fair' if node_type == 'fair_boot' else node_type }}" + build_target_map: + fair: "fair" + skale: "skale" + + - name: Fail if build target is unknown + fail: + msg: "Unsupported node_type: {{ node_type }}" + when: _build_target | length == 0 + + - name: Set full build command + set_fact: + build_cmd: "bash scripts/build.sh test test {{ _build_target }}" - name: Build binary docker_container: @@ -40,44 +79,40 @@ volumes: - "{{ base_path }}/node-cli/dist:/app/dist" command: "{{ build_cmd }}" - when: env is defined and env == "dev" - - -- name: Copy executable to /usr/bin/local for normal - copy: remote_src=True src="{{ base_path }}/node-cli/dist/skale-test-Linux-x86_64" dest=/usr/local/bin/skale - when: env is defined and env == "dev" and (sync_node is not defined or not sync_node) - - -- name: Copy executable to /usr/bin/local for sync - copy: remote_src=True src="{{ base_path }}/node-cli/dist/skale-test-Linux-x86_64-sync" dest=/usr/local/bin/skale - when: env is defined and env == "dev" and sync_node is defined and sync_node - + when: + - build_type == "source" + +- name: Copy source-built executable based on node type + when: build_type == "source" + block: + - name: Determine source and destination paths for the executable + set_fact: + executable_paths: "{{ path_map[base_node_type] | default({}) }}" + vars: + base_node_type: "{{ 'fair' if node_type == 'fair_boot' else node_type }}" + path_map: + fair: + src: "{{ base_path }}/node-cli/dist/skale-test-Linux-x86_64-fair" + dest: "/usr/local/bin/fair" + skale: + src: "{{ base_path }}/node-cli/dist/skale-test-Linux-x86_64" + dest: "/usr/local/bin/skale" + + - name: Fail if executable paths could not be determined + fail: + msg: "Unsupported node_type for copy operation: {{ node_type }}" + when: executable_paths | length == 0 or executable_paths.src == "" + + - name: Copy the correct executable to /usr/local/bin + copy: + remote_src: true + src: "{{ executable_paths.src }}" + dest: "{{ executable_paths.dest }}" + mode: "0755" - name: Remove builder container docker_container: state: absent name: node-cli-builder - when: env is defined and env == "dev" - - -- name: Download skale_cli from spaces - get_url: - url: "{{ skale_cli_url }}" - dest: "/usr/local/bin/skale" - force: yes - mode: 644 - when: env is defined and env == "test" - tags: binary - - -- name: Add execute permission to skale executable - file: - path: /usr/local/bin/skale - mode: '0555' - tags: binary - - -- name: Register skale command - set_fact: - skale: "/usr/local/bin/skale" - tags: binary + when: + - build_type == "source" diff --git a/skale-nodes/ansible/roles/ssl/tasks/configure.yaml b/skale-nodes/ansible/roles/ssl/tasks/configure.yaml index e309152c..37c8f145 100644 --- a/skale-nodes/ansible/roles/ssl/tasks/configure.yaml +++ b/skale-nodes/ansible/roles/ssl/tasks/configure.yaml @@ -4,14 +4,8 @@ - name: Upload SSL certificates to the node command: "skale ssl upload -c {{ host_ssl }}/fullchain.pem -k {{ host_ssl }}/privkey.pem -f" - environment: - LC_ALL: "C.UTF-8" - LANG: "C.UTF-8" - name: Set domain name command: "sudo skale node set-domain -d {{ domain }} --yes" - environment: - LC_ALL: "C.UTF-8" - LANG: "C.UTF-8" tags: domain diff --git a/skale-nodes/ansible/roles/sync/tasks/main.yaml b/skale-nodes/ansible/roles/sync/tasks/main.yaml index 2162a5dd..bf81bff2 100644 --- a/skale-nodes/ansible/roles/sync/tasks/main.yaml +++ b/skale-nodes/ansible/roles/sync/tasks/main.yaml @@ -4,7 +4,6 @@ dest: "{{ base_path }}" delete: yes recursive: yes - when: env is defined and env == "dev" tags: admin - name: Synchronization of transaction-manager repo @@ -13,7 +12,6 @@ dest: "{{ base_path }}" delete: yes recursive: yes - when: env is defined and env == "dev" tags: tm - name: Synchronization of skale-watchdog repo @@ -22,7 +20,6 @@ dest: "{{ base_path }}" delete: yes recursive: yes - when: env is defined and env == "dev" tags: watchdog - name: Synchronization of skale-node repo @@ -31,7 +28,6 @@ dest: "{{ base_path }}" delete: yes recursive: yes - when: env is defined and env == "dev" tags: skale-node - name: Synchronization of node-cli repo @@ -40,7 +36,6 @@ dest: "{{ base_path }}" delete: yes recursive: yes - when: env is defined and env == "dev" tags: cli - name: Synchronization of bounty-agent repo @@ -49,17 +44,20 @@ dest: "{{ base_path }}" delete: yes recursive: yes - when: env is defined and env == "dev" + when: + - node_type == "skale" tags: bounty - name: Replace skale-node docker-compose file template: src: docker-compose.yml.j2 dest: "{{ base_path }}/skale-node/docker-compose.yml" - when: env is defined and env == "dev" + when: + - node_type == "skale" -- name: Replace skale-node docker-compose-sync file +- name: Replace fair-node docker-compose-fair file template: - src: docker-compose-sync.yml.j2 - dest: "{{ base_path }}/skale-node/docker-compose-sync.yml" - when: env is defined and env == "dev" and sync_node is defined and sync_node + src: docker-compose-fair.yml.j2 + dest: "{{ base_path }}/skale-node/docker-compose-fair.yml" + when: + - node_type in ['fair_boot', 'fair'] diff --git a/skale-nodes/ansible/roles/sync/templates/docker-compose-fair.yml.j2 b/skale-nodes/ansible/roles/sync/templates/docker-compose-fair.yml.j2 new file mode 100644 index 00000000..c13342b9 --- /dev/null +++ b/skale-nodes/ansible/roles/sync/templates/docker-compose-fair.yml.j2 @@ -0,0 +1,213 @@ +x-sk-base: &sk_base + restart: unless-stopped + labels: + com.skale.prefix: "node" + cpu_shares: 128 + logging: + driver: "json-file" + options: + max-file: "5" + max-size: "10m" + +services: + transaction-manager: + <<: *sk_base + container_name: sk_tm + image: "skalenetwork/transaction-manager:${TAG:-latest}" + build: + context: "{{ base_path }}/transaction-manager" + dockerfile: Dockerfile + network: host + network_mode: host + tty: true + volumes: + - ${SKALE_DIR}:/skale_vol + - ${SKALE_DIR}/node_data:/skale_node_data + + boot-admin: + <<: *sk_base + container_name: sk_boot_admin + image: "skale-admin:${TAG:-latest}" + build: + context: "{{ base_path }}/skale-admin" + dockerfile: Dockerfile + network: host + cpu_shares: 192 + network_mode: host + tty: true + cap_add: + - NET_ADMIN + - NET_RAW + command: "python3 admin.py" + volumes: + - /var/run/skale:/var/run/skale + - ${SKALE_DIR}:/skale_vol + - ${SKALE_DIR}/node_data:/skale_node_data + - ${SKALE_LIB_PATH}:${SKALE_LIB_PATH} + - /etc/nft.conf.d/skale/chains:/etc/nft.conf.d/skale/chains + healthcheck: + test: ["CMD", "python3", "healthchecks/admin.py"] + interval: 1m + timeout: 10s + retries: 2 + start_period: 30s + + admin: + <<: *sk_base + container_name: sk_admin + image: "skale-admin:${TAG:-latest}" + build: + context: "{{ base_path }}/skale-admin" + dockerfile: Dockerfile + network: host + cpu_shares: 192 + network_mode: host + tty: true + cap_add: + - NET_ADMIN + - NET_RAW + command: "python3 fair.py" + volumes: + - /var/run/skale:/var/run/skale + - ${SKALE_DIR}:/skale_vol + - ${SKALE_DIR}/node_data:/skale_node_data + - ${SKALE_LIB_PATH}:${SKALE_LIB_PATH} + - /etc/nft.conf.d/skale/chains:/etc/nft.conf.d/skale/chains + healthcheck: + test: ["CMD", "python3", "healthchecks/admin.py"] + interval: 1m + timeout: 10s + retries: 2 + start_period: 30s + + boot-api: + <<: *sk_base + container_name: sk_boot_api + image: "skale-admin:${TAG:-latest}" + build: + context: "{{ base_path }}/skale-admin" + dockerfile: Dockerfile + network: host + network_mode: host + tty: true + cap_add: + - NET_ADMIN + - NET_RAW + command: "gunicorn app:app -c gunicorn.conf.py" + volumes: + - /var/run/skale:/var/run/skale + - ${SKALE_DIR}:/skale_vol + - ${SKALE_DIR}/node_data:/skale_node_data + - ${SKALE_LIB_PATH}:${SKALE_LIB_PATH} + - /etc/nft.conf.d/skale/chains:/etc/nft.conf.d/skale/chains + + api: + <<: *sk_base + container_name: sk_api + image: "skale-admin:${TAG:-latest}" + build: + context: "{{ base_path }}/skale-admin" + dockerfile: Dockerfile + network: host + network_mode: host + tty: true + cap_add: + - NET_ADMIN + - NET_RAW + command: "gunicorn fair_api:app -c gunicorn.conf.py" + volumes: + - /var/run/skale:/var/run/skale + - ${SKALE_DIR}:/skale_vol + - ${SKALE_DIR}/node_data:/skale_node_data + - ${SKALE_LIB_PATH}:${SKALE_LIB_PATH} + - /etc/nft.conf.d/skale/chains:/etc/nft.conf.d/skale/chains + + redis: + <<: *sk_base + container_name: sk_redis + image: "redis:8.4.0-alpine" + network_mode: host + tty: true + environment: + - REDIS_REPLICATION_MODE=master + command: "redis-server /data/redis.conf" + volumes: + - ${SKALE_DIR}/node_data/redis-data:/data:rw + - ${SKALE_DIR}/config/redis.conf:/data/redis.conf + restart: unless-stopped + + watchdog: + <<: *sk_base + container_name: sk_watchdog + image: "skale-watchdog:${TAG:-latest}" + build: + context: "{{ base_path }}/skale-watchdog" + dockerfile: Dockerfile + network: host + network_mode: host + environment: + ALLOWED_TS_DIFF: 300 + FLASK_APP_PORT: 3010 + FLASK_APP_HOST: "127.0.0.1" + FLASK_DEBUG_MODE: "False" + SKALE_NETWORK_TYPE: "fair" + PASSIVE_NODE: ${PASSIVE_NODE} + + nginx: + <<: *sk_base + image: nginx:1.20.2 + container_name: sk_nginx + network_mode: host + depends_on: + - watchdog + volumes: + - ${SKALE_DIR}/node_data/nginx.conf:/etc/nginx/conf.d/default.conf:ro + - ${SKALE_DIR}/node_data/ssl:/ssl:ro + - type: bind + bind: + propagation: slave + source: ${SCHAINS_MNT_DIR} + target: ${SCHAINS_MNT_DIR} + read_only: true + + advisor: + <<: *sk_base + image: gcr.io/cadvisor/cadvisor-amd64:v0.50.0 + container_name: monitor_cadvisor + cpu_shares: 128 + network_mode: host + volumes: + - /:/rootfs:ro + - /var/run:/var/run:ro + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /dev/disk/:/dev/disk:ro + + node-exporter: + <<: *sk_base + container_name: monitor_node_exporter + image: quay.io/prometheus/node-exporter + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + command: + - '--path.procfs=/host/proc' + - '--path.rootfs=/rootfs' + - '--path.sysfs=/host/sys' + - '--collector.filesystem.mount-points-exclude=^/(mnt|dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/.+)($$|/)' + network_mode: host + + filebeat: + <<: *sk_base + container_name: sk_filebeat + user: root + image: elastic/filebeat:9.1.3 + network_mode: host + environment: + FILEBEAT_HOST: ${FILEBEAT_HOST} + volumes: + - ${SKALE_DIR}/node_data/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro + - /var/lib/docker:/var/lib/docker:ro + - /var/log/docker-lvmpy:/var/log/docker-lvmpy:ro + - /var/run/skale:/var/run/skale diff --git a/skale-nodes/ansible/roles/sync/templates/docker-compose-sync.yml.j2 b/skale-nodes/ansible/roles/sync/templates/docker-compose-sync.yml.j2 deleted file mode 100644 index c4a1cfeb..00000000 --- a/skale-nodes/ansible/roles/sync/templates/docker-compose-sync.yml.j2 +++ /dev/null @@ -1,63 +0,0 @@ -version: '3.4' - -services: - base: &skale_base - image: rancher/pause:3.6 - restart: unless-stopped - labels: - com.skale.prefix: "node" - cpu_shares: 128 - logging: - driver: "json-file" - options: - max-file: "5" - max-size: "10m" - - skale-sync-admin: - <<: *skale_base - container_name: skale_sync_admin - image: "skale-admin:${TAG:-latest}" - build: - context: "{{ base_path }}/skale-admin" - network: host - dockerfile: Dockerfile - network_mode: host - tty: true - cap_add: - - NET_ADMIN - - NET_RAW - environment: - ENDPOINT: ${ENDPOINT} - SKALE_DIR_HOST: ${SKALE_DIR} - ENV_TYPE: ${ENV_TYPE} - SCHAIN_NAME: ${SCHAIN_NAME} - SYNC_NODE: "True" - command: "python3 sync_node.py" - volumes: - - /var/run/skale:/var/run/skale - - ${SKALE_DIR}:/skale_vol - - ${SKALE_DIR}/node_data:/skale_node_data - - ${SKALE_LIB_PATH}:${SKALE_LIB_PATH} - - /etc/nft.conf.d/skale/chains:/etc/nft.conf.d/skale/chains - healthcheck: - test: ["CMD", "python3", "healthchecks/admin.py"] - interval: 1m - timeout: 10s - retries: 2 - start_period: 30s - - nginx: - <<: *skale_base - image: nginx:1.20.2 - container_name: skale_nginx - network_mode: host - volumes: - - ${SKALE_DIR}/node_data/nginx.conf:/etc/nginx/conf.d/default.conf:ro - - ${SKALE_DIR}/node_data/ssl:/ssl:ro - - /var/lib/skale/filestorage:/filestorage:ro - - type: bind - bind: - propagation: slave - source: ${SCHAINS_MNT_DIR} - target: ${SCHAINS_MNT_DIR} - read_only: true diff --git a/skale-nodes/ansible/roles/sync/templates/docker-compose.yml.j2 b/skale-nodes/ansible/roles/sync/templates/docker-compose.yml.j2 index ed5b1880..56c6ea52 100644 --- a/skale-nodes/ansible/roles/sync/templates/docker-compose.yml.j2 +++ b/skale-nodes/ansible/roles/sync/templates/docker-compose.yml.j2 @@ -1,20 +1,18 @@ -version: '3.4' +x-sk-base: &sk_base + restart: unless-stopped + labels: + com.skale.prefix: "node" + cpu_shares: 128 + logging: + driver: "json-file" + options: + max-file: "5" + max-size: "10m" services: - base: &skale_base - image: kubernetes/pause - restart: unless-stopped - labels: - com.skale.prefix: "node" - logging: - driver: "json-file" - options: - max-file: "5" - max-size: "10m" - transaction-manager: - <<: *skale_base - container_name: skale_transaction-manager + <<: *sk_base + container_name: sk_tm image: "skalenetwork/transaction-manager:${TAG:-latest}" build: context: "{{ base_path }}/transaction-manager" @@ -22,17 +20,13 @@ services: network: host network_mode: host tty: true - environment: - SGX_URL: ${SGX_SERVER_URL} - ENDPOINT: ${ENDPOINT} - ALLOWED_TS_DIFF: 10000 volumes: - ${SKALE_DIR}:/skale_vol - ${SKALE_DIR}/node_data:/skale_node_data - skale-admin: - <<: *skale_base - container_name: skale_admin + admin: + <<: *sk_base + container_name: sk_admin image: "skale-admin:${TAG:-latest}" build: context: "{{ base_path }}/skale-admin" @@ -44,32 +38,11 @@ services: cap_add: - NET_ADMIN - NET_RAW - environment: - TM_URL: http://127.0.0.1:3008 - SGX_SERVER_URL: ${SGX_SERVER_URL} - SGX_CERTIFICATES_DIR_NAME: ${SGX_CERTIFICATES_DIR_NAME} - ENDPOINT: ${ENDPOINT} - IMA_ENDPOINT: ${IMA_ENDPOINT} - SKALE_DIR_HOST: ${SKALE_DIR} - TG_API_KEY: ${TG_API_KEY} - TG_CHAT_ID: ${TG_CHAT_ID} - MONITORING_CONTAINERS: ${MONITORING_CONTAINERS} - BACKUP_RUN: ${BACKUP_RUN} - DISABLE_DRY_RUN: ${DISABLE_DRY_RUN} - DEFAULT_GAS_LIMIT: ${DEFAULT_GAS_LIMIT} - DEFAULT_GAS_PRICE_WEI: ${DEFAULT_GAS_PRICE_WEI} - MAX_ALLOWED_LOG_TIME_DIFF: 600 - DISABLE_IMA: ${DISABLE_IMA} - ENV_TYPE: ${ENV_TYPE} - DEFAULT_TIMEOUT: ${DEFAULT_TIMEOUT} - ALLOWED_TS_DIFF: 10000 - TELEGRAF: "${TELEGRAF}" - INFLUX_URL: "${INFLUX_URL}" - command: "python3 admin.py" + command: "python3 skale_admin.py" volumes: - /var/run/skale:/var/run/skale - ${SKALE_DIR}:/skale_vol - - ${SKALE_DIR}/node_data:/skale_node_data + - ${SKALE_LIB_PATH}:${SKALE_LIB_PATH} - /etc/nft.conf.d/skale/chains:/etc/nft.conf.d/skale/chains healthcheck: test: ["CMD", "python3", "healthchecks/admin.py"] @@ -78,9 +51,9 @@ services: retries: 2 start_period: 30s - skale-api: - <<: *skale_base - container_name: skale_api + api: + <<: *sk_base + container_name: sk_api image: "skale-admin:${TAG:-latest}" build: context: "{{ base_path }}/skale-admin" @@ -91,32 +64,7 @@ services: cap_add: - NET_ADMIN - NET_RAW - environment: - TM_URL: http://127.0.0.1:3008 - SGX_SERVER_URL: ${SGX_SERVER_URL} - SGX_CERTIFICATES_DIR_NAME: ${SGX_CERTIFICATES_DIR_NAME} - ENDPOINT: ${ENDPOINT} - IMA_ENDPOINT: ${IMA_ENDPOINT} - DB_USER: ${DB_USER} - DB_PASSWORD: ${DB_PASSWORD} - DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} - DB_PORT: ${DB_PORT} - FLASK_SECRET_KEY: ${FLASK_SECRET_KEY} - FLASK_APP_PORT: 3007 - FLASK_APP_HOST: "127.0.0.1" - FLASK_DEBUG_MODE: "False" - SKALE_DIR_HOST: ${SKALE_DIR} - TG_API_KEY: ${TG_API_KEY} - TG_CHAT_ID: ${TG_CHAT_ID} - MONITORING_CONTAINERS: ${MONITORING_CONTAINERS} - BACKUP_RUN: ${BACKUP_RUN} - DISABLE_DRY_RUN: ${DISABLE_DRY_RUN} - DEFAULT_GAS_LIMIT: ${DEFAULT_GAS_LIMIT} - DEFAULT_GAS_PRICE_WEI: ${DEFAULT_GAS_PRICE_WEI} - ENV_TYPE: ${ENV_TYPE} - DEFAULT_TIMEOUT: ${DEFAULT_TIMEOUT} - ALLOWED_TS_DIFF: 10000 - command: "gunicorn app:app -c gunicorn.conf.py" + command: "gunicorn skale_api:app -c gunicorn.conf.py" volumes: - /var/run/skale:/var/run/skale - ${SKALE_DIR}:/skale_vol @@ -124,7 +72,7 @@ services: - /etc/nft.conf.d/skale/chains:/etc/nft.conf.d/skale/chains celery: - <<: *skale_base + <<: *sk_base container_name: celery image: "skale-admin:${TAG:-latest}" build: @@ -133,19 +81,15 @@ services: network: host network_mode: host tty: true - environment: - TG_API_KEY: ${TG_API_KEY} - TG_CHAT_ID: ${TG_CHAT_ID} - SKALE_DIR_HOST: ${SKALE_DIR} command: "celery -A tools.notifications.tasks worker --loglevel=info" volumes: - /var/run/skale:/var/run/skale redis: - <<: *skale_base - container_name: skale_redis - image: "redis:6.0.10-alpine" + <<: *sk_base + container_name: sk_redis + image: "redis:8.4.0-alpine" network_mode: host tty: true environment: @@ -156,48 +100,39 @@ services: - ${SKALE_DIR}/config/redis.conf:/data/redis.conf bounty: - <<: *skale_base - container_name: skale_bounty + <<: *sk_base + container_name: sk_bounty image: "bounty-agent:${TAG:-latest}" build: context: "{{ base_path }}/bounty-agent" dockerfile: Dockerfile network: host network_mode: host - environment: - SGX_SERVER_URL: ${SGX_SERVER_URL} - SGX_CERTIFICATES_DIR_NAME: ${SGX_CERTIFICATES_DIR_NAME} - ENDPOINT: ${ENDPOINT} - DB_USER: ${DB_USER} - DB_PASSWORD: ${DB_PASSWORD} - DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} - DB_PORT: ${DB_PORT} - DISABLE_DRY_RUN: ${DISABLE_DRY_RUN} - DEFAULT_GAS_LIMIT: ${DEFAULT_GAS_LIMIT} - DEFAULT_GAS_PRICE_WEI: ${DEFAULT_GAS_PRICE_WEI} - ALLOWED_TS_DIFF: 10000 volumes: - ${SKALE_DIR}:/skale_vol - ${SKALE_DIR}/node_data:/skale_node_data watchdog: - <<: *skale_base - container_name: skale_watchdog + <<: *sk_base + container_name: sk_watchdog image: "skale-watchdog:${TAG:-latest}" build: context: "{{ base_path }}/skale-watchdog" dockerfile: Dockerfile network: host network_mode: host + volumes: + - ${SKALE_DIR}/node_data/settings:/settings:ro environment: + ALLOWED_TS_DIFF: 300 FLASK_APP_PORT: 3010 FLASK_APP_HOST: "127.0.0.1" FLASK_DEBUG_MODE: "False" nginx: - <<: *skale_base - image: nginx:1.19.6 - container_name: skale_nginx + <<: *sk_base + image: nginx:1.20.2 + container_name: sk_nginx network_mode: host depends_on: - watchdog @@ -213,19 +148,20 @@ services: read_only: true advisor: - <<: *skale_base + <<: *sk_base + image: gcr.io/cadvisor/cadvisor-amd64:v0.50.0 container_name: monitor_cadvisor - image: google/cadvisor:latest cpu_shares: 128 network_mode: host volumes: - /:/rootfs:ro - /var/run:/var/run:ro - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro - /dev/disk/:/dev/disk:ro node-exporter: - <<: *skale_base + <<: *sk_base container_name: monitor_node_exporter image: quay.io/prometheus/node-exporter volumes: @@ -240,14 +176,15 @@ services: network_mode: host filebeat: - <<: *skale_base - container_name: skale_filebeat + <<: *sk_base + container_name: sk_filebeat user: root - image: docker.elastic.co/beats/filebeat:7.3.1 + image: elastic/filebeat:9.1.5 network_mode: host environment: FILEBEAT_HOST: ${FILEBEAT_HOST} volumes: - ${SKALE_DIR}/node_data/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro - /var/lib/docker:/var/lib/docker:ro + - /var/log/docker-lvmpy:/var/log/docker-lvmpy:ro - /var/run/skale:/var/run/skale diff --git a/skale-nodes/ansible/roles/update/tasks/config.yaml b/skale-nodes/ansible/roles/update/tasks/config.yaml deleted file mode 100644 index bea159b5..00000000 --- a/skale-nodes/ansible/roles/update/tasks/config.yaml +++ /dev/null @@ -1,17 +0,0 @@ -- name: Sync docker-compose.yml - synchronize: - src: "{{ base_path }}/skale-node/docker-compose-sync.yml" - dest: "{{ base_path }}/.skale/config/docker-compose-sync.yml" - delegate_to: "{{ inventory_hostname }}" - -- name: Sync containers.json - synchronize: - src: "{{ base_path }}/skale-node/containers.json" - dest: "{{ base_path }}/.skale/config/containers.json" - delegate_to: "{{ inventory_hostname }}" - -- name: Sync schain_allocation.yml - synchronize: - src: "{{ base_path }}/skale-node/schain_allocation.yml" - dest: "{{ base_path }}/.skale/config/schain_allocation.yml" - delegate_to: "{{ inventory_hostname }}" diff --git a/skale-nodes/ansible/roles/update/tasks/main.yaml b/skale-nodes/ansible/roles/update/tasks/main.yaml index bb7c5fdd..b93b74ed 100644 --- a/skale-nodes/ansible/roles/update/tasks/main.yaml +++ b/skale-nodes/ansible/roles/update/tasks/main.yaml @@ -1,6 +1,2 @@ -- name: Update configs - import_tasks: config.yaml - when: env is defined and env == "dev" - - name: Skale node update import_tasks: skale_update.yaml diff --git a/skale-nodes/ansible/roles/update/tasks/resource_allocation.yaml b/skale-nodes/ansible/roles/update/tasks/resource_allocation.yaml index b5260fb7..5536a5ab 100644 --- a/skale-nodes/ansible/roles/update/tasks/resource_allocation.yaml +++ b/skale-nodes/ansible/roles/update/tasks/resource_allocation.yaml @@ -1,9 +1,6 @@ - name: Run resource allocation generate shell: cmd: "skale resources-allocation generate {{ base_path }}/init-env --yes" - environment: - LANG: en_US.utf-8 - LC_ALL: en_US.utf-8 tags: - resource_allocation diff --git a/skale-nodes/ansible/roles/update/tasks/skale_update.yaml b/skale-nodes/ansible/roles/update/tasks/skale_update.yaml index 474a785b..553b4bbf 100644 --- a/skale-nodes/ansible/roles/update/tasks/skale_update.yaml +++ b/skale-nodes/ansible/roles/update/tasks/skale_update.yaml @@ -1,19 +1,30 @@ -- name: Run skale node update - shell: - cmd: "skale node update {{ base_path }}/init-env --yes --pull-config all" - environment: - LANG: en_US.utf-8 - LC_ALL: en_US.utf-8 - HOME_DIR: "{{ base_path }}" - when: sync_node is not defined or not sync_node +- name: Update node based on its type tags: skale_update + block: + - name: Determine update command from map + set_fact: + update_cmd: "{{ command_map[lookup_key] | default('') }}" + vars: + passive_suffix: "{{ 'passive' if (passive_node | default(false) | bool) else 'normal' }}" + lookup_key: "{{ node_type }}_{{ passive_suffix }}" + command_map: + fair_boot_normal: "fair boot update {{ base_path }}/init-env --yes" + fair_normal: "fair node update {{ base_path }}/init-env --yes" + fair_passive: "fair passive-node update {{ base_path }}/init-env --yes" + skale_normal: "skale node update {{ base_path }}/init-env --yes --pull-config all --unsafe" + skale_passive: "skale passive-node update {{ base_path }}/init-env --yes --unsafe" -- name: Run skale sync node update - shell: - cmd: "skale sync-node update {{ base_path }}/init-env --yes" - environment: - LANG: en_US.utf-8 - LC_ALL: en_US.utf-8 - HOME_DIR: "{{ base_path }}" - when: sync_node is defined and sync_node - tags: skale_update + - name: Fail if update command could not be determined + fail: + msg: "Could not determine update command for node_type='{{ node_type }}' and passive_node='{{ passive_node | default('not defined') }}'." + when: update_cmd | length == 0 + + - name: Show node update command + debug: + msg: "{{ update_cmd }}" + + - name: Run node update command + shell: + cmd: "{{ update_cmd }}" + environment: + HOME_DIR: "{{ base_path }}" diff --git a/skale-nodes/ansible/roles/validators/tasks/generate.yaml b/skale-nodes/ansible/roles/validators/tasks/generate.yaml deleted file mode 100644 index 1771cffd..00000000 --- a/skale-nodes/ansible/roles/validators/tasks/generate.yaml +++ /dev/null @@ -1,35 +0,0 @@ -- name: Set SM download URL - set_fact: - manager_contracts: "{{ sm_url }}" - when: manager_contracts is undefined - -- name: Crash if no SM ABIs URL provided - fail: - msg: manager_contracts is undefined - when: manager_contracts is undefined - -- name: Download contracts to the local machine - get_url: - url: "{{ manager_contracts }}" - dest: "files/manager.json" - mode: 0644 - validate_certs: false - -- name: Set hosts - set_fact: hosts="{{ hosts|default([]) + [ item.value['ansible_host'] ] }}" - with_dict: "{{ hostvars }}" - tags: save_base_keys - -- name: Execute setup_validator script - script: setup_validator.py - environment: - BASE_DIR: "files" - ETH_AMOUNT: "0.2" - ETH_PRIVATE_KEY: "{{ eth_private_key }}" - ENDPOINT: "{{ endpoint }}" - MIN_DELEGATION_AMOUNT: "0" - COMMISSION_RATE: "1" - NODES_NUMBER: "{{ hosts|length }}" - args: - executable: python3 - tags: setup_validators diff --git a/skale-nodes/ansible/run_anvil.yaml b/skale-nodes/ansible/run_anvil.yaml new file mode 100644 index 00000000..8c4f0776 --- /dev/null +++ b/skale-nodes/ansible/run_anvil.yaml @@ -0,0 +1,6 @@ +- name: Run anvil container on the first node + hosts: "{{ groups['nodes'][0] }}" + roles: + - role: run_anvil + tags: [anvil] + when: anvil is defined and anvil \ No newline at end of file diff --git a/skale-nodes/ansible/set_fair_boot_node_type.yaml b/skale-nodes/ansible/set_fair_boot_node_type.yaml new file mode 100644 index 00000000..2a5a03db --- /dev/null +++ b/skale-nodes/ansible/set_fair_boot_node_type.yaml @@ -0,0 +1,7 @@ +- name: Set node_type to fair_boot + hosts: 127.0.0.1 + connection: local + roles: + - role: set_fair_boot_node_type + tags: + - set_fair_boot diff --git a/skale-nodes/ansible/setup.yaml b/skale-nodes/ansible/setup.yaml index fc3cae03..3967cdc6 100644 --- a/skale-nodes/ansible/setup.yaml +++ b/skale-nodes/ansible/setup.yaml @@ -1,10 +1,22 @@ +- name: Propagate manager_contracts to nodes + hosts: nodes,archive + gather_facts: no + tasks: + - name: Set manager_contracts fact for each node + set_fact: + manager_contracts: "{{ hostvars['localhost']['manager_contracts'] | default(manager_contracts, true) }}" + - name: Crash if no SM contract address/alias provided + fail: + msg: manager_contracts is undefined + when: manager_contracts is undefined + - name: Setup skale node - hosts: nodes + hosts: nodes,archive become: true roles: - role: sync tags: sync - when: env is defined and env == "dev" + when: build_type == "source" - role: skale_cli tags: cli diff --git a/skale-nodes/ansible/skale_node_passive.yaml b/skale-nodes/ansible/skale_node_passive.yaml new file mode 100644 index 00000000..295a9500 --- /dev/null +++ b/skale-nodes/ansible/skale_node_passive.yaml @@ -0,0 +1 @@ +- import_playbook: setup.yaml diff --git a/skale-nodes/ansible/main.yaml b/skale-nodes/ansible/skale_pipeline.yaml similarity index 54% rename from skale-nodes/ansible/main.yaml rename to skale-nodes/ansible/skale_pipeline.yaml index 0a2b2c8e..443cf978 100644 --- a/skale-nodes/ansible/main.yaml +++ b/skale-nodes/ansible/skale_pipeline.yaml @@ -1,9 +1,9 @@ -# - import_playbook: deploy_contracts.yaml -- import_playbook: base.yaml -- import_playbook: sgx.yaml +- import_playbook: run_anvil.yaml +- import_playbook: deploy_contracts.yaml +- import_playbook: sgx_sim.yaml - import_playbook: setup.yaml - import_playbook: validator.yaml - import_playbook: signature.yaml - import_playbook: link_addresses.yaml - import_playbook: register.yaml -- import_playbook: ssl.yaml +- import_playbook: create_chain.yaml diff --git a/skale-nodes/ansible/transfer_funds.yaml b/skale-nodes/ansible/transfer_funds.yaml new file mode 100644 index 00000000..3d2eccfd --- /dev/null +++ b/skale-nodes/ansible/transfer_funds.yaml @@ -0,0 +1,48 @@ +- name: Prepare node information + hosts: nodes + tasks: + - name: Save folder name for nodes addresses info + set_fact: + node_info_dir: "files/node-info" + delegate_to: "127.0.0.1" + + - name: Block for getting wallet info and saving it + block: + - name: Get wallet info + command: + cmd: "{{ node_commands[node_type] }}" + vars: + node_commands: + fair_boot: "sudo fair wallet info -f json" + fair: "sudo fair wallet info -f json" + skale: "sudo skale wallet info -f json" + when: node_type in node_commands + register: wallet_info_cmd + changed_when: false + + - name: Show wallet info command output + debug: + msg: "{{ wallet_info_cmd.stdout }}" + + - name: Get wallet data from json + set_fact: + wallet_data: "{{ wallet_info_cmd.stdout | from_json }}" + + - name: Show wallet info command output + debug: + msg: "{{ wallet_data.address }}" + + - name: Save address to a file on the control node + copy: + content: "{{ wallet_data.address }}" + dest: "{{ node_info_dir }}/{{ inventory_hostname }}" + delegate_to: "127.0.0.1" + +- name: Transfer funds to node address + hosts: 127.0.0.1 + connection: local + tasks: + - name: Transfer funds + import_role: + name: link_addresses + tasks_from: transfer_funds diff --git a/skale-nodes/ansible/update.yaml b/skale-nodes/ansible/update.yaml index 1d68bb26..9d1a21b2 100644 --- a/skale-nodes/ansible/update.yaml +++ b/skale-nodes/ansible/update.yaml @@ -1,9 +1,9 @@ - name: Update skale node - hosts: nodes + hosts: nodes,archive become: true roles: - role: sync - when: env is defined and env == "dev" + when: build_type == "source" tags: sync - role: config diff --git a/skale-nodes/ansible/validator.yaml b/skale-nodes/ansible/validator.yaml index 4d630e04..617a007d 100644 --- a/skale-nodes/ansible/validator.yaml +++ b/skale-nodes/ansible/validator.yaml @@ -1,8 +1,7 @@ -- name: Setup validators +- name: Setup validator hosts: 127.0.0.1 connection: local - tasks: - - name: Generate and configure validator - import_role: - name: validators - tasks_from: generate + roles: + - role: setup_validator + tags: + - setup_validator