diff --git a/Makefile b/Makefile index 58b79e17f..8165fa73f 100644 --- a/Makefile +++ b/Makefile @@ -1092,6 +1092,20 @@ ansible_batcher_deploy: ## Deploy the Batcher. Parameters: INVENTORY, KEYSTORE -i $(INVENTORY) \ -e "keystore_path=$(KEYSTORE)" +ansible_aggregator_create_env: ## Create empty variables files for the Aggregator deploy + @cp -n infra/ansible/playbooks/ini/config-aggregator.ini.example infra/ansible/playbooks/ini/config-aggregator.ini + @echo "Config files for the Aggregator created in infra/ansible/playbooks/ini" + @echo "Please complete the values and run make ansible_aggregator_deploy" + +ansible_aggregator_deploy: ## Deploy the Operator. Parameters: INVENTORY + @if [ -z "$(INVENTORY)" ] || [ -z "$(ECDSA_KEYSTORE)" ] || [ -z "$(BLS_KEYSTORE)" ]; then \ + echo "Error: INVENTORY, ECDSA_KEYSTORE, BLS_KEYSTORE must be set."; \ + exit 1; \ + fi + @ansible-playbook infra/ansible/playbooks/aggregator.yaml \ + -i $(INVENTORY) \ + -e "ecdsa_keystore_path=$(ECDSA_KEYSTORE)" \ + -e "bls_keystore_path=$(BLS_KEYSTORE)" ansible_operator_create_env: ## Create empty variables files for the Operator deploy @cp -n infra/ansible/playbooks/ini/config-operator.ini.example infra/ansible/playbooks/ini/config-operator.ini diff --git a/infra/ansible/README.md b/infra/ansible/README.md index b3e59ac01..806b3fe90 100644 --- a/infra/ansible/README.md +++ b/infra/ansible/README.md @@ -70,7 +70,6 @@ make ansible_batcher_deploy INVENTORY= KEYSTORE= [!CAUTION] > To register the Operator in Aligned successfully, you need to have been whitelisted by the Aligned team previously. - To deploy the Operator you need to set some variables and then run the Operator playbook. Create the variables files: @@ -86,18 +85,17 @@ This will create the following files in `infra/ansible/playbooks/ini`: The `config-register-operator.ini` contains the variables to register the Operator in EigenLayer: -| Variable | Description | Stage | Testnet | Mainnet | -|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|---------------------------------------| -| address | ECDSA address of the Operator | | | | -| metadata_url | Operator Metadata. You can create one following this [guide](https://docs.eigenlayer.xyz/eigenlayer/operator-guides/operator-installation#operator-configuration-and-registration) | | | | -| el_delegation_manager_address | Delegation Manager Address | `0xA44151489861Fe9e3055d95adC98FbD462B948e7` | `0xA44151489861Fe9e3055d95adC98FbD462B948e7` | TBD | -| eth_rpc_url | HTTP RPC url | `https://ethereum-holesky-rpc.publicnode.com` | `https://ethereum-holesky-rpc.publicnode.com` | `https://ethereum-rpc.publicnode.com` | -| private_key_store_path | Path to the ECDSA keystore in the Operator host | `/home/app/.keystores/operator.ecdsa` | `/home/app/.keystores/operator.ecdsa` | `/home/app/.keystores/operator.ecdsa` | -| private_key_store_password | Password of the ECDSA keystore | | | | -| chain_id | Chain ID | 17000 | 17000 | 1 | -| weth_address | Address of wETH token | [0x94373a4919B3240D86eA41593D5eBa789FEF3848](https://holesky.etherscan.io/address/0x94373a4919B3240D86eA41593D5eBa789FEF3848) | [0x94373a4919B3240D86eA41593D5eBa789FEF3848](https://holesky.etherscan.io/address/0x94373a4919B3240D86eA41593D5eBa789FEF3848) | TBD | -| weth_strategy_address | Address of wETH token strategy | [0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9](https://holesky.eigenlayer.xyz/restake/WETH) | [0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9](https://holesky.eigenlayer.xyz/restake/WETH) | TBD | - +| Variable | Description | Stage | Testnet | Mainnet | +|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------| +| address | ECDSA address of the Operator | | | | +| metadata_url | Operator Metadata. You can create one following this [guide](https://docs.eigenlayer.xyz/eigenlayer/operator-guides/operator-installation#operator-configuration-and-registration) | | | | +| el_delegation_manager_address | Delegation Manager Address | `0xA44151489861Fe9e3055d95adC98FbD462B948e7` | `0xA44151489861Fe9e3055d95adC98FbD462B948e7` | TBD | +| eth_rpc_url | HTTP RPC url | `https://ethereum-holesky-rpc.publicnode.com` | `https://ethereum-holesky-rpc.publicnode.com` | `https://ethereum-rpc.publicnode.com` | +| private_key_store_path | Path to the ECDSA keystore in the Operator host | `/home/app/.keystores/operator.ecdsa` | `/home/app/.keystores/operator.ecdsa` | `/home/app/.keystores/operator.ecdsa` | +| private_key_store_password | Password of the ECDSA keystore | | | | +| chain_id | Chain ID | 17000 | 17000 | 1 | +| weth_address | Address of wETH token | [0x94373a4919B3240D86eA41593D5eBa789FEF3848](https://holesky.etherscan.io/address/0x94373a4919B3240D86eA41593D5eBa789FEF3848) | [0x94373a4919B3240D86eA41593D5eBa789FEF3848](https://holesky.etherscan.io/address/0x94373a4919B3240D86eA41593D5eBa789FEF3848) | TBD | +| weth_strategy_address | Address of wETH token strategy | [0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9](https://holesky.eigenlayer.xyz/restake/WETH) | [0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9](https://holesky.eigenlayer.xyz/restake/WETH) | TBD | The `config-operator.ini` contains the variables to run the Operator in Aligned: @@ -121,17 +119,53 @@ The `config-operator.ini` contains the variables to run the Operator in Aligned: | metrics_ip_port_address | Where to expose prometheus metrics if enabled | `localhost:9092` | `localhost:9092` | `localhost:9092` | | last_processed_batch_filepath | Where to store the last processed batch for system recovery | `/home/app/operator.last_processed_batch.json` | `/home/app/operator.last_processed_batch.json` | `/home/app/operator.last_processed_batch.json` | - Deploy the Operator: ```shell make ansible_operator_deploy INVENTORY= ECDSA_KEYSTORE= BLS_KEYSTORE= ``` +## Aggregator + +> [!IMPORTANT] +> You need to have previously created an ECDSA keystore with at least 1ETH and a BLS keystore. +> You can create keystore following this [guide](#How-to-Create-Keystores) + +To deploy the Aggregator you need to set some variables and then run the Aggregator playbook + +This will create the following file in `infra/ansible/playbooks/ini`: + +```shell +make ansible_aggregator_create_env +``` +- `config-aggregator.ini` + +The `config-aggregator.ini` contains the variables to run the Operator in Aligned: + +| Variable | Description | Stage | Testnet | Mainnet | +|-------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------| +| aligned_layer_deployment_config_file_path | JSON with Aligned contracts addresses | `/home/app/repos/aggregator/aligned_layer/contracts/script/output/holesky/alignedlayer_deployment_output.stage.json` | `/home/app/repos/aggregator/aligned_layer/contracts/script/output/holesky/alignedlayer_deployment_output.json` | TBD | +| eigen_layer_deployment_config_file_path | JSON with EigenLayer contracts addresses | `/home/app/repos/aggregator/aligned_layer/contracts/script/output/holesky/eigenlayer_deployment_output.json` | `/home/app/repos/aggregator/aligned_layer/contracts/script/output/holesky/eigenlayer_deployment_output.json` | TBD | +| eth_rpc_url | HTTP RPC url | | | | +| eth_rpc_url_fallback | HTTP RPC fallback url. Must be different than `eth_rpc_url` | `https://ethereum-holesky-rpc.publicnode.com` | `https://ethereum-holesky-rpc.publicnode.com` | `https://ethereum-rpc.publicnode.com` | +| eth_ws_url | WS RPC url | | your_rpc_ws_provider> | | +| eth_ws_url_fallback | WS RPC fallback url. Must be different than `eth_ws_rpc_url` | `wss://ethereum-holesky-rpc.publicnode.com` | `wss://ethereum-holesky-rpc.publicnode.com` | `wss://ethereum-rpc.publicnode.com` | +| ecdsa_private_key_store_path | Path to the ECDSA keystore in the Operator host | `/home/app/.keystores/aggregator.ecdsa` | `/home/app/.keystores/aggregator.ecdsa` | `/home/app/.keystores/operator.ecdsa` | +| ecdsa_private_key_store_password | Password of the ECDSA keystore | | | | +| bls_private_key_store_path | Path to the BLS keystore in the Operator host | `/home/app/.keystores/aggregator.bls` | `/home/app/.keystores/aggregator.bls` | `/home/app/.keystores/operator.bls` | +| bls_private_key_store_password | Password of the BLS keystore | | | | +| enable_metrics | Expose or not prometheus metrics | `true` | `true` | `true` | +| metrics_ip_port_address | Where to expose prometheus metrics if enabled | `localhost:9092` | `localhost:9092` | `localhost:9092` | +| telemetry_ip_port_address | Where to send telemetry traces | `100.73.98.8:4001` | `100.91.67.33:4001` | TBD | + +Deploy the Aggregator: + +```shell +make ansible_aggregator_deploy INVENTORY= ECDSA_KEYSTORE= BLS_KEYSTORE= +``` > [!Note] > ECDSA_KEYSTORE and BLS_KEYSTORE are the paths of the keystores in your machine. - # How to Create Keystores ## Create ECDSA Keystore @@ -196,7 +230,6 @@ Ethereum Address: 0x... Refer to this link for more details about keystore creation https://docs.eigenlayer.xyz/eigenlayer/operator-guides/operator-installation#create-keys - ## Create BLS Keystore Make sure you have installed: @@ -227,10 +260,9 @@ BLS Private Key (Hex): And then, ``` - Key location: $HOME/.eigenlayer/operator_keys/.bls.key.json Public Key: E([...,...]) - ``` Refer to this link for more details about keystore creation https://docs.eigenlayer.xyz/eigenlayer/operator-guides/operator-installation#create-keys + diff --git a/infra/ansible/playbooks/aggregator.yaml b/infra/ansible/playbooks/aggregator.yaml new file mode 100644 index 000000000..599f6e76e --- /dev/null +++ b/infra/ansible/playbooks/aggregator.yaml @@ -0,0 +1,116 @@ +- name: Run setup playbook + ansible.builtin.import_playbook: setup.yaml + vars: + host: aggregator + +- name: Run go playbook + ansible.builtin.import_playbook: go.yaml + vars: + host: aggregator + +- hosts: aggregator + vars: + service: "aggregator" + + tasks: + - name: Update apt and install required system packages + become: true + apt: + pkg: + - pkg-config + - libssl-dev + state: latest + update_cache: true + vars: + ansible_ssh_user: "{{ admin_user }}" + + - name: Create directories for each service if do not exist + file: + path: /home/{{ ansible_user }}/repos/{{ service }} + state: directory + mode: '0755' + owner: '{{ ansible_user }}' + group: '{{ ansible_user }}' + loop: + - aggregator + + - name: Clone Aligned repository + git: + repo: https://github.com/yetanotherco/aligned_layer.git + dest: /home/{{ ansible_user }}/repos/{{ service }}/aligned_layer + version: v0.10.2 + loop: + - aggregator + + - name: Set permissions for cloned repository + file: + path: /home/{{ ansible_user }}/repos/{{ service }}/aligned_layer + mode: '0755' + owner: '{{ ansible_user }}' + group: '{{ ansible_user }}' + recurse: yes + + - name: Copy ECDSA keystore to server + copy: + src: '{{ ecdsa_keystore_path }}' + dest: /home/{{ ansible_user }}/.keystores/aggregator.ecdsa + owner: '{{ ansible_user }}' + group: '{{ ansible_user }}' + + - name: Copy BLS keystore to server + copy: + src: '{{ bls_keystore_path }}' + dest: /home/{{ ansible_user }}/.keystores/aggregator.bls + owner: '{{ ansible_user }}' + group: '{{ ansible_user }}' + + - name: Build aggregator + shell: + chdir: /home/{{ ansible_user }}/repos/aggregator/aligned_layer/ + cmd: /usr/local/go/bin/go build -o /home/{{ ansible_user }}/repos/aggregator/aligned_layer/build/aligned-aggregator /home/{{ ansible_user }}/repos/aggregator/aligned_layer/aggregator/cmd/main.go + + - name: Upload config file for aggregator + template: + src: config-files/config-aggregator.yaml.j2 + dest: "/home/{{ ansible_user }}/config/config-aggregator.yaml" + vars: + aligned_layer_deployment_config_file_path: "{{ lookup('ini', 'aligned_layer_deployment_config_file_path', file='ini/config-aggregator.ini') }}" + eigen_layer_deployment_config_file_path: "{{ lookup('ini', 'eigen_layer_deployment_config_file_path', file='ini/config-aggregator.ini') }}" + eth_rpc_url: "{{ lookup('ini', 'eth_rpc_url', file='ini/config-aggregator.ini') }}" + eth_rpc_url_fallback: "{{ lookup('ini', 'eth_rpc_url_fallback', file='ini/config-aggregator.ini') }}" + eth_ws_url: "{{ lookup('ini', 'eth_ws_url', file='ini/config-aggregator.ini') }}" + eth_ws_url_fallback: "{{ lookup('ini', 'eth_ws_url_fallback', file='ini/config-aggregator.ini') }}" + ecdsa_private_key_store_path: "{{ lookup('ini', 'ecdsa_private_key_store_path', file='ini/config-aggregator.ini') }}" + ecdsa_private_key_store_password: "{{ lookup('ini', 'ecdsa_private_key_store_password', file='ini/config-aggregator.ini') }}" + bls_private_key_store_path: "{{ lookup('ini', 'bls_private_key_store_path', file='ini/config-aggregator.ini') }}" + bls_private_key_store_password: "{{ lookup('ini', 'bls_private_key_store_password', file='ini/config-aggregator.ini') }}" + enable_metrics: "{{ lookup('ini', 'enable_metrics', file='ini/config-aggregator.ini') }}" + metrics_ip_port_address: "{{ lookup('ini', 'metrics_ip_port_address', file='ini/config-aggregator.ini') }}" + telemetry_ip_port_address: "{{ lookup('ini', 'telemetry_ip_port_address', file='ini/config-aggregator.ini') }}" + + - name: Allow access to tcp port 8090 + become: true + ufw: + rule: allow + port: 8090 + proto: tcp + vars: + ansible_ssh_user: "{{ admin_user }}" + + - name: Create systemd services directory + file: + path: "/home/{{ ansible_user }}/.config/systemd/user/" + state: directory + + - name: Add service to systemd + template: + src: services/aggregator.service.j2 + dest: "/home/{{ ansible_user }}/.config/systemd/user/aggregator.service" + force: no + + - name: Start aggregator service + systemd_service: + name: aggregator + state: started + enabled: true + scope: user diff --git a/infra/ansible/playbooks/batcher.yaml b/infra/ansible/playbooks/batcher.yaml index 238a6bf2c..2a1c1cb71 100644 --- a/infra/ansible/playbooks/batcher.yaml +++ b/infra/ansible/playbooks/batcher.yaml @@ -97,7 +97,6 @@ telemetry_ip_port_address: "{{ lookup('ini', 'telemetry_ip_port_address', file='ini/config-batcher.ini') }}" batcher_replacement_private_key: "{{ lookup('ini', 'batcher_replacement_private_key', file='ini/config-batcher.ini') }}" - - name: Upload env file for batcher template: src: config-files/env-batcher.j2 diff --git a/infra/ansible/playbooks/ini/config-aggregator.ini.example b/infra/ansible/playbooks/ini/config-aggregator.ini.example new file mode 100644 index 000000000..6c01c1c1b --- /dev/null +++ b/infra/ansible/playbooks/ini/config-aggregator.ini.example @@ -0,0 +1,14 @@ +[global] +aligned_layer_deployment_config_file_path= +eigen_layer_deployment_config_file_path= +eth_rpc_url= +eth_rpc_url_fallback= +eth_ws_url= +eth_ws_url_fallback= +ecdsa_private_key_store_path= +ecdsa_private_key_store_password= +bls_private_key_store_path= +bls_private_key_store_password= +enable_metrics= +metrics_ip_port_address= +telemetry_ip_port_address= diff --git a/infra/ansible/playbooks/templates/config-files/config-aggregator.yaml.j2 b/infra/ansible/playbooks/templates/config-files/config-aggregator.yaml.j2 new file mode 100644 index 000000000..49bb8a3c4 --- /dev/null +++ b/infra/ansible/playbooks/templates/config-files/config-aggregator.yaml.j2 @@ -0,0 +1,32 @@ +# Common variables for all the services +# 'production' only prints info and above. 'development' also prints debug +environment: "production" +aligned_layer_deployment_config_file_path: "{{ aligned_layer_deployment_config_file_path }}" +eigen_layer_deployment_config_file_path: "{{ eigen_layer_deployment_config_file_path }}" +eth_rpc_url: "{{ eth_rpc_url }}" +eth_rpc_url_fallback: "{{ eth_rpc_url_fallback }}" +eth_ws_url: "{{ eth_ws_url }}" +eth_ws_url_fallback: "{{ eth_ws_url_fallback }}" +eigen_metrics_ip_port_address: "localhost:9090" + +## ECDSA Configurations +ecdsa: + private_key_store_path: "{{ ecdsa_private_key_store_path }}" + private_key_store_password: "{{ ecdsa_private_key_store_password }}" + +## BLS Configurations +bls: + private_key_store_path: "{{ bls_private_key_store_path }}" + private_key_store_password: "{{ bls_private_key_store_password }}" + +## Aggregator Configurations +aggregator: + server_ip_port_address: localhost:8090 + bls_public_key_compendium_address: + avs_service_manager_address: + enable_metrics: {{ enable_metrics }} + metrics_ip_port_address: "{{ metrics_ip_port_address }}" + telemetry_ip_port_address: "{{ telemetry_ip_port_address }}" + garbage_collector_period: 2m #The period of the GC process. Suggested value for Prod: '168h' (7 days) + garbage_collector_tasks_age: 20 #The age of tasks that will be removed by the GC, in blocks. Suggested value for prod: '216000' (30 days) + garbage_collector_tasks_interval: 10 #The interval of queried blocks to get an old batch. Suggested value for prod: '900' (3 hours) diff --git a/infra/ansible/playbooks/templates/services/aggregator.service.j2 b/infra/ansible/playbooks/templates/services/aggregator.service.j2 new file mode 100644 index 000000000..eacf82989 --- /dev/null +++ b/infra/ansible/playbooks/templates/services/aggregator.service.j2 @@ -0,0 +1,15 @@ +[Unit] +Description=Aggregator +After=network.target + +[Service] +Type=simple +WorkingDirectory=/home/{{ ansible_user }}/repos/aggregator/aligned_layer/aggregator +ExecStart=/home/{{ ansible_user }}/repos/aggregator/aligned_layer/build/aligned-aggregator --config /home/{{ ansible_user }}/config/config-aggregator.yaml +Restart=always +RestartSec=1 +StartLimitBurst=100 +LimitNOFILE=100000 + +[Install] +WantedBy=multi-user.target diff --git a/infra/ansible/stage_inventory.yaml b/infra/ansible/stage_inventory.yaml index fb8085653..2a4cc8d38 100644 --- a/infra/ansible/stage_inventory.yaml +++ b/infra/ansible/stage_inventory.yaml @@ -1,9 +1,9 @@ aggregator: hosts: aligned-holesky-aggregator-1: - ansible_host: aligned-ansible - ansible_user: admin - app_user: app + ansible_host: aligned-holesky-stage-1-aggregator + admin_user: admin + ansible_user: app ansible_python_interpreter: /usr/bin/python3 batcher: hosts: