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
[](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