From 5e762efd276be514c6d678a8fd836802e31dd974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Tubal=20P=C3=A1ez=20Ruiz?= Date: Thu, 31 Oct 2024 16:36:18 +0100 Subject: [PATCH] feat: add EigenLayer Onchain Exporter (#3) * feat: Add initial version of code * chore: Add requirements.txt * feat: Add Dockerfile * ci: Add workflow to build and push Docker image * feat: Serve original requested_at instead of time_difference * feat: Sort blobs by requested_at * feat: Stop updating redundant metrics * fix: Cast FETCH_INTERVAL to int * feat: Add docker-compose for testing purposes * feat: implement eigenlayer onchain exporter * chore: add gh cli to the devcontainer * refactor: remove python files * fix: Rename module * doc: Update root command short description * fix: Update README.md Co-authored-by: Miguel Tenorio <46824157+AntiD2ta@users.noreply.github.com> * doc: Add Labels section * fix: Update README references * fix: Update command usage * feat: Update CI/CD workflow * fix: Prometheus metric labels * refactor: Log errors instead of stop the exporter * feat: Add eigenda_exporter_up metric * refactor: Remove RPC mutex * feat: Use backoff for RPC calls * feat: Add docker compose containers' names * refactor: Configure log level as string * refactor: Update config path default value * feat: Update Viper configuration * refactor: Update exprters shutting down process * fix: Init the EigenDA exporter up metric at the creation time * fix: Update docker compose volume * doc: Update README * refactor: Update confirmBatchInput TODO comment * feat: Check RPC ChainID * fix: Log Prometheus server error * fix: Typo * chore: Add checks and linters * fix: Ethereum Mainnet chain id * refactor: Update project structure and graceful exit * test: Init E2E tests * test: Add test cases --------- Co-authored-by: AntiD2ta Co-authored-by: Miguel Tenorio <46824157+AntiD2ta@users.noreply.github.com> --- .config/dictionary.txt | 25 + .config/markdownlint.yaml | 1 + .devcontainer/devcontainer.json | 38 +- .github/workflows/golangci-lint.yml | 20 + .github/workflows/publish-docker.yml | 60 - .github/workflows/publish-image.yml | 56 + .gitignore | 182 +-- .pre-commit-config.yaml | 34 + Dockerfile | 35 +- Makefile | 26 +- README.md | 149 ++- api_client.py | 25 - cmd/eoe/main.go | 27 + cspell.config.yaml | 25 + docker-compose.yml | 16 +- e2e/e2e.go | 56 + e2e/eoe/e2e.go | 65 + e2e/eoe/eigenda_test.go | 156 +++ e2e/eoe/run_test.go | 275 ++++ e2e/eoe/utils.go | 37 + e2e/utils.go | 55 + go.mod | 67 + go.sum | 236 ++++ img/eoe-diagram.png | Bin 0 -> 222618 bytes internal/avs/eigenda/abi.go | 70 + .../abi/holesky-bls-apk-registry.json | 619 +++++++++ .../abi/holesky-service-manager.json | 1126 +++++++++++++++++ .../abi/mainnet-bls-apk-registry.json | 619 +++++++++ .../abi/mainnet-service-manager.json | 1019 +++++++++++++++ .../avs/eigenda/contracts/blsApkRegistry.go | 75 ++ .../avs/eigenda/contracts/serviceManager.go | 74 ++ internal/avs/eigenda/eigenda.go | 369 ++++++ internal/avs/eigenda/prometheus.go | 34 + internal/avsexporter/exporter.go | 12 + internal/cli/root.go | 16 + internal/cli/run.go | 119 ++ internal/common/networks.go | 27 + internal/config/config.go | 43 + internal/config/viper.go | 32 + internal/prometheus/prometheus.go | 13 + internal/rpc/eth-evm.go | 111 ++ main.py | 42 - metrics.py | 40 - prometheus.yml | 4 +- requirements.txt | 6 - 45 files changed, 5714 insertions(+), 422 deletions(-) create mode 100644 .config/dictionary.txt create mode 100644 .config/markdownlint.yaml create mode 100644 .github/workflows/golangci-lint.yml delete mode 100644 .github/workflows/publish-docker.yml create mode 100644 .github/workflows/publish-image.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 api_client.py create mode 100644 cmd/eoe/main.go create mode 100644 cspell.config.yaml create mode 100644 e2e/e2e.go create mode 100644 e2e/eoe/e2e.go create mode 100644 e2e/eoe/eigenda_test.go create mode 100644 e2e/eoe/run_test.go create mode 100644 e2e/eoe/utils.go create mode 100644 e2e/utils.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 img/eoe-diagram.png create mode 100644 internal/avs/eigenda/abi.go create mode 100644 internal/avs/eigenda/contracts/abi/holesky-bls-apk-registry.json create mode 100644 internal/avs/eigenda/contracts/abi/holesky-service-manager.json create mode 100644 internal/avs/eigenda/contracts/abi/mainnet-bls-apk-registry.json create mode 100644 internal/avs/eigenda/contracts/abi/mainnet-service-manager.json create mode 100644 internal/avs/eigenda/contracts/blsApkRegistry.go create mode 100644 internal/avs/eigenda/contracts/serviceManager.go create mode 100644 internal/avs/eigenda/eigenda.go create mode 100644 internal/avs/eigenda/prometheus.go create mode 100644 internal/avsexporter/exporter.go create mode 100644 internal/cli/root.go create mode 100644 internal/cli/run.go create mode 100644 internal/common/networks.go create mode 100644 internal/config/config.go create mode 100644 internal/config/viper.go create mode 100644 internal/prometheus/prometheus.go create mode 100644 internal/rpc/eth-evm.go delete mode 100644 main.py delete mode 100644 metrics.py delete mode 100644 requirements.txt diff --git a/.config/dictionary.txt b/.config/dictionary.txt new file mode 100644 index 0000000..8ab7b1d --- /dev/null +++ b/.config/dictionary.txt @@ -0,0 +1,25 @@ +Apks +avsexporter +Buildx +cenkalti +CODEOWNERS +codespell +Confirmer +devcontainer +Eigen +eigenda +eigenlayer +ethclient +ethcommon +golangci +Holeksy +holesky +IBLS +markdownlint +Nethermind +promauto +promhttp +Pubkeys +Rpcs +stretchr +twinstake diff --git a/.config/markdownlint.yaml b/.config/markdownlint.yaml new file mode 100644 index 0000000..9ac2f57 --- /dev/null +++ b/.config/markdownlint.yaml @@ -0,0 +1 @@ +line_length: false \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 978c07f..0146e6b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,39 +3,29 @@ "build": { "dockerfile": "Dockerfile" }, - // 👇 Features to add to the Dev Container. More info: https://containers.dev/implementors/features. - // "features": {}, - + "features": { + "ghcr.io/devcontainers/features/go:1": { + "version": "1.23.1" + }, + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/gvatsal60/dev-container-features/pre-commit:1": {} + }, // 👇 Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], - // 👇 Use 'postCreateCommand' to run commands after the container is created. // "postCreateCommand": "sudo apt install -y graphviz", - // 👇 Configure tool-specific properties. "customizations": { - "vscode": { - "extensions":[ - "ms-python.python", - "njpwerner.autodocstring", - "ms-python.vscode-pylance", - "amazonwebservices.aws-toolkit-vscode", + "vscode": { + "extensions": [ + "golang.go", + "Gruntfuggly.todo-tree", "streetsidesoftware.code-spell-checker", - "GitHub.copilot", - "ms-python.isort", - "redhat.vscode-yaml", - "hashicorp.terraform", - "yzhang.markdown-all-in-one", - "DavidAnson.vscode-markdownlint", - "eamodio.gitlens", - "github.vscode-github-actions" + "DavidAnson.vscode-markdownlint" ] - } - }, - "features": { } - + } // 👇 Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "root" -} +} \ No newline at end of file diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000..96d56f8 --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,20 @@ +name: golangci-lint +on: + pull_request: + +permissions: + contents: read + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: stable + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: v1.61.0 diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml deleted file mode 100644 index 9d7669a..0000000 --- a/.github/workflows/publish-docker.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Publish Docker image - -on: - push: - branches: [main] - - workflow_dispatch: - inputs: - image-name: - description: Image name - required: true - default: eigenda-blob-scraper - tag: - description: Image tag - required: true - dockerfile: - description: Dockerfile - required: true - default: Dockerfile - fetch-interval: - description: Fetch interval in seconds, default 1 minute - required: false - default: 60 - api-url: - description: Endpoint to get the blob json data from - required: false - default: https://blobs-goerli.eigenda.xyz/api/trpc/blobs.getBlobs - -jobs: - publish-docker: - name: Publish to Docker Hub - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: Build and push image to Docker Hub (staging) - run: | - branch=$(echo "${{ github.ref }}" | sed -e "s/refs\/heads\///g") - original_tag=${{ github.event.inputs.tag || '$branch' }} - tag=$(echo "$original_tag" | sed 's/\//-/g') # replace '/' with '-' in tag na - echo "Building image with tag $tag" - - docker buildx build --platform=linux/amd64,linux/arm64 \ - -f ${{ github.event.inputs.dockerfile || 'Dockerfile' }} \ - -t "nethermind/${{ github.event.inputs.image-name }}:$tag" \ - . --push - - docker buildx build --platform=linux/amd64,linux/arm64 \ - -f ${{ github.event.inputs.dockerfile || 'Dockerfile' }} \ - -t "nethermind/${{ github.event.inputs.image-name }}:latest" \ - . --push \ No newline at end of file diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml new file mode 100644 index 0000000..ae1d40e --- /dev/null +++ b/.github/workflows/publish-image.yml @@ -0,0 +1,56 @@ +name: CI/CD pipeline + +env: + DOCKER_REGISTRY: nethermind.jfrog.io + + REPO_DEV: angkor-oci-local-dev + REPO_STAGING: angkor-oci-local-staging + REPO_PROD: angkor-oci-local-prod + IMAGE_NAME: eigenlayer-onchain-exporter + + +on: + push: + branches: [main] + workflow_dispatch: + +permissions: + id-token: write + contents: write + +jobs: + build_docker_image: + runs-on: ubuntu-latest + outputs: + DOCKER_IMAGE_NAME: ${{ env.IMAGE_NAME }} + DOCKER_IMAGE_TAG: ${{ steps.set_tag.outputs.DOCKER_IMAGE_TAG }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Define image tag + id: set_tag + run: | + export DOCKER_IMAGE_TAG=$(git describe --tags) + # This one is to be able to use the image tag in the next steps in this job + echo "DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG" >> $GITHUB_ENV + # This one is to be able to use the image tag in the next jobs + echo "DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to registry + run: | + docker login ${{ env.DOCKER_REGISTRY }} -u ${{ secrets.ARTIFACTORY_ANGKOR_USERNAME }} -p ${{ secrets.ARTIFACTORY_ANGKOR_TOKEN_CONTRIBUTOR }} + - name: Build and Push + uses: docker/build-push-action@v6 + with: + context: . + platforms: "linux/amd64" + push: true + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.REPO_DEV }}/${{ env.IMAGE_NAME }}:latest diff --git a/.gitignore b/.gitignore index 1c18fbf..67cbe1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,162 +1,52 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll *.so +*.dylib -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy +# Test binary, built with `go test -c` +*.test -# Sphinx documentation -docs/_build/ +# Output of the go coverage tool, specifically when used with LiteIDE +*.out -# PyBuilder -.pybuilder/ -target/ +# Dependency directories (remove the comment below to include it) +# vendor/ -# Jupyter Notebook -.ipynb_checkpoints +# Go workspace file +go.work -# IPython -profile_default/ -ipython_config.py +# IDE-specific files +.idea/ +.vscode/ -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version +# OS-specific files +.DS_Store +Thumbs.db -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py +# Log files +*.log -# Environments +# Environment variables file .env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json +# Build output directory +/build/ -# Pyre type checker -.pyre/ +# Temporary files +/tmp/ +*.tmp -# pytype static type analyzer -.pytype/ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a -# Cython debug symbols -cython_debug/ +# Debug files +debug -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +# Project-specific ignore patterns (if any) +# Add any other patterns specific to your project here -resources/* \ No newline at end of file +eoe-config.yml +bin/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b271e29 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,34 @@ +--- +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +exclude: > + (?x)^( + .devcontainer/devcontainer.json| + .vscode/extensions.json| + .vscode/settings.json| + )$ +repos: + - repo: https://github.com/streetsidesoftware/cspell-cli + rev: v8.7.0 + hooks: + - id: cspell + exclude: > + (?x)^( + \.github/CODEOWNERS| + \.github/workflows/.*\.yml| + \.gitignore| + \.pre-commit-config\.yaml| + )$ + # entry: codespell --relative + # args: [--relative, --no-progress, --no-summary] + name: Spell check with cspell + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.41.0 + hooks: + - id: markdownlint + args: + - "--config=.config/markdownlint.yaml" + - repo: https://github.com/golangci/golangci-lint + rev: v1.61.0 + hooks: + - id: golangci-lint diff --git a/Dockerfile b/Dockerfile index 07a8b1c..3eea862 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,28 @@ -# Use an official Python runtime as a parent image -FROM python:3.9-slim -# Set the working directory in the container -WORKDIR /usr/src/app +# Build stage +FROM golang:1.23-alpine AS builder -# Copy the current directory contents into the container at /usr/src/app +WORKDIR /app + +# Copy go mod and sum files +COPY go.mod go.sum ./ + +# Download all dependencies +RUN go mod download + +# Copy the source code COPY . . -# Install any needed packages specified in requirements.txt -RUN pip install --no-cache-dir -r requirements.txt +# Build the application +RUN CGO_ENABLED=0 GOOS=linux go build -o eoe cmd/eoe/main.go + +# Final stage +FROM alpine:latest -# Make port 9600 available to the world outside this container -EXPOSE 9600 +WORKDIR /root/ -# Define environment variable -ENV FETCH_INTERVAL=60 -ENV API_URL=https://blobs-goerli.eigenda.xyz/api/trpc/blobs.getBlobs +# Copy the binary from builder +COPY --from=builder /app/eoe . -# Run main.py when the container launches -CMD ["python", "./main.py"] +# Command to run the executable +CMD ["./eoe", "run"] diff --git a/Makefile b/Makefile index 3b4a5fa..a1b528a 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,14 @@ DEFAULT_GOAL := help .PHONY: env -pyenv: ## Activate pyenv - @source venv/bin/activate +run: + go run cmd/eoe/main.go run -upgrade-pip: ## Upgrade pip version - @pip3 install --upgrade pip +build: + go build -o ./bin/eoe cmd/eoe/main.go -install-deps-locally: upgrade-pip ## Install dependencies in project folder - @pip3 install -r requirements.txt -t . +build-docker: + docker build -t eoe . -install-deps: upgrade-pip ## Install dependencies - @pip3 install -r requirements.txt - -freeze: ## Freeze dependencies - @rm -f requirements.txt - @pip3 freeze > requirements.txt - -test: ## Run unit tests - @python -m unittest discover - -help: ## Show this help - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' \ No newline at end of file +pre-commit: + pre-commit run --all-files diff --git a/README.md b/README.md index 6485e07..114b8b4 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,137 @@ -# eigenda-blob-scraper +# EigenLayer AVS OnChain Exporter -A Python application that scrapes the Eigenda website for the latest blob data and exposes it via Prometheus metrics. +EigenLayer AVS OnChain Exporter (EOE) is a tool designed to export on-chain data from various Actively Validator Set (AVS) services within the EigenLayer ecosystem as Prometheus metrics. -## Project Description +## Features -The application gets the blob data in a json form from an EigenDA public endpoint and transforms it into Prometheus metrics every `FETCH_INTERVAL` seconds. The metrics are then exposed via a Prometheus server at port 9600. +### Supported AVSs and Prometheus metrics -The application is deployed via Docker image to DockerHub. The image can be found here: https://hub.docker.com/repository/docker/nethermind/eigenda-blob-scraper. +#### EigenDA -## Environment Variables +For EigenDA, Holeksy and Mainnet are supported and exposes the following metrics: -The application uses the following environment variables: +- `eoe_eigenda_exporter_latest_block{network=""}`: Latest block number that the EigenDA exporter of the specific network has processed. +- `eoe_eigenda_onchain_batches_total{network=""}`: Total number of onchain batches that the EigenDA exporter of the specific network has processed. This is a counter that increments with each block and resets to 0 if the exporter is restarted. +- `eoe_eigenda_onchain_batches{operator="", network="", status=""}`: Number of onchain batches missed by an operator in the specific network. For now the only status is `missed`. +- `eoe_eigenda_onchain_quorum_status{operator="", network="", quorum=""}`: The status of the operator in the specific network and quorum. The value could be 1 if the operator is in quorum, 0 if the operator is not in quorum. +- `eoe_eigenda_exporter_up{avsEnv=""}`: The status of the exporter. The value could be 1 if the exporter is running, 0 if the exporter is not running. -| Variable | Description | Default Value | -| --- | --- | --- | -| API_URL | Endpoint to get the blob json data from | https://blobs-goerli.eigenda.xyz/api/trpc/blobs.getBlobs | -| FETCH_INTERVAL | Fetch interval in seconds | 60 | +> If the exporter might track operators already running before it's deployed, set the `eoe_eigenda_onchain_quorum_status` initial value by configuring `operators[i].eigenDAConfig.quorums[j]` to `true` when the operator is in quorum at the exporter's start. -## Docker image +##### Labels -`nethermind/eigenda-blob-scraper:latest` +- `network`: The network name (e.g., `holesky`, `mainnet`). +- `operator`: The operator name (e.g., `nethermind`, `twinstake`). The operator name corresponds to the name specified in the configuration file. +- `quorum`: The quorum index (e.g., `0`, `1`). +- `status`: The status of the onchain batches. Currently, the only supported status is `missed`. If EigenDA developers add more events to the EigenDA contracts, the exporter will be able to report additional statuses. A `signed` status cannot be used because the emitted event does not contain the signers' public keys. -## How to Run the Application +## Installation -### Docker +There are two options for installing the EigenLayer AVS OnChain Exporter: -The application can be run via Docker. The Docker image is available on DockerHub. To run the application, execute the following command: +### Option 1: Building the Docker Image -```bash -docker run -p 9600:9600 nethermind/eigenda-blob-scraper:latest -``` +1. Ensure you have Docker installed on your system. +2. Clone the repository: -or alternatively, if you want to modify the env variables: + ```shell + git clone https://github.com/NethermindEth/eigenlayer-onchain-exporter.git + cd eigenlayer-onchain-exporter + ``` -```bash -docker run -p 9600:9600 -e API_URL=https://blobs-goerli.eigenda.xyz/api/trpc/blobs.getBlobs -e FETCH_INTERVAL=60 nethermind/eigenda-blob-scraper:latest -``` +3. Build the Docker image: -### CLI + ```shell + docker build -t eigenlayer-onchain-exporter . + ``` -The application can also be run via the CLI. To run the application, execute the following command: +4. Run the container: -```bash -python3 main.py -``` + ```shell + docker run \ + -p 8080:8080 \ + -v $(pwd)/config.yml:/config.yml \ + eigenlayer-onchain-exporter + ``` + +### Option 2: Building the Go Binary Directly + +1. Ensure you have Go 1.23 or later installed on your system. +2. Clone the repository: + + ```shell + git clone https://github.com/NethermindEth/eigenlayer-onchain-exporter.git + cd eigenlayer-onchain-exporter + ``` + +3. Build the binary: + + ```shell + go build -o eigenlayer-onchain-exporter + ``` + +4. Run the binary: -or alternatively, if you want to modify the env variables: + ```shell + ./eigenlayer-onchain-exporter --config config.yml run + ``` + +Choose the installation method that best suits your needs and environment. + +## Usage + +Run the `eoe --help` command to see all the command options. + +```shell +$ ./bin/eoe --help +EigenLayer On-chain Exporter (eoe) exposes Prometheus metrics about AVS protocols and EigenLayer's Node Operator. + +Usage: + eoe [command] + +Available Commands: + completion Generate the autocompletion script for the specified shell + help Help about any command + run Run the application + +Flags: + -c, --config string path to config file (default "config.yml") + -h, --help help for eoe + +Use "eoe [command] --help" for more information about a command. +``` -```bash -API_URL=https://blobs-goerli.eigenda.xyz/api/trpc/blobs.getBlobs FETCH_INTERVAL=60 python3 main.py +## Configuration + +The application uses a YAML configuration file. Here's an example of the `config.yml`: + +```yaml +operators: + - name: nethermind + address: 0x57b6FdEF3A23B81547df68F44e5524b987755c99 + blsPublicKey: ["8888183187486914528692107799849671390221086122063975348075796070706039667533", "1162660161480410110225128994312394399428655142287492115882227161635275660953"] + avsEnvs: + - eigenda-holesky + eigenDAConfig: + quorums: + - 0: false + - name: nethermind + address: 0x110af279aAFfB0d182697d7fC87653838AA5945e + blsPublicKey: ["2358328128321302874738169219641985530311496023056707902743599195833986584402", "20423525555617668586476030951095516580576618542850420469015501514067149320880"] + avsEnvs: + - eigenda-mainnet + eigenDAConfig: + quorums: + - 0: true +rpcs: + - holesky: https://ethereum-holesky-rpc.publicnode.com + - mainnet: https://ethereum-rpc.publicnode.com ``` -## How to Update the Code and Trigger CI/CD +## Structure Overview -The repository uses GitHub Actions for Continuous Integration and Continuous Deployment. The workflow is defined in the `.github/workflows/publish-docker.yml` file. To update the code and trigger the CI/CD pipeline, follow these steps: +![diagram](./img/eoe-diagram.png) -1. Make your code changes locally. -2. Commit and push the changes to the main branch. -3. GitHub Actions will automatically build and push the docker image to DockerHub. +## Contributing -The CI/CD pipeline is triggered on every push to the main branch, but can also be triggered manually by clicking on the "Actions" tab in the repository and selecting the "Publish Docker image" workflow. Then click on the "Run workflow" button. \ No newline at end of file +Contributions are welcome! Please feel free to submit a Pull Request. diff --git a/api_client.py b/api_client.py deleted file mode 100644 index c7c75a0..0000000 --- a/api_client.py +++ /dev/null @@ -1,25 +0,0 @@ -import requests - -def fetch_data_from_api(url): - """ - Fetch data from the given API URL. - - Args: - url (str): The URL of the API endpoint. - - Returns: - dict: The JSON response data. - """ - response = requests.get(url) - if response.status_code == 200: - return response.json() - else: - raise Exception(f"Failed to fetch data from API. Status code: {response.status_code}") - -# # Test the function with the provided URL -# test_url = "https://blobs-goerli.eigenda.xyz/api/trpc/blobs.getBlobs" -# try: -# data = fetch_data_from_api(test_url) -# print("Data fetched successfully.") -# except Exception as e: -# print(str(e)) diff --git a/cmd/eoe/main.go b/cmd/eoe/main.go new file mode 100644 index 0000000..828dbf3 --- /dev/null +++ b/cmd/eoe/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "context" + "log/slog" + "os" + "os/signal" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/cli" +) + +func main() { + rootCmd := cli.RootCmd() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, os.Interrupt) + go func() { + <-signalChan + cancel() + }() + err := rootCmd.ExecuteContext(ctx) + if err != nil { + slog.Error("error executing root command", "error", err) + os.Exit(1) + } +} diff --git a/cspell.config.yaml b/cspell.config.yaml new file mode 100644 index 0000000..f14b743 --- /dev/null +++ b/cspell.config.yaml @@ -0,0 +1,25 @@ +version: "0.2" +ignorePaths: + - .devcontainer + - .vscode + - internal/avs/eigenda/contracts/abi + - go.sum + - go.mod +dictionaryDefinitions: + - name: words + path: .config/dictionary.txt + addWords: true +dictionaries: + - en_US + - bash + - words + - softwareTerms + - misc +words: [] +ignoreWords: [] +import: [] +enableFiletypes: + - go + - yaml + - yml + - md diff --git a/docker-compose.yml b/docker-compose.yml index 8fee0f9..ae45c44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,20 +1,20 @@ -version: '3' - services: - scraper: + onchain-exporter: + container_name: eigenlayer-onchain-exporter build: . - ports: - - "9600:9600" + expose: + - "9090" restart: unless-stopped - environment: - - FETCH_INTERVAL=60 + volumes: + - ./eoe-config.yml:/root/eoe-config.yml prometheus: + container_name: eoe-prometheus image: prom/prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090" depends_on: - - scraper + - onchain-exporter restart: unless-stopped diff --git a/e2e/e2e.go b/e2e/e2e.go new file mode 100644 index 0000000..5a9c4ee --- /dev/null +++ b/e2e/e2e.go @@ -0,0 +1,56 @@ +package e2e + +import ( + "os/exec" + "path/filepath" + "runtime" + "testing" +) + +type E2ETestCase struct { + T *testing.T + TestDir string + RepoPath string + BinaryName string +} + +func (e *E2ETestCase) BinaryPath() string { + binaryName := e.BinaryName + if runtime.GOOS == "windows" { + binaryName += ".exe" + } + return filepath.Join(e.TestDir, binaryName) +} + +func (e *E2ETestCase) InstallGoModules() { + e.T.Helper() + cmd := exec.Command("go", "mod", "download") + cmd.Dir = e.RepoPath + e.T.Logf("Installing Go modules in %s", e.RepoPath) + if err := cmd.Run(); err != nil { + e.T.Fatalf("error installing Go modules: %v", err) + } else { + e.T.Logf("Go modules installed") + } +} + +func (e *E2ETestCase) Build() { + e.T.Helper() + e.T.Logf("Building binary to %s", e.BinaryPath()) + err := exec.Command("go", "build", "-o", e.BinaryPath(), filepath.Join(e.RepoPath, "cmd", e.BinaryName, "main.go")).Run() + if err != nil { + e.T.Fatalf("error building binary: %v", err) + } else { + e.T.Logf("binary built") + } +} + +func CheckGoInstalled(t *testing.T) { + t.Helper() + err := exec.Command("go", "version").Run() + if err != nil { + t.Fatalf("error checking Go installation: %v", err) + } else { + t.Logf("Go installed") + } +} diff --git a/e2e/eoe/e2e.go b/e2e/eoe/e2e.go new file mode 100644 index 0000000..0978a8e --- /dev/null +++ b/e2e/eoe/e2e.go @@ -0,0 +1,65 @@ +package e2e + +import ( + "os" + "os/exec" + "path/filepath" + "testing" + + base "github.com/NethermindEth/eigenlayer-onchain-exporter/e2e" +) + +type ( + e2eArranger func(t *testing.T, testDir string) error + e2eAct func(t *testing.T, testDir string) *exec.Cmd + e2eAssert func(t *testing.T) +) + +type e2eEOETestCase struct { + base.E2ETestCase + arranger e2eArranger + act e2eAct + assert e2eAssert + pid int +} + +func newE2eEOETestCase(t *testing.T, arranger e2eArranger, act e2eAct, assert e2eAssert) *e2eEOETestCase { + t.Helper() + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + tc := &e2eEOETestCase{ + E2ETestCase: base.E2ETestCase{ + T: t, + TestDir: t.TempDir(), + RepoPath: filepath.Dir(filepath.Dir(wd)), + BinaryName: "eoe", + }, + arranger: arranger, + act: act, + assert: assert, + } + t.Logf("Creating new E2E test case (%p). TestDir: %s", tc, tc.TestDir) + base.CheckGoInstalled(t) + tc.E2ETestCase.InstallGoModules() + tc.E2ETestCase.Build() + return tc +} + +func (e *e2eEOETestCase) run() { + // Cleanup environment before and after test + if e.arranger != nil { + err := e.arranger(e.T, e.TestDir) + if err != nil { + e.T.Fatalf("error in Arrange step: %v", err) + } + } + if e.act != nil { + cmd := e.act(e.T, e.TestDir) + e.pid = cmd.Process.Pid + } + if e.assert != nil { + e.assert(e.T) + } +} diff --git a/e2e/eoe/eigenda_test.go b/e2e/eoe/eigenda_test.go new file mode 100644 index 0000000..a0c99c5 --- /dev/null +++ b/e2e/eoe/eigenda_test.go @@ -0,0 +1,156 @@ +package e2e + +import ( + "io" + "net/http" + "os" + "os/exec" + "testing" + "time" + + base "github.com/NethermindEth/eigenlayer-onchain-exporter/e2e" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" + "github.com/stretchr/testify/assert" +) + +func TestEigenDAExporterUpMetric(t *testing.T) { + var ( + cmdErr error + prometheusResp *http.Response + prometheusErr error + ) + + e2eTestCase := newE2eEOETestCase(t, + // Arrange + func(t *testing.T, appPath string) error { + setupConfigFile(t, appPath, &config.Config{ + Operators: []config.OperatorConfig{ + { + Name: "nethermind", + Address: "0x57b6FdEF3A23B81547df68F44e5524b987755c99", + BLSPublicKey: [2]string{"8888183187486914528692107799849671390221086122063975348075796070706039667533", "1162660161480410110225128994312394399428655142287492115882227161635275660953"}, + AVSEnvs: []string{"eigenda-holesky"}, + EigenDAConfig: config.EigenDAConfig{ + Quorums: map[int]bool{ + 0: true, + }, + }, + }, + }, + RPCs: map[string]string{ + "holesky": "https://ethereum-holesky-rpc.publicnode.com", + }, + LogLevel: "debug", + }) + return nil + }, + // Act + func(t *testing.T, appPath string) *exec.Cmd { + cmd, _, _ := base.RunCommandCMD(t, appPath, "eoe", "run") + + // Wait for the Prometheus server to start and metrics to be collected + time.Sleep(10 * time.Second) + + // Get Prometheus metrics + prometheusResp, prometheusErr = http.Get("http://localhost:9090/metrics") + + // Stop EOE + if err := cmd.Process.Signal(os.Interrupt); err != nil { + t.Fatalf("Failed to send interrupt signal: %s", err) + } + + // Wait for EOE to exit + cmdErr = cmd.Wait() + return cmd + }, + // Assert + func(t *testing.T) { + // Check command ran successfully + assert.NoError(t, cmdErr) + + // Check Prometheus metrics were collected successfully + assert.NoError(t, prometheusErr) + assert.Equal(t, http.StatusOK, prometheusResp.StatusCode) + + // Check for the presence of eigenda_exporter_up metrics + responseBody, err := io.ReadAll(prometheusResp.Body) + if err != nil { + t.Fatalf("Failed to read response body: %s", err) + } + assert.Contains(t, string(responseBody), "eigenda_exporter_up") + }, + ) + + e2eTestCase.run() +} + +func TestEigenDAExporterLatestBlockMetric(t *testing.T) { + var ( + cmdErr error + prometheusResp *http.Response + prometheusErr error + ) + + e2eTestCase := newE2eEOETestCase(t, + // Arrange + func(t *testing.T, appPath string) error { + setupConfigFile(t, appPath, &config.Config{ + Operators: []config.OperatorConfig{ + { + Name: "nethermind", + Address: "0x57b6FdEF3A23B81547df68F44e5524b987755c99", + BLSPublicKey: [2]string{"8888183187486914528692107799849671390221086122063975348075796070706039667533", "1162660161480410110225128994312394399428655142287492115882227161635275660953"}, + AVSEnvs: []string{"eigenda-holesky"}, + EigenDAConfig: config.EigenDAConfig{ + Quorums: map[int]bool{ + 0: true, + }, + }, + }, + }, + RPCs: map[string]string{ + "holesky": "https://ethereum-holesky-rpc.publicnode.com", + }, + LogLevel: "debug", + }) + return nil + }, + // Act + func(t *testing.T, appPath string) *exec.Cmd { + cmd, _, _ := base.RunCommandCMD(t, appPath, "eoe", "run") + + // Wait for the Prometheus server to start and metrics to be collected + time.Sleep(time.Minute) + + // Get Prometheus metrics + prometheusResp, prometheusErr = http.Get("http://localhost:9090/metrics") + + // Stop EOE + if err := cmd.Process.Signal(os.Interrupt); err != nil { + t.Fatalf("Failed to send interrupt signal: %s", err) + } + + // Wait for EOE to exit + cmdErr = cmd.Wait() + return cmd + }, + // Assert + func(t *testing.T) { + // Check command ran successfully + assert.NoError(t, cmdErr) + + // Check Prometheus metrics were collected successfully + assert.NoError(t, prometheusErr) + assert.Equal(t, http.StatusOK, prometheusResp.StatusCode) + + // Check for the presence of eigenda_exporter_latest_block metric + responseBody, err := io.ReadAll(prometheusResp.Body) + if err != nil { + t.Fatalf("Failed to read response body: %s", err) + } + assert.Contains(t, string(responseBody), "eoe_eigenda_exporter_latest_block") + }, + ) + + e2eTestCase.run() +} diff --git a/e2e/eoe/run_test.go b/e2e/eoe/run_test.go new file mode 100644 index 0000000..ba22b2b --- /dev/null +++ b/e2e/eoe/run_test.go @@ -0,0 +1,275 @@ +package e2e + +import ( + "net/http" + "os" + "os/exec" + "testing" + "time" + + base "github.com/NethermindEth/eigenlayer-onchain-exporter/e2e" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" + "github.com/stretchr/testify/assert" +) + +func TestE2E_ConfigNotFound(t *testing.T) { + // Test context + var ( + cmdErr error + stdErr string + ) + // Build test case + e2eTestCase := newE2eEOETestCase(t, + //Arrange + func(t *testing.T, appPath string) error { + return nil + }, + //Act + func(t *testing.T, appPath string) *exec.Cmd { + cmd, _, stdErrReader := base.RunCommandCMD(t, appPath, "eoe", "run") + go copyOutputString(t, stdErrReader, &stdErr) + cmdErr = cmd.Wait() + return cmd + }, + //Assert + func(t *testing.T) { + // CMD should fail + assert.Error(t, cmdErr) + // Check if the error message contains the expected error + assert.Contains(t, stdErr, "Error: open eoe-config.yml: no such file or directory") + }, + ) + // Run test case + e2eTestCase.run() +} + +func TestE2E_ConfigFound(t *testing.T) { + // Test context + var ( + cmdErr error + ) + // Build test case + e2eTestCase := newE2eEOETestCase(t, + //Arrange + func(t *testing.T, appPath string) error { + setupConfigFile(t, appPath, &config.Config{ + Operators: []config.OperatorConfig{ + { + Name: "nethermind", + Address: "0x57b6FdEF3A23B81547df68F44e5524b987755c99", + BLSPublicKey: [2]string{"8888183187486914528692107799849671390221086122063975348075796070706039667533", "1162660161480410110225128994312394399428655142287492115882227161635275660953"}, + AVSEnvs: []string{"eigenda-holesky"}, + EigenDAConfig: config.EigenDAConfig{ + Quorums: map[int]bool{ + 0: true, + }, + }, + }, + }, + RPCs: map[string]string{ + "holesky": "https://ethereum-holesky-rpc.publicnode.com", + }, + LogLevel: "debug", + }) + return nil + }, + //Act + func(t *testing.T, appPath string) *exec.Cmd { + cmd, _, _ := base.RunCommandCMD(t, appPath, "eoe", "run") + + time.Sleep(2 * time.Second) + if err := cmd.Process.Signal(os.Interrupt); err != nil { + t.Fatalf("Failed to send interrupt signal: %s", err) + } + + cmdErr = cmd.Wait() + return cmd + }, + //Assert + func(t *testing.T) { + // CMD should fail + assert.NoError(t, cmdErr) + }, + ) + // Run test case + e2eTestCase.run() +} + +func TestE2E_LogLevelDebug(t *testing.T) { + var ( + cmdErr error + stdErr string + ) + + e2eTestCase := newE2eEOETestCase(t, + // Arrange + func(t *testing.T, appPath string) error { + setupConfigFile(t, appPath, &config.Config{ + Operators: []config.OperatorConfig{ + { + Name: "nethermind", + Address: "0x57b6FdEF3A23B81547df68F44e5524b987755c99", + BLSPublicKey: [2]string{"8888183187486914528692107799849671390221086122063975348075796070706039667533", "1162660161480410110225128994312394399428655142287492115882227161635275660953"}, + AVSEnvs: []string{"eigenda-holesky"}, + EigenDAConfig: config.EigenDAConfig{ + Quorums: map[int]bool{ + 0: true, + }, + }, + }, + }, + RPCs: map[string]string{ + "holesky": "https://ethereum-holesky-rpc.publicnode.com", + }, + LogLevel: "debug", + }) + return nil + }, + // Act + func(t *testing.T, appPath string) *exec.Cmd { + cmd, _, stdErrReader := base.RunCommandCMD(t, appPath, "eoe", "run") + + // Capture the output + go func() { + copyOutputString(t, stdErrReader, &stdErr) + }() + + // Let it run for a short time + time.Sleep(2 * time.Second) + + // Stop the command + if err := cmd.Process.Signal(os.Interrupt); err != nil { + t.Fatalf("Failed to send interrupt signal: %s", err) + } + + cmdErr = cmd.Wait() + return cmd + }, + // Assert + func(t *testing.T) { + assert.NoError(t, cmdErr) + assert.Contains(t, stdErr, "DEBUG") + }, + ) + + e2eTestCase.run() +} + +func TestE2E_LogLevelInfo(t *testing.T) { + var ( + cmdErr error + stdErr string + ) + + e2eTestCase := newE2eEOETestCase(t, + // Arrange + func(t *testing.T, appPath string) error { + setupConfigFile(t, appPath, &config.Config{ + Operators: []config.OperatorConfig{ + { + Name: "nethermind", + Address: "0x57b6FdEF3A23B81547df68F44e5524b987755c99", + BLSPublicKey: [2]string{"8888183187486914528692107799849671390221086122063975348075796070706039667533", "1162660161480410110225128994312394399428655142287492115882227161635275660953"}, + AVSEnvs: []string{"eigenda-holesky"}, + EigenDAConfig: config.EigenDAConfig{ + Quorums: map[int]bool{ + 0: true, + }, + }, + }, + }, + RPCs: map[string]string{ + "holesky": "https://ethereum-holesky-rpc.publicnode.com", + }, + LogLevel: "info", + }) + return nil + }, + // Act + func(t *testing.T, appPath string) *exec.Cmd { + cmd, _, stdErrReader := base.RunCommandCMD(t, appPath, "eoe", "run") + + // Capture the output + go func() { + copyOutputString(t, stdErrReader, &stdErr) + }() + + // Let it run for a short time + time.Sleep(2 * time.Second) + + // Stop the command + if err := cmd.Process.Signal(os.Interrupt); err != nil { + t.Fatalf("Failed to send interrupt signal: %s", err) + } + + cmdErr = cmd.Wait() + return cmd + }, + // Assert + func(t *testing.T) { + assert.NoError(t, cmdErr) + assert.Contains(t, stdErr, "INFO") + }, + ) + + e2eTestCase.run() +} + +func TestE2E_Prometheus(t *testing.T) { + // Test context + var ( + cmdErr error + prometheusResp *http.Response + prometheusErr error + ) + // Build test case + e2eTestCase := newE2eEOETestCase(t, + //Arrange + func(t *testing.T, appPath string) error { + setupConfigFile(t, appPath, &config.Config{ + Operators: []config.OperatorConfig{ + { + Name: "nethermind", + Address: "0x57b6FdEF3A23B81547df68F44e5524b987755c99", + BLSPublicKey: [2]string{"8888183187486914528692107799849671390221086122063975348075796070706039667533", "1162660161480410110225128994312394399428655142287492115882227161635275660953"}, + AVSEnvs: []string{"eigenda-holesky"}, + EigenDAConfig: config.EigenDAConfig{ + Quorums: map[int]bool{ + 0: true, + }, + }, + }, + }, + RPCs: map[string]string{ + "holesky": "https://ethereum-holesky-rpc.publicnode.com", + }, + LogLevel: "debug", + }) + return nil + }, + // Act + func(t *testing.T, appPath string) *exec.Cmd { + // Run EOE + cmd, _, _ := base.RunCommandCMD(t, appPath, "eoe", "run") + // Wait for the Prometheus server to start + time.Sleep(2 * time.Second) + // Get Prometheus metrics + prometheusResp, prometheusErr = http.Get("http://localhost:9090/metrics") + // Stop EOE + if err := cmd.Process.Signal(os.Interrupt); err != nil { + t.Fatalf("Failed to send interrupt signal: %s", err) + } + // Wait for EOE to exit + cmdErr = cmd.Wait() + return cmd + }, + // Assert + func(t *testing.T) { + assert.NoError(t, prometheusErr) + assert.Equal(t, http.StatusOK, prometheusResp.StatusCode) + assert.NoError(t, cmdErr) + }, + ) + // Run test case + e2eTestCase.run() +} diff --git a/e2e/eoe/utils.go b/e2e/eoe/utils.go new file mode 100644 index 0000000..ffbe84e --- /dev/null +++ b/e2e/eoe/utils.go @@ -0,0 +1,37 @@ +package e2e + +import ( + "bytes" + "io" + "os" + "path/filepath" + "testing" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" + "gopkg.in/yaml.v2" +) + +func copyOutputString(t *testing.T, reader io.ReadCloser, out *string) { + t.Helper() + outBuffer := new(bytes.Buffer) + _, err := io.Copy(outBuffer, reader) + if err != nil { + panic("Failed to copy output: " + err.Error()) + } + *out = outBuffer.String() +} + +func setupConfigFile(t *testing.T, appPath string, config *config.Config) { + t.Helper() + t.Logf("appPath: %s", appPath) + configFile, err := os.Create(filepath.Join(appPath, "eoe-config.yml")) + if err != nil { + t.Fatalf("Failed to create config file: %s", err) + } + defer configFile.Close() + + encoder := yaml.NewEncoder(configFile) + if err := encoder.Encode(config); err != nil { + t.Fatalf("Failed to write config to file: %s", err) + } +} diff --git a/e2e/utils.go b/e2e/utils.go new file mode 100644 index 0000000..bef8a8b --- /dev/null +++ b/e2e/utils.go @@ -0,0 +1,55 @@ +package e2e + +import ( + "io" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +func RunCommand(t *testing.T, path string, binaryName string, args ...string) error { + _, _, err := runCommandOutput(t, path, binaryName, args...) + return err +} + +func RunCommandCMD(t *testing.T, path string, binaryName string, args ...string) (cmd *exec.Cmd, stdOut io.ReadCloser, stdErr io.ReadCloser) { + t.Helper() + t.Logf("Running command: %s %s", binaryName, strings.Join(args, " ")) + cmd = exec.Command(filepath.Join(path, binaryName), args...) + + cmd.Dir = path + + stdOut, err := cmd.StdoutPipe() + if err != nil { + t.Fatalf("Failed to pipe stdout: %s", err) + } + stdErr, err = cmd.StderrPipe() + if err != nil { + t.Fatalf("Failed to pipe stderr: %s", err) + } + + if err := cmd.Start(); err != nil { + t.Fatalf("Failed to start command: %s %s", binaryName, strings.Join(args, " ")) + } + + return cmd, stdOut, stdErr +} + +func runCommandOutput(t *testing.T, path string, binaryName string, args ...string) ([]byte, *exec.Cmd, error) { + t.Helper() + t.Logf("Binary path: %s", path) + t.Logf("Running command: %s %s", binaryName, strings.Join(args, " ")) + cmd := exec.Command(path, args...) + out, err := cmd.CombinedOutput() + t.Logf("===== OUTPUT =====\n%s\n==================", out) + return out, cmd, err +} + +func LogAndPipeError(t *testing.T, prefix string, err error) error { + t.Helper() + if err != nil { + t.Log(prefix, err) + } + return err +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..780caf3 --- /dev/null +++ b/go.mod @@ -0,0 +1,67 @@ +module github.com/NethermindEth/eigenlayer-onchain-exporter + +go 1.23.1 + +require ( + github.com/cenkalti/backoff/v4 v4.3.0 + github.com/ethereum/go-ethereum v1.14.8 + github.com/prometheus/client_golang v1.20.3 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 + github.com/stretchr/testify v1.9.0 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/uint256 v1.3.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.11 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ca72654 --- /dev/null +++ b/go.sum @@ -0,0 +1,236 @@ +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw= +github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.14.8 h1:NgOWvXS+lauK+zFukEvi85UmmsS/OkV0N23UZ1VTIig= +github.com/ethereum/go-ethereum v1.14.8/go.mod h1:TJhyuDq0JDppAkFXgqjwpdlQApywnu/m10kFPxh8vvs= +github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4= +github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= +github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= +github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/img/eoe-diagram.png b/img/eoe-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..1e1f0bdcc7144d5a527dbddc274a454835739445 GIT binary patch literal 222618 zcma&ObzD?!+cpYF3{pdb;J^@q(j{F(3rHy)0!kyLz|b);beD*Pps0X!$NU|}(1sVT}o@iyOnhgWCTd3Zzsi^k&uvtjGb@L*HS zyjy&Ujnf&Wz^s{Ig&mS2=gLJ@`>Yiz7rdyOdtbj8j3PNG4BL}#9;_wZ8v4DK)foTV zW61v}W)JIl00Or?+J1A$`)0eFDeyu-6%hmmt1rUxQYe#PyhdK{LgoSsctSe`aiuKo7~>`*8kDEf!i}P;2fy-hbKQG{QuqM-^IKV z0@m`nlJKW%*#DV$Dxl0PJPeN?u;U`+h** z+nVVGiVxq8-KDbH`HHnm>S4I`y7cTD6OKJv&1-VWQRGM41E!=B&)Hs~Z(j|GVy}i? zch={9w|08v3!lj7yZ!$Vz(^)Ym?Tkud(n7{$XUqZ%29g4n7h}eF~T#9B9}3HFzRV} zK&^3L|3c~9e~Dtm0VI5OF}Hq{5wASg{LLyRR>r`*KA&>gP2TQ_nNzomuH=BVWK3R?SJ}Jl^2>)0JzvBO z@S!2s6Q;F4iXFNC=LF@X$?1e_G}eCrh<-Qr$N&kz#oIcC|!Dwdn4RLCQ(s*uHzMe-L_Xz69aZ5-Fj( zdH1hU=2GD9e%t!$if%j(S0EK<8<0MpNqzF2V)$aOoy>9;zNUHRGc0|K2%|NxV?Qf- zoTifd^5*#)BW3}DPhkIF7B5!`#VWV?O#iC3^rdIh)!7#RPSp>6gUDcW*#w7!mt$iZccxEn$K8 zfal+hhmrHMIDh_-cDwesrwLJf!K=Nvgj^uJbDrO$T^g!K5hRk=u z{#TXwkB5p6f`5wC=x^eES-+A-nkSIsyIaqX84$89&Fx~p-j5GNoTHm%_t09hm%_!B zLlTyS?>uiy`~3OjrvBwC1@5dLW{}^iBVwe;pwx9Sl0#oNESnq$mKzM3w-<33`&9PZ zb2_Y~cJ|v>p4!c;vgwx%VFXNm{Di(IBMM~W)cM9w%?T&6RZV<%s@vJqO?8WQpFGiG z{b{3g*C`L_pj;sTejze^o&PtCOU{h?Kf?d_;Qu;nZEPHtv5HX74sw-O5fefI7bpDV zPxM}tGJjZhEN!Hj^k^UcnDxa?g!VdoQle z(d`HQd`vQcvcVR-X5oeHp_KPDK)@?o!xyPf+i-}uwQEMFU7Dr0o3F3J+~Z}hyw`s> zconYQ)6Aqg+38|%A@=S}O){pizdjufqzJpuHUd1+xawCTtIEW0-+b;2O~V#07w8y1 z8Ds|0_#_>$Fn-*a;`!@eIq9bEz2Aa=d^r#8=Dfn6ASr&p^%ZyPCU*YWnHIH&$BD0U z7BqjU;G&kD?Ws0$<1krn{Sqk*e_!3BQS|m-ZOAPzifXTsSZW&igx zgq$M_vtY>|)B;}3Pjg@D+nrI>S~90>f6#NXr*~b#-Ilt-jBMXk+kKF|*i$gH|B%{- zWC}3!#$Q^cx5>!cBgUP|5U_5ex6LA-^*{bS_6<~7z47razSQ*U8{6!Hp+|^)v%t&4 zNXs$d9~#Nty&vGH596_-zXA0$R;zTrj4_ynxc5L8T5gd!ZS6a_!g9yS_nvoF|1@X7 zCuKCOg;sA~%}ZAja?RZCs!FvQ6diBcC~Z1(_&otji(;sMSoxt8Pws}khBP}+RuGimeIxy`=t-NXs$C#8Qsh2`3SA~e*I6r)5-(6&37;Gw?)v0AD$-__n ztk=z5`oEbTi!C5rzbnzQ=eL|#4~ef8GbmSosnab^H}m`zLhEDTJ164qJaPNjrljxz zizdN}%{%==_5Zj}ISgxA*BwVh?W~Xb?UdD=FKO%0wBuz9BkzSUleTZ=>~c>z{su#F za{jy6ibFxzx7=lZXLq`M+xQryl9*0yU@BnhF(?uyD-CSGGMcA`^WqxNSH>a0o4*fY z^jXhS`=pFZbbWa=&3B5vzB+Cu+?7ETJcVVa{q~xZcB)$lUr2Ahc%j+)n00hD+jkdH zJpDXbQx{W9ewHY}+jO$1Mz5xVi#nhoQ!YbzcTA&;N}C=HNi08W%TJhN1BCL52PeDu z8I!qX7N)R%|Ng`~`;Twhun8EoUk|kd6530+T4K7+(0J0=ZZY8?@+7KyLtc-?|o?9;TPYhb&4I++>|e?2#f z@@f!75cr=gAlrf1GYhrVsJ#Wd^*1cN62M{k5s)1;EPE|gj5_FB*eY$_<>z8>uF`Rr zIdUJ7C!luEaEk-{`eqNgOMU(KM_F&8wvwB+6PleeE3D}NaZab7Uovyy!JDPSuiq827 z$)z1_{NU(4|Cz56|8+NWiWWyi3Cn$Zv#9j(tX|u;%%2g3cSmPc_<++|3$oQWx1YGg zW@L_HCYC*0&)+MuxO`AtGvz?|ory?%RGgK$x~KO|;f|E|PaMZ4%qsP)9ZSh~MmO(532L;weeAtH;AW*O|tDG2hTjl(hq0Y2hVP+4?aixJXs-^^n-M_WAVrv`$tzCDU0d#*a_HG@w7*5DYlN`Q zHz=8+ya`qpF<2c@?=HUy@vf`C1jO_h4Bm7b`=oRC>S|P-@AXNI?9rsP<=6Vv%|F{c ziL6A!SG!)#M990IhIz!^qEI;<%_>hhd z6S9&E&z(nb`vTbyMZ2ifhPddQ=d^S1>A-`m!?m|AO&!UJ*SzdiowC50z0Lqko@ha2 z$(DaW@^DO#l23m1`!aCqzGZ&OL_Ag6Ez={(1v5%@1T#RE(rd z-oNt`3Agt!Gsv3p!Ci|Fb>~MFLvF@Q^)5USghMAY$=%Qt7cZE1+D5^LFrP44I8`nom0UV6zAIm&N$W+)G_@3tx)9_UQ@> zc(!1LczN#4x7No-Z`I2_za#eqFO`JCc+I$}aQJrssTYt;tuq}e-ho2y(-NWS z;G)n)fu4v%P-@M)*ICtVK3gTVkBM0llqv0FP2U>1Ij6f*liT0knB@IY>IMXGZ4w;D z-8yYo)n#o>937dH3%y5Tif%eJ?W}2E5Y`J=^}w2!zsWuQajh(^ZuPny;daip9=oX^ zS>3LL1k2bzdQ;`L_`zdLM}?hs&4(~eKfx1hYY&6OS;tG){Ls2`jU4~dNO`zfSbBWA zmZR0iy$?}%^c6@oV(n`57zQ{_%K35=g1nb?+b%wm7c}8e(HKJ217Izb_NFbH^{Zj^ z{{;UOK}>??GxSgA&!wvX1CH&NLOYS2nQj zj??Vn1oi6b@HAZ<^al}OzgD2@3V&YZ@#{r;m?Rn{WS=}&3#4v}ZWfQ%Mf39a!OzX| zvj{Lv{^#MZCyY3P9Lt5cJvt3}$QaishXzU;kBpHv8w~hQZ2U4NIEDtRsyisuaeIon z*KCNRAIo0;K@?yr*0O!?K`s;}_S}~fRcK&w?zMPDmhIu}QSN*Le3%$8NzfXdtw8Yh zpaMnOTgq$64z^?a_st1`r76&-*{6m;tRNa3!MF90;_;t+GBMoCkz=|C9{hoJaI0Oz z43)d2dw~~)&AqZdYe{Sr@Gr#(dD2mc?eXsM4n3T9`rO{x4{BdHxmxQz;wnW6M&^bX z@NWGeV&g^I&mJ_zIq>fv%1xFv{X%{OJmm7beVy<}E8z&XIUwC_2Tb=Js!}ZfiS_bY zY_emutfBO_8%p6%yj$9|$z(T@m|mATa`a4(+vgp}C~w_-NEuK;&_cTD(%mZ3-v%uK z<)0q&Zjrs@*0~W^aqV2dc?T!WXZFM{@gOhSM&ok+!T(a()f$Wbuo2!M2gaKaMTRRT z=dsZLz%;v2cZLgI4qm}}>Any~8-6%p!sj@yY4Ngh@F7tGjj8Y`H`Ut!EX^_b3Gnl+ zI=3Z>!zdy$+Or!a>0S6yDq7aO5YCX4v0a@e_RGKgth_6V&(yR`JC50Of`?nDFU7N~B^qCl zAn9vXoAB1=zT(v0LOUf3nKg7MKfzy7XWlO}tzmE~BJ~SGR9K7aOhe|KVfk<+XZ?Oq zWhELoNXo~OJ5{isgWi4b5hnt9+bfWVXcXonX{v_^o6gj)X-KZi%-m?q+nBn%fT6_% zKl^aqf$V*0zUyU*!EL4jj0Jt2vdm`i2aX8>(@!;}U36S6MKKy)1$;_`KZt zd+PJ^xE-S-&QKYc_|kq!wJ4$Ay2p-b2b3_(aDt$;zAtbe_|pMcFuy`DWpL1@tQ3EV1yFEBq@u z%7Ui}*s4mU*Gx6PFo2aho?-=Z<`JJ~m1 z;t#_kOgDznFw4L{j}z1fO$QbcrE8JC2hlq4P9*h_&%3IDaQPUs>y}UYB_G{B`0j=+ z&>C_$9~Wn8g&+>+3hLW zL65SH@26D6-Ga$ze#Sio%2<Ik+S2#GOe1>j0manvGc)5+h_Nvs-ix#eIMhcKx_0>cL{%T-dN1IUx*uV&qQ+0&`oQqT5J>bu`Y zYbS!tZJybm&mI1>u<$14Gn$al3D}!A2Cni*FU6-Ut$Y@+FNLU!Lw~IzFXRr=?huM- z5PP1mV>uK0Yt8X~^%T=O<%t3n4doH{uAbYcXD-{Vl`#xih73khyHbhD-qx?o6{jN! z-I_ELetEyid@}8sUH=Jh0&H62RhIKsl=WEel{L*E^73v-O-7;EH-(88pN~_~kmV2Q z%3lYiCTo0tMFE9pe)ZW{(KT?qPeOxaos6UnJ*|45JlO6blf6h_qD>-r0U_+$GI>3;=sr^gH#+Li1o}fZdlti*N=j)~ zeI0Eu5&l!oca5~oA)G9yE@;hmn)pdvZKMISF^ zMg9B*w0AO7KA1DP$25Nz&F)qwt)SA9To6PnZ(^xcJ0FTfyP5aqaOmDOFRp7jlRO@4)#nLu1c|GYUAjalY5@z|L^f_bz zD~mvC!x7D-jGK^S)In)qTqq`j`&|0mVJbk+dD`gApuaJrx+PN%6dAREyDW%szqs2q zEi@RKkB-t^pC({*xLw=)lQ_u%}bZe;d$AtO!6nPggUgi-61Slu7D@*-g- zybeM*V{rg?gqo8R!IiFeC&6RX*Ql`4-cU)JYTxa0l>^XaYajo;HY@es3~tPRH^WY% zjkQu@o2+S51B=G{?jS>q&F43^yi=dKJLqVMVN9KQs`blf(OI=lgHhP&LR31Y&%dNf z`Ipr2Nb}(WogcfWxZB(#X2fpRtoO8@xX!jva~X5?ie@DbK1VaK~CkgBklWYd)+SK1O7FWmUf% zQ3s>DHoQ+9dDBas!I-_|>HaRxjO$%EK#5OAy!xH(sIFg#XKIjLAk-}oNkM63;kU1}$P>E2rzlJg0i)=7E^#}EI^_InS6;5S;~qdP6@xk! zUY?rVFD*f>6tyCR8p-8nlE3#)X0DnKUnz}IBj)P03L}p>Z)`{1$8W`m$^He`Z>B}Y zOcZ6Y#dI=1#a`meivVR=Z$4(TUX#@@mpj%r@m%cLs?q%mq@I(P`u5^UnHKVwq0_e0Fc6b=h2iKI#Xt+CGo^2;s2T zPO0{Pwa*S0Cp%ZQ|9bg6C><9`LDkAARz6zPwOKj3Z@Cgx%aHDK)&Y&|C(tikb(7kEbe?l4eir_Mst=1>=F+l#GiYXUv7bFCfzQyVYXNjH zzmj^!Xk$ldMdip>`D8_KfSrqP;xMT^AF)3eDO#5^H3q~b z=LabqJt|+*_u5h9v!H&v3A#i1DXZ7S*!8{l-oCnhYjG_(dgeA)aRNfcDra#~ec(#B zO;Y^=UU_HPY(+OI?U+r=qLJ2}-SP48-wB;DJvNmS-BMS$a*5Q(s-}F-rRnD(Nf|=? za}}bq-mC)4d#9c!ym=X-TY^7S_xzG04xT|P#eL->oTa7TUvTEb$6CvKzL^}!qT2by*-6EBlcg|;tL*r3%RyGZy<_}A z?d~2aN4}7mqIcG4C6HUIZ>Cb+uzR6m9c38@JW|a#AkXe~+hk_bzjH0{m~tQ24P!Q@d6Xv4-N&oUNPk#08-$3wCSOfPQ?|{b)r4axLFrq1 zIo=hsM;6n^(C;A8&DckcO|b`lYXf@{5cPje04V-{cV-qpy{B^tMA}?O@E$N3`6%BS zdrbXu5=_vUr01d5wZ#%IrvYY3BzvHr!s$gg2<~3eDoT#$cob7L*=KsYEN!33X0v4~ z+11aqYMUQH{R21&!%xWQ9}-)|KR&CSiN9JOSw^SEj6dk0An3f+frq3^itz|;_3a_W zxGgb0BK9iw9EAyWqy?6%JTXW4`5SV)|Fic9yk&i#XxYlK)#Q|d7msLIYB8s_ph+q| zl^OZ0=LxGc;dq2dUYHYGRoGyDHKC53V_db~0M46(qiokm74d~g4prr|P^rs5KYCI6 z4-!;Rv}^>czvY;PjA|K;F%yHvp_7YA$V2utHu2{k9$Wtq{L(0_UdibBqn4BUDrs&l z3&K>Ezxnnn1Ki1Do!wfGCk#z*v(y{csBE*{#UoB;7w)gDV1{M2V&pW$j?I8^OxQKw zN^2Y?Idjs#Sb&gpAp`xzwmI9AE)&&Sl;e1ex;JTPzA-Xq6%~@6OxxA#&pJ36<}Smg z|5-ajW+q38en09^7s5HgMC>-807g^8lA*Ke_td2W{OBa*bD{Rb?z3%^5hBl_tzyX@ zyL=p-QebPrf~@jSE(8bU>~K`LH<@-Z8kpa``T4^5+W%xkm`w3c%KquAo$8;woE4ZM zz4e+s~pU8tjI8@f@Rmjak&LPjK|KcF)hnyekNxbYAmnkWz8BK-O@1+7Tn0_7rr?VznH#eKWf1_McP>_(QPxXzw7;PfR#3 zgMVSKot^0*q~Ccqw311Sy}rXQf*DP{+Wyw{v>-4+*_^P0&MK=>w}sN9b2aT4JO1OO zZ@)zZG%BWeC8;}ewW2MIsDjh{M-vZ-qvxHNT6yXMOfDcsxKzD375Zwi32sG2_L%fI zAqreMobtYRlRs=i#iJ=lPW{3%wFyx_arzd-Ed-Ep2!Rjk;{l z{)yoBd4f&#&=qo#bEqV7!b??#SKaL;p1KvOd^7=r<1oS>dRmGDZMOyGOTq)Qa$Tl^`Eu|2ocFeTiuKCV{s6mG2{ zM)~V>s7>~a(S8NQzw46KxXtL+14Xh$xg$`osv_s#sa$<74srV!OOjQ0%e!1;5d-$M zN)e(mx0}&n7T$~LC<@0=eQOl%6bp~Oh)X$m$ti-r8jX2#>{%dnsR(CW^BamnHV=0k zL#1+BSchsAf79G&8}{>#SKMV*6vI~8jadG(6!UHL5f{67^J1mb#Qupp+_ls*&i_@U z6eP)eJTvjmvGLHEJHtQ1v$?HvhyJ^dWaH^p zGYQycyZnwdnDOhiD&pk}G6d||x58{6{9?NJE%}f_kv44KY08U0i<4;U&4k4(5S{Oy zX7sWB?mp_RC+&gaos%=hjBO9_5BMn0vVB9M;SYV|9_!sYx*$48cE{nImX=SKCG0f7 z9j)2mkx#kr!^zcS z7gnEvSQ4~0cj%N^{jeGl3Z+dGBNQ`)MOkh*6cFZ#_1t3=a9q;F0;K#q+$ zb&)#RWrBtvYfy9!Wz}y=`Uo>9YN2b!PHW6W!+KBT^24p9l-CPOQ`2;y?=5~AC;dqr zEeB0rGQqWjtY`w{j@YhG`OHgGDINS1uUlaR1Ujf7ZeF;tw+@jT*rZ61v@{0xx$WB? z-K3%V{g{gRU=dr!+Z;RMyfmB;yLhj={bH(CN4IBX`DC8o3#>g|YP906nK+F-)Al?8 zm&izwzo-LIc!r7ZiFH5E6y+_u8nHcklp?a7Zd!4H7kwOBFR)+FvEwp8=A24oyUB;_ zq)0Ec?8l2ANj!?9Z$-M{PW+(3zkg(0^0CxtBE0W!zBWaO{fcmh?pL@A9^z>xQh1HG zsT5({6%_08aLt)=h`$pxbxHrbG*npY)w%T5)ejj68)vgU6As}h5iG1m=eci1s4s4| z0-XIQcWI`-77{{eP2HxIDmavvLsvLINab6E+3B4A0vPPDJMSU9qWGHbxTAv_6I`AK zFaIt&^uV*JTr!qyMae%a)o=3gRagD(TOw_})(J>g+eKn4cpmEDt|@cUK?MEIUW^6b zj2C})K~DB_Yt$-?FF)V#N)!BRKT8-cTnexIyIKOh0|BiPDlTB; zHj=Hah|sFz6?mpG-P~s*B%KF+2i~N4;WLy}E9rRZAP}tmXZeE?A;Pbx%R%k7~>PGB1TeHzYORs$fV5@869P| zD2^H-K-B&89%FVZ-gSox#;7g@h2eDY@_{87Ne9nw#Y<`7dxwMzGJe9S7WWj&kS?sg zUP>M_=4CIMLmsL|Z^X9Ua=HkcMN$`2@wu#6`+rvYM7FtzWshq!>nfi8r)_B@nKvNY zP)}Ln`@Ja0YAfk;#8nwlMc~)WgcunDkRxrWGL?)yLICMs>~qO}m&;^zw9Ha-RFp~| z)c5uV!BqCgYU?R_Uv(BQ#}VjJ7=nM)5E{DKR}sN9R#%O-+(tdFxziR*J%6dx$rTtC z7gkf7DC^<7CxzDT;9Zbtl-pn|S?aj0jU25pc_yvN((MORI>_UbKWS|jX=!p<5|c~Z z@t~FU1A^tdh}TS+V;EzI^9Ih&p)LBHqA@$+C#KMu)RZ+t^RV zH{+_@yI{L+DSK}NH^?z$@FQJEes%+_c;KK<%;kh;Sm3r3@xIlq8r?)f{+AWtK=@B$ zTg@Sf6{*S5&6RV*2kvqcP2ObSp%6~|%U@JVvVltjJFy|3n3Pz(aB|Ru*6$`Kd(PVE zqcLQ!Pdy3^cDrqbQyP|OLoS}1i`_c61I?t1F};8Ga6gft4_@s*CW*Ku zB=#r!Ws~%fh}2SQ)ygW%5OtW~&v=f2>`!2@4>&miH50g$WiV5(oqhg^G*xj@HTnq! zQftL2nkA=)Liua3)5V-y)X$7a|15FDmsBoHK*Zo>J~D56Z>Z?*Mm#qyU1fxAy&Oz45H&` zuCU7W`?}ubvEOb()#3PhwGqk0;FS|EOKfYEhbhJ;hx;FMk!P;yd2j1CS*E(epD6md zra7pqZ*4N^Lk3=o7NZj_PY)TBZwTJ~8Tn%ZAT zulZa%C~uwi;$`aE=mO6{iwKV>`2u)*@%Du2K{1I7PueO8t;Lu9_vLKp@p(Ko>;=oV z!1MkNhr-_cs)>#C~$458}RC_>_T_ zPM_m)Y!N37NQHf3s2DUUfRl0Z3WM)wyJ8EK2}L&M_?>i#sd<-|y|>Y^#aAACms+LP z-o3U`Hdk+FiMJumgRzS4zSAdMnGlzwve72hwUBZl@mSqS%aCGIgpUWkv9`v_1FuGh z9xMNW->Uca?SHY#wAH}9NO;1X?y;%3vDyeSRN+KScGvCw3ghLewG{Cm6ojPyt#Ya; zady(~;k*#C9QS_}<(~aerVq=*r4w;mlZTV!DH*Aq?6qlbd9znpo+1JBDOk-hdNW$=Z}_uN~idGOK9Vedu?bWhiB!YMX~AZWw6hq#Jr2$ z*CbcjeGSk2g2>4FAnkX-i*H=d!3o;}1CoKY{xk2H;KRCs$koOhV3=NerH^%&!_-%N z^rNyP|5(Q*8bv9z61~*x%K3G z=2nc~Tnkr6AZtc_61SNG;-mB7jwc--$5sL{ug|rkW*rJ=*tdO};%up?)SpqiavLjT6kcZZi{{e?#uV6rf+(+`VY|hFvW&+SoP(hgaGCH8qjhBT|QwhK0oZ?EH!D6Sv{NY%Z7JXPtPhYeau8ABghpqdn!H6VoKi@R3^-4~lUormFY5*fhfr1mbpFUR+qt zC9luEt<2*1!ZF|v(uc(u4q=t`CTn#k=Xehp#o=s;c0BYgDM3%3)zZZkyKxUJ;SP`g z5kX7n!2i}TMXW7esR>H(qeB}A2EfajpJa~=TcxcA5bt~aV(|D7D?+L?bV}E#As$?| zBo&j$2myH;<_{nu=9}7%iTPMn$*2xevlbR*3h43OWP`Y&R#?u@m{Y=vF>6{=_mA$b z#`M?H^@~zmw#}epT#~bwBxxm-DCJ_XajEE{Uw5jLL9<(_9RTpsyKZ_lS*Dv1D5bI1~7(1X{9_8N|^0ZqS_jP118s2pp z@@n0rUmBq!+^IwZqi%b=->-#rXV8-S-)u_WtGD`oqS5WW3X&JYP$J*3|KUCl62+hY zsu-bkBooLNL(*6o6L#U~4Kt1t-aStkpT)$x(9Y?{XbjLXKhD?I1ST6s#Xw_V+P6hI z$E#$_JnD+fid?~pXjt81ge*5_-S(x$cvQ-v=eLsyLI8*}q49s-ITC@HLGZfMyA3Uf+*(#BS zQU|3KG5Vc&D`0^uI*|oSi#;Da#-AGOjQMkK$M9D&5f(1;*<}9_jAv&uFG-rbP~LSN z`Llq#acd%GSty!E;j;6WbyuCvlxxpQMN4akEJL?*DL!A$UV4-JNfDdW<0*-#5`6Jx ztMNCU-pFSxF*u4Lgi9gMBT87EQTn9ppbW#tD;R~ZS?4S;84S8OVSZRg?7L8=@rhNh z>I57uQ;Q4HQT}4-7W2A*5Y4buHj>g5K!rn-j-uLl)QnQeGt1b<+HTZc+Iw##%Hu+> zKh&2MjYsf&m7g?6r&v0|&OHgf@Qftb{#^6IX*)9ACY3%pgJ!f3DZx$sHR|D|{H(8U zdE5y}uhr+xb970J^%7QdnkIZHH8*9=U#a!QGMBGFAN1&FRkRimQNAfZd3=Mj9N`63 zF(lfEzt*;MlQ~LT`>;xkm-p_+4^{9r_gsK$yCF!6ahGxMK~^YKPplAiwppZR=RC9k zN0mA`&2q*|XxA)`CmQ(iLWsj+wil(8IK8Dl@=x_W@YYYXi1TGo_Lh3vi2)5$52bJx zM3cYlJj42$RfXV?#{O!=a2h3SC^?^!E-%_x82-x1%B zuGWB1e!lU6*l`j|qDXY(54&3|gu1zg-o4&r1A0vp8C31}Nzd2&_hrf~x}m51P2m}X zNk{oJlD5qT-(>fsj>Rzvoe{ZX8O#IqL`L+xWdlTWh1`&a84q~8Q@s4J@JfmvP3&Ta zM6h?;NoYexyx7e!uRON@X_Uyf`(@E2f=g#Rmuu4-tdDd^rA9XLj;+5AfTWzcQ6`;# z@ctR%-5!2%Z&ZwKRc&VWcBlc<-x*#i%RF_Np`*N*8(n$9ly~v|_ZTvo1O+gj;aTqT zF2HxlBa(TA9c6kx=~D{LUR#t`Rg(Dx)=V&JdZ*6USmnC0zX0)n=l4vfD_w%E+Y;NF zOG{$6v0YQD3W9T)<(Lp|C^Vg_6c(F^zhoPWcD5gD1*UeLk zCeN|Y_C_fn4$2O<)$XHXH|H*^E)dV!ntGJ_xGUc1_2^EsGG7piN2XMc#S0vrlRLKf zO8SJ%MF?w+9`IV~L))B2xcn`Rnb+u zk+!$V4p;6}K_111om1iSW(Ajx#t&NhY&5EO&5HP5f9g4I@tifirq+u zHvdM5?#7jNbW@puM=1*hsV^}azpX)j$bOdW4;P?6uLg-@O6JVIdm31oMW4Qp1Aq_4 zhxNZUdzA_-t6BepYDoZ7axNEyunb@3XuJ2UG36=uXPy-|bd4*O z=|p+Zpo8UV>Zs|rz3mDaBMYfsOU3Bgs%m%6-d^Xh(fJ=*vYNc^v(oPpI80NZ?-$p^ zBXlN`!@RBYo*%1O_;c2ZvBey=bJ&I9Mp7migwi^Dv+xY9rM|w3N^M^vJK)zEA_9Ry z9aW*ej1Q{}IUljo{^(&jgK;u)ccFrWAX>`<5$9VTJSW;gQZ9r@Yhu4T<_V!RW4CK~ zxQvh0a1wj6Xnehrp%y}-;$&y+#jvrR($(DB0+;f78G+#^)$1XfcUxi{787fJ;yn(< z;hM~J(CK2-C+1bt*{ty^F3+@)u-k z{q%fLrpt5HCMBjvz338qwB7v}W)V34e%&+Y$QMlhHqI1_)Jfc3Ij6QHFH(V`x0)pN zFT}Ts2!}IwSPC;xL%1`^iy0kS+Jh(laF?&eOo}|bNq7F?C>?$P5V%7xR$CxJ z7OWI8T#4YI#tj~hSGr`YuTDUEf9enzDQbdm-kmd`%Ahi_>4{ie4 zhbUcyA5{cdN&18r5nqHCIXWEfnWzCNRl-#_oiNUl9c)YMg8%W8l<78R#|-+mpC>B~ zyr<<8p0&7QvU)4tm7fe}R(z5rJB+kJw1l4s$7?y#w*3HkYLQyOqdAPry~wrXrJnH+ zbNJ8uvkAD1x5CKP_r=)AokHkiQrutvLc56>Pl!xJ$uN%UsN5ZIwma=!9J`BZ&Z^H4I2w#heSXaegyI+BbakR(Q7*`HN{cTq0@_@CNbP{7z=Q~2n~8NdbnC& zOr>nP8LBuI-a+|+=v|B0aum{zgTC!=L*IyaAmk<%&F~1-KIv$U(iA0wLlPiwohsBQ zuJ|=u5~YaeZxiZ2;Ksw?38>H!p;`=02Dl2Sq0hZV{W7$Yf)rk|tn5|b&d6{;J4gx) zvusIN5Qj?&;fp*%w7?JG}VT^7;U#9YoC0iNaPlanzbRla(B9f66bb(rDX z?A}Unolnpz=NCob#wI73h{M7uzEHMWr`Pwfx~V?C=6-&ExhTGJ*!&j08{`)3b@|Z` zRY#bFpzQdO$Z*{g{l7`lCMZJH@sQrB@ybJ1u+$fI%r$5>?!#&j|6d2noDiw%SnIud zh^6})pn{HEf?GUpYtdTCFEs{LG(K4bG(T^kla)h##xyA{>_sj56@Pn6NI1?PekbwMTyX<8-+PC^c;amDn+Q~v|9rr7{M9BA0wUT zM*u}IKYg?i|C1!@6|Po8hUuTfr%|-0f;XUWL<&o-NdpKo4Ui^g2$!Nuh~kONbrU?? zNNedN`{eZ(>S=rhzLR45n+Yimxn;2(5sFO%@yCAFvGUyMtVN@%$r8|x3W`;?yEMBg zBE+9>ZJ0Qeq#Ns{RmKX+jM--r$NiRms@NB z8$VKw!hNcr)%%qE-cMv%$0y6<-(Ffh%~eOgZ1>s@JN(NZLN~)n?;0~Nec5o#cKiHK z$8Ve*oH(&5H0g7B49z0+9W;{r5AWq~;C)2iqfzi3OaJ;m_+UF;T+|{1d)V>GzVs!) zWJ|^!;f&_-qJ9A_RZWON_5cK+)VJLByuwk(_#t3EMz-ju4qn|wPgkE_UeIIDUf;lh z2p#Vrc?P3?ly^f+dg@m(JU0GK^nEup!9Gb1)#2iB?0F>e-fS}hyV^9+yNA3hX|Me7 z5!Ebl-Dk4Di}GOssKnXpUv`CYdxraJ8Cn~1I3f1XjT9_D`t;1vMhn1|@m1J=I| z!U`8;1Y4&-8TMGRZ^U3_3oN(6S|P|FDs$laiW6nCv7o~|V^a000+5uyqlo`R1`5FYJPpabVNC)6Z)_Yyf_mk91T)L> z9SA3_xwj?lpW@TEY;5xY)*$0mN|tFmlFa4maS;-hO9XDockYNFSL^>EW!jMI=%D)# z8OxXvAcgbD1oKQ@>f|ej0o=Y#(vc94LSDdk{au*dL*SVr(=nf9|4M`kcMmKM0OXS{ z)GkEDv%%cli=x{AKoS*4$J5RdCh-d zGw$?URbUcX;kwgh35Y#SAn+P3_Q1#lEz zp^QytTF65}9Ae{&(r-i(0qMjsN(vp>6wjweQH8omdwb8oA3_a0u-^S5ggVu8RGX zH;UFGSmRVxm6rkBG${bTL#Dj}9;5`$;J1Vs0?37Ai}PbN)5~ug_bdT2{69&6!_85X z%rY(a`{~G}v{H&*o?TX{XBSZSOHR=m-dR0vN;Zoo$tJXx>Lzvw{s6 z{@&?G1-S3|u$vbX^f<2Ex;s4h7D0IZYG%>S!U@2XZdYb-rV2Rix4?&m9&e5p?R1+u z1R==%0q$hm4H54n(0+Xx8-|}lg54B-1BaV@7D`efovVAJw&H+rzxmxB`>SAb4{>kW zZ2V4>W&AH^>PX23fb?kLy9yJ@kH?bEHBsMm?iaJs0uJud&tCfxGn}mt4X0XkA9Ij8jw`; z;sE>sz4zS+*@&EG9TvFts8K|Vsjx{Jzr=~I5(ZGb@L_4_P0N)m97 znp}Tb@gpIi1ku=nU;R9_rWpWV&%_lsc1uuSa;ZCBD78?4Ul}=h9uEhPvTXmEXm%QdH#O=a}Q8Ej^72> z0Nq?`mG>pYe)RZ7VEq4W&g6v?P+o$0kjelst#$z0pFlSu3s50NoJ~@x0lUo9NB&pz`A0YYag(Be?vIlgKQ$%51tp7k zZclc+B}Bi^miA3^?nHXdc+L5@CqNbYWPXg}{aFy3Gk?w9u z3F!s_fk8@;?ruSpP&!3m0O=M4>5}g5{;hHEbI$v|-}(LrhIyW~)_t$*zT)58eijD4 zl1q>{96XR#a26y9DV7%CstQ#Ug(Ot_0flc6uF6xY3n!P+lbz{WsvC(f4s}0Ezb%HB z1IUO!*N}I(9s;AjO42dvsUED}wH`f!LrB3Hw*VXs6v=6@({F0atQOnDOu%;f@i>{^ zN%VOW4Ps0D|9GPK*8^LS633y!#b=Z+rHHkxPS~mE3A6ONfoRltKfF-#%vO8lV+1?# zAFG8fQdiWupF%ER+0kB%#)6&7Knk|DCwbY6Nzt1P)gW&NP!4o-?JGJq$CArZ4QBA? z;tgyv9KM3pei8)=B~{g7FG~nG|H~G3idwuO2qy-#$p|5!o6GUoo2z4{B%nYQG3Rn+ zw;@BV?4JcFM2h{5hgil|+oZP+QGyoz@&!=0(Rp1>Z-SY*?U5V12+ncKp;2XiD z<8gbvCK{3>8A3lu>h?<=sXtv@sKsM|cbwL@lOVNtq*)F|I@*;JX zu?QE5ZP2vI>vX$@Sjo@?8b~9m+3+t!^R&-rn+w&B-;bwPWUG1pRxa>)0uKW+f{^&_ zppzuw$1Er(CUMgEJu~W8`BNzU+;dfjQvDbvDUbV~cpxNgZ9oc^a2&VyFzajHGWe)H zo-@!&V{fQ5gT!tiKC17UDEU`CM4(2-bhp zzCKHFxdbqf;ExwFWn?V?1(0(@i8}}d>nY_ixZZ4Z1)|}$f<89;n!m1#9W+MuCuR7L zo58}9pCdB|3f7=kp?X`Vb=~0LgO>xnouyB8>B=ARFq!)Vm5tf?{zA_LF;!q3ZM(&% z>6(g0Aip#LpSR2T3&@Pmf`r_ozKc05Oa6r|BSaKeOl4jY1f+MOCgAL33%p(0gMHTX zxp?z&I7*7LZ$=pSotTUpdJNQL$7XE}10VCp)Om1mjP+MUg79dfl860&Vb^LznW?m&AFE8nlEw$ z3O~Jo^L#8^Iv0?(8ukZQMrdjToF5o`hBn^NiEE{$~A{cnYK+v^c!ok|kMFf^aw zaqOHcQ_$;}wStFibfC6BQwOx*PlN}(*+CmCPsj#;ZyycJ5bo&A#P{*UTMW^ABDBW% zS`vhwbpw|PZ3s>BiKi;^@=1Qrl#Ib{f~tso_Ycq~a3SQ{Dks(ZQu89M^sDvBI2A zz!b*raMxl|m1RR{qM}y9{CWY~58`ums$A&L=m+kPC{*fe>2{^&emj#@R<^i$=jHCu3az_w8j?lgo)o{W%2?^ z6&ZgwGT?=49g^o%p9G|kC~R6J>(S2ut$0}c#fNuT5C15aUBG2UkIFmy4oRAdoSJdE z04RX_AL=H${t6pTxibQ`BabZRfz?W^ja!^-7o2$A3 zW10d>U^%uuqbJa_<%<4?@mg3l=w{gvH9N=(R{I0=-zu~WIdomC$0k4p> zU+Rj~QEnX#;T|l3t|g6%2$vXGS7$U?#`ZmUNVQhfkd@0bJ*-AkH-vAB{KPK}iS!(> zgz8Xm9;8K$8)w12iyINz|9;Lk3_7%6Y>{)yV$ep&r%Y&0yZ}BES+Dk69(WvTSSSyI z1DdQp+iCz-_QN)`8txjj@IZzFQM4*+@wq2Ln~4%bU?$kCR@bq$sx?z-;~>b{N!JmKxLI0JI(1P}GW8mWbGQjEBj<-XwluRBhkXIod-e{ev2f zK?1`_q@3hM%%VG(Nh)JX6S5que^^Aq@p4UU+3D?uRd{-$L6kGgJ0s{-KTHCnZQr!Vc{UDSgV22$rLZ*KV*Ef ztXXnqH?ddPGsEo(#!1CQm%&u`Tgja+@GtyUgVj=x1)aKOw^+Omfl*Iu_iCTPvzS-9z|Gt&1+;wM0zv(?Q%E=P2PG%oQc)*{5Zi}D_z zsN;t>9}g>%;Z?~H>LW?)iwFP4QMYS(hm^;8)3x;jk}70^U1EH5b%y=YB%t=*k?BJt zy!yZur38hF-iQZT`jNPG;0}oEBnJOY>D{f0svd?+fy}RLg5LA}TPy$*YCe2e)q`Vk z031rmFrYo}rrKLCHq}}9prPfi%8|7gcoD#AVX|p`6X-4@%KXZZd#%TwUyk1g=C1lk zT93#PL*l?eA_{$oyCA$|Xz5UZ7D!R4F{^l zSL-p4o9JT+l(#{V^?-*1uIkh2vx(YnpO6B&y$9xxq+aIP-A5+Sz%^+)*q2^E!jUCa zr!1sWPu-iiimHT;!k)*gvS96Wd!QUfctrZ#lVFX4wR4ZQ!r!o>3Br1r3IfsDzfnFm zJLPnN#f;Q-Q)Z#SD##W^nbIwn z%Pm6C2*(`Pw<~$B+NN-oo+mn+7a3Z;`(%W;;J-Ef{_J8O$ijH=zQxkeGajoybA%ss zrnQ!t5JhX?s}kYj-369QGKDS9hd#q=n6pF0M&mp|=6b6k#I}qd?sd6(rSOdfzG?{| z3khAR#A`(BC5Yo6D-YTRl?6|{n?z~P4Of4EB$L~2GxGqA)J)U-q5BjNSsE)!()~`c z#Z37MHxZM1%A8@m-Wr3kEZPBFJ{NGiQ|`2R=qrbp*jG_N=0hi|r}Rwwoz~oeS4^eL zU@0(Y3JZy2_ysYu4g|0cTwRwNwpbwo7n9>01ds0JqmK!^*z8%U9arJJ_5p{txd|%F z*P^}d-J+Z{flN76%HCJth!Oj)$#^OgAf^w{6+z5~bdUJ*gkl|Y(AlWKm2A#{x0`Y+ z{hJ))SPCw2w6NfU#CcpuhOL6L97$X983dyd=2V!9aU^h^iXEC@nxzdJS5;1jxo*Op=b+}!G* zK|g#-UsR~a4SHWgiBu~5V1g$Z6`eVjBdZx}`>^{FJWntusIBl!1N@Az)ibha73rm_6lc@z^Af2Z*H38Q975h$i;HdMhRFl z^@t@iHjjcW6uTLvzwKjgSQVW{FgFd9_w>Ja&~4W9(wnp^397fa0o3Sb$@|~08Om?P z1RvQjzED_;`WsGgRZAvD_HWMSRfWdw?PG%jRgagO zjIV5RbLRIJMcREzEC+@>`gXbvxXB^yrdiF)ypd=xX@*V9EH2R|?LE0K*onS$UWVkJ z8d(F=!`JJhMLH%h9YZ&*%HYN!*)g=eCwoGzg7!uo-UaX!_puYr9TDse>v`Eo0o{hV z31riB?=X78d;5l5UtTwARjK}T|56vR)k*lSqGFIUX4~~^r!Y?MBuYSXCG26w^Xc(o z*GaP8Fu5(Ps$#DH>q`0utzV}`or;s=X3T~yhS7?qdOn?)ry^HlmPpMF!!CK?d{2HM zEI>o^G0V(IH%C@iJ=sbf(~Mf>LfG;>#nZ;qsiOUYRLBu3Qtzuyk~QAe0AB#tbNo60 zu=Ra8?!>degd=isMrZXIzk?0}GP(P3Ggjl+JqkDI+#oLdb@WH5g|NAJ2^w#VJoz3e zO^TX*{1GMxKCbW5USI+@SLXSh{>!Abldt7Yrx<}KsL+K$NQ%S| zVO9Qt$g#i%0+++8>t6KyfTb#Sa97Nv+J4cbRb_cC@~(i5>V~y|@`^-i3s?cZAavCy zmp@uWyF zSOoDW73h| z=f$3MNPckfb)WXPfNB8FF6JKQyj7w*!p^PbsN3uO!w}yv&29!Zzx+C@5T*BerG_GQ zB@T7Pb1XU`YlsCwND;7J!h@0i3Rj~!BglQ!+RSF09<@-~u&aPK1AB~P`J>&-=HlRT z=(Umj-s8cVcIH02-7BO8_8*$n^<#zB#%` z^ww=nZCC1xxknE()^`*|N0;@3KN9JC!>oOuLlfe1#98G6-GOl~_^+Vxo+^Yky2PIv zy+IDWq>7A`E5F>YY@P0nz)?Kq-^)oHi}w4P&WlUJrQ5i@5x7Q!k$1+ZLUTjuFtGJ= zjhVKY=%ihO(dg70HGUc{peMUJx^gDk+hL+pq9WAOjb__QoB{5Uy~>6?^DL8V2f92c z_d-3LzQ2r$8^?MwwhY8oN@Iq+TP5i};l6kof?J>XwaaglQBt7&_zDwVoZ8dlE<5f8 z^U}F)1(RdC|DIC+2bU6q@DL(E2MiUwNk)Hlp>!+%o8Slcv+QK>b3RC$ge}vd?_*F) zkyW-~3DTbAhv{U+5mFtxz#CE++@KCYQ(Qj5H`_!}c zU0}&M)iG^fJUa?T$wKyzXc+|#y6r-Kp%iHlin-{qmuk%E&$YF9wIeVzXMmU~4`*WU z$XQDYIfSDLGy)sLga87(Wm@t`kreDe*7mMMO_eko1>v~+2VxL;3TEueXb<`UlEQS4 zNZ``*7iJ1!dB!*+&?lp_9|)`@>FtsnW~kwt}Sx#$90$HXL!E_N}I>Tg}(z(I-C(>vGS zAp31p*YvO>p{qlVw&+tj?~*H*zK^rD#25$R1y^OMvUjw6^B4ktYH#?3zE^ohdg^%t zuXQ0!PZ)}F{%i{25Sn7uvC{uM1-ENY8LS%YGM@lQYj)s=$PS3v?Jd9vLjWPDEfd>`(D%XPj*HCieFJH@6rgl`CBjmPJs!A&UYbCJeMBY)z6_?3b zKd!TQi=W44B&6HxB@wm%0;&*;CGrbzQ0y;p8Mcb{M?s{fe9ADmdO;B5QEw$e-Y5A@ zOtgmavnpb|rV8skn1|W^Zh8B05^^7}hVeJm091~rn+G+|T(&sWUsB5{=7z|Ry-FWn1o*cO<&?Jwtpt(8 zir3KedvLao@|tyyEZ9s04kUia;FpzL?GVH8uNUz#K1P%RI;M=hWcY2t8y$*ExPU z2QiY_y;T0*tJ|fEI&j^yaGdg*t;nasrhGf`t_64aXJC2Q>IvjWtov!!n*bE2XQ8*I z8UyJq=&YyiQJCb`;|XqD6>DdhLJzrm#Sn&Fw9Q#z^CLS>b9PZ4-y_MpxoZJR??(6p zw(zr~L2>qL*$aSCC3-GO$b}9ooO!CMT%85-+LOC1znuo~!9zpSn}c1Qs=30+f_1ry zx+;~+p$x7KLyT$IU0XR4SWKR)m9u@}a&~7#W9R>4p7f`q_ydf*ra~;HGyj#%E6UCNnMy0=p3Szkq=!491yJoBBQ@eKfj&yX zZuO-;5ny16R)IW;B#=Z8qk=xebm{iG5dxE~9zt(X8v=_Do>}I4(G)(%>W>~_Q{U@* z11Sdd8Fpchz#%TS^b2$-HsiEj+c8cV9>pPU9(S*9 zXAmBZz3ve-)K~boL&ux9v@}vwbLzJqQ$feP)F}5vPpW*)awv|I&H|nl-^EhE@?kMg z;Tme^32QNDBi#kxR1P0hblRS%Xo${r!C{_(n?24!TlL-7fb`R zJFA^@z;qpl9zpiXJ3<30W5ha`CLz^pyyes(N2!5@DCz6k~ z`rVJ`e=ij)uvEBSGMaiyay_A>uogHl|Au{|?_k_lGyUF|Aa3lvXT$X)8WcQt4y6pTt}?IINORs^Gv8BY}C_~w}c!{h{mufJmxLJHbyvyOYa<= zr{U9vi>_f^_$7Z+4dY`Zz%U9{I%S)vAX;VK!9q0igoohVq@`8XXVj#qFCF%HLf;xm zsl3H+a@>D~t4buKPgMZ{Q%H`Nn2RPdPoF{DLn$-(;p7*7?Ot-8E^UKuUos;_mKk(Y z3G4-~Z}t%0v)?6qP*o{~tf)96LxX18(c@2?kf{bIAbZxxX`Q~m+wcy5XyR{Aa8rKk zseqtu_gqzrB#4Id#=u;DhR`3|38LrdZlwD^rI96Ty_OKm5Be6AY3WeT-x-WMH`2Xk z(9UTJhNeoPy&5_1CRthtDrS;{Ul7-21l#EEeihovoAQ}Uxb!AD5M%pVaIo`M?maN? zOklsJJH?{k$%y!`lFl%gSnll)nm{rAHOZd!wlHWs`!2t{@JTNGA?v9xoZJH zwJQue@Ba#_)kFQYDTi5q>FQ5#y~A=M=CH}B>uuSVv{uKzC#v9qR|wih z;2Tw>$yB-}X3n;ZJVu?q(s#5Ro$~$eEA>qs zwK8$&y)TDF6c*7F+Jj`CmUmJ6N${#)s?9`Y*v$&Ufh}wd0D8?H8Sui+uUT=Ox!8lE z3T5TJTpWMo_S>!Zs_P1hJL)?>1-d1a1^WZq=y?J;c9$J-?w3pXq8{UOpY@|Y$C z#DZ}Nt61G&Io~J0@W^Zo@D2n42gU{ahzX6tDN{K!ugCQ++VedJT`Vhf<#c?(R*v*f~W@ZK}QDZ8^#50a827=59G97hK4w!_=%FAf>`)TcD>b5I-+R|v@@ zN~2+t!-CV?{3?D7>vaD`!CbDZCzPmWg!|-?zrlCAR{VvfkJ<-%5`;W( zB(@lhid%CZ2C8od5dTbeSut@1$(i470N);QvrfM~DiyOWx56um@cn6|By%XV=QTw< z5FoJi4X;UW^BhdUvSL|m$luxwN}hV{X{zES+r>2Ai|_XuoNNfKCB7o_WQsrwB)RJN zrKxJjh+KCcN79k==p)NG_MO)lZ`-xF+QE;cM`KMZCFU_l0TrmIG%^H9p^ch(P5jP{ z%h_!ce^E&l4Cd*|Qxs0F4bTjP^4MhyzkTD`JmSJ~>8sr^=WVEW#+1dx@3GC~t$Dco zFxTi5`*h!B&pE3}`$^f(IlxKXGqs`+%)or94>R`~Cst_4BR82u8du5}0L65?GRwuy zWJOQq^QX~Gq%{{^D8`wWPH;;*&jzPxfz9Ep&<+NLUEmkWPGyFe z0)5QA|4<$N9fE>}7W5H{?9Z8gExFDQKV{aUFF2uyK?;3)u++tH!W~j!rCsN&bLds0 zt2LYtn42eJe@S3stItu*y$~v(d@xC%e!QgK=asaY1_^sxKt%f>t7sc3@r89xP`nqt z*Zn;Unz^1gFGqUaF82bkqx5%DnZdo0hi0aHP(W8+w0e$NyyQxlhPtFxpe!ihlL6Ul zwg_s6A}%u{R1O*`=vv`cdG${Mx)J)bg{{QuQFy8Qaql$RyEIO+HdhzExALb5$I3 zeV%+IQ|F|U>{>R6sa4!$ySbppvC^qkLDQ7S$vY5(X4&b z_)|(hbG{h=Thes1-A@_rF)l!Jqs1eaSTECmq&4u==me}I#Qj%+=H&tkll0RL1^B6L z5LXV%0cT0FT#=UFb5$=IO6mc_fT#A7iHY@iV+s{oMQ?PoYSbob?1XDt>$FdnTk0~Y znYQ3XS;HByDyGUl!=b7lUTmE~tzBy(pA$K)Yu;2g?df$UNw-XWexsE0T;(7oPgD=D zDXOq5v1ldqTIQrHv3m5hz_3e;#XG$sOTTeX@AQIoOF&Whw{FCq3ft9){aUjAZuXp z7T0xY{jtl!F7rkqm&Yh4Qtk`jc{K#I{G}h^wRGV4#6+aD)ncV zOqCQz?Q*Ba%S6+{lpH%Q3JJh#_ccZ@t|W9C`}p3nM(9*0c0nzpk#}APiA)lq#6oDXv;D4R8%pk7T^?ZyN7auxEblcPcdXA1! zS{5F%1r+h!NLTMKZUZI+7Kb0c#F%1&b`ton2SUU?b&u#r8{{qzTD#K;81xBf8A^O0 zL^f0=yh#(9cn!TGPc1*Rjq;GBmNWW;mW|#n#V!1R`@a6&B)Wv z?1xPz07UTAwM?^!@9K^@MUZ29pNIYZY^uTUieA5(0O13I7>?lXjg25+Jw5EELHDEJ zcQja^u60TY_}!TQ0FxLG!M0`Ji6M3ZTZ1gl(nQm@ary0#tN*Z()sFB9@%#S*m-3(> z!`cmBPYg1lQogDTyyp3Z#SewkxHF*m7iKE+~tN3HX4ffHZC zCr2siZ;FYS7d2q4iUuOM6=I2x6Ttt;ZvgU^46(ld!vr&4?*cf!D<^nTW==z`jzXYsmYUDYVfy;Sza&_>$zV}30L~%yAqOBh2A8q9umX~!j zaDp5qPH;fx7Ph>55VFt~GX7D2lITr{2oUyS`Rl@UQ{;Zv z2e}*w34yLt<4O8Q<4vh6sv(C^o^EbA9vthP+E89N|f{Y~R( zg5(Chk%}8F9G0Vw`q~@h%=2EnLM;Y_IC$pG0($5I2t>k`48g(#4V&X=-e=#x^$lVw zsE`v_7nw&OU|tGv6;k@?bFcJf^4MrR1(_FZi0GI=wG2QEa*bB&2m)mFsc^ZfSWMFJ zvWDIIc9fmlvr42K1gri3@`@-?0i(IQ`a!7>H~eHVK|UqRcjx_(UApClVUsUUxLn_2 zP;e~~@?%pe3RHsqf14WgPt4YZ_EUTEm}YgHJesKo3x2 zZe$1XT+c^Qk_Y8K$HS!TR<#P6{zUx&eTCKCr4{TbsH?3kg%oPJ!|jCfLR<5HeEerN zNC#f@5!ZFVL0z(xoa8v2s`Ho zEY2?qe{VEvX;dR`Yo%|e%P0>GDcsv!O{R#5i##t6y5tvjQnDTn&Us0~Rw^pczJ#z& z_|=qe9i#;Jcqys#TQl73`Kl;x1V7qO?f&P?^GM}lR`c= z{j&r3C138;Nhq!;7SY8e(?!zswYU^q<*E0Rl*D=d{8yfxd)4D<@-~pC%bih zyg*sE0Swy%+Xcl45t&v!Fu?<*Qp501rXRkhg6+Kb>y4oQTat`K^%64k`f_0*&8w8- zFPFs${vzs9^2URY`>pS4gVWYB8SE?fDopB)PnaK`u2D3R7!iBO!rpB2`roM}%p0HC zuM3Q@@@8;O5#1fPAs(61?Zsx_V0`_-SN#w3g(gcr(em&zT2U&_)5U}~n(^%H>ocUa zd9u}1oe;kg%zxejCaOMLyIDzSHLD3}T8nABZaTj{@q%`YmKb5N_`CZ-R#~3(_SHXS zOpe!oo>}>!!@-g{4QM?{DCpMb_?vA6qS3=Y%Hzma6D zyUe=a`k(#FWB9WLXs?f)R6}+`qOj1}YTxusQGI5=yD1HN@`99ynzeS}lq`$t^^#r8 zJOMd{s~&8t;~0IB8f6TtOxV+Jz4`X5NfnAparcYuJ~WCzKfhD;b%7<;g)Kin^0}+4 zqlFdOU5q{Wp;8YQYg6xildc6(9NGA2sVQ=rThdiycZ>h*BnzlDU0JnlShbLmb*!~W z;wNQmu1BTnOst5wz?Ys=>my(b5m;u`Rm45IUcBuRy~WuDu~y%kLCVWWInZGRf>J2& z8LF`T*MCy}hM!zX>$txLp^O-yayaFnpS)Qk2h4axq5F4WAWKN*mmLH?6G_NLeY`o! zk_qPDX;~X8L6ko!N1(S}fbjq2VxQ~Phh4x0q%&|E)k5eIN1S5lzDfc_{4g zl%*|Iz3pM+#VDz3NLv}KdjD>zRFGrFrzdpzj%qTx=^`(F&K41~*v;y*ih1>3m|khr z^>X>H`EK417rR{W$DQQ)`TKD}s<*Neh11)($)4&fWIH{-a7~1mfzRK9X1N=$b z#-Y>=OUMQc#2%s^)}%#(#1AE2Ew?%^W00hXh=vG6P+N~TMhdn+21BT8$Fo7~;Xcry zcrg2QJk|*u)!}e3(Eb|7$NpPVFn((xB291A) z6V;-~^FBvfgaX#164sJ3Ggdiyt-hapo3`g(cj7FhHTY>;lEQ9hO-`wEZf=hz1797U z_Az`HSGw7SH?;PQg*$P^=j1FE2u+TpJV%Vq{|~hSe6`((D5P3 zE>z@h|NVYPAa-j^0{x%z6t7vfw|GIJVVcUfu%NqrnVd6A`9UxP{?&E0oKHsj&Zgr&LO5-$X4Scos-s66vB|2-ln1I~7 zK|$#S&}|7F@6I-ixF*mmEBH15K?I7CbDorxzRd(z@YeKMfuNX95F=;>INAU+2}%#> z5rMiOXij#rW;p5IzWX+iqvfE-8i3J?YhtYaDZq9%mv3}IT8EvU&%oBFf?Bt+Fu@0w@hcmB@zaxIb9%isnCK$o7ukZsG3dlr#+9 zkyIb=JO98==5(a+B1_Keq6%tsTRmVU-}W~*+ur~(&>zul}qv6CzM`1W|= zMOjeQ*=^4y#^m*f1YBx5WpenN=il}Y<9bv{c6nKgD@U_}OljN+p|>|1A!Otv#M+Ge|i6usNth@X+qf;3jc&p0s;89^?e6)liU~LE%7OG zRqNa)Kn50!PaUIE$pc^=jj!s(-eLN(mvs1jFWp#Ey+lgH$<6~o0x-fa@Rb5Q)2es z=Zt8t?kvl7?+9*W)>CRR^5!W1z!cs?7t}jI; zUrsNO>w?He^IqRQO9s4m{lk^MlzqPH)(IRrPilu=oeFIIGBs2@Bxy06?mCG5?0KD# ztL)Khlw(b^oNb8(=?|;*tEF8dh7U}*)~7a+I*9ON??nrHZ(0x4tleXpR}s8IuJasH zjNiLkGw+MsFI?Kqg7bV9P5WtCIUZKB>US5GSb|@y79x~L6Ag(~o^Y%@_;wZ3R?tEd zg?Z1kAV)J->B5!zan!lM&Bfxe7YUKPra`1^&5wm z7&Ym&Dao_EKYgV3Yu-|SfG{EpVE7MYb0k#wOsA@w5Ui)*vZe)-vc*~UNpA`+VJ4vu z?CGbZ_Srtd9FEZ3+8QfCe_dkQ5&pzucjo&bIsrSL92*JZu1k3qIS+$Bt;=mGHEifl ze=FrWU40^EKBPVU)uD=4_C>CM%Glr_kmJ0qh$%?YjULSjJ`sj}5h1=Q7qB$(}gHVf(=kmDk^-rh1cD z+Q>`gUr*~BTcc{E%W3kavpawnhn^d-bxOA}Dh@A2z|H!0t5h}GFNGF`8M40D)YUKXf*y!DzuazD1<&nLex+uaEJy8-UlDYZpz*f;Wd9Z|k zaT}pk={Il0^jgE2>Hfy^di!pX62s%KN<^@Xi|ZyEmX&X~5xwI@KzimZX%2F3Nwk-P z8;VC}4_6L@Bpl&tNH*HL@MkUxd7B#f-n>k{`kqX>>w)F4>&rHJy{8vU7nUccn!C#` zR*D0b{0bfDBn5r%_+6j->G9cptbleXBwm=@cpq;PezMKI87Ue|EP8{TV5Z7wx_RY! zbl=nUx#)%CO>gWCYm_Fm)rBr z^O1u!vDHbjBSjz!(B)z!Wvk~DV}=%!m?w51gFl0~GF|SIvI~w0(q?Be+l$CivnTf- zW`p#<`}O!GK1M=j&S5;e@6vhg(n$mQ2~g!)0`9E@;;O`g(GBXPa_5LPb*Xa?`t!or z>E-xOgCGDc8Ke$REqhAx_FC1kQC?FGg@S>ZRQO|-_>VYO>m@hb5)xSE;JFfn9 zvH@1R1Ktb97>ynB$oti>F>3er&*!22@Ul-Ee%i^-6_q=d!B=X&%>Uv7m=4noQ|?8B z^kea~Qvlecy2(Xr?S_HYo~b7}2%R!7j7RH}#e%}m{67bf91`jrsb@25_WR_}8t8V#IQ8!U$i<%=z+r zn(MOTL%at&s9o@t^B&U#NhbDiQ89oMO%1dq`!?Js|mA5ONWt$M^7Yd)A|&-P2T)LHDT z@epNNC+M-8_{?pyJ4?7_-boFbL+kR%YB0;6)N)~aZ(^oI{ZnvVBBl{v>IKJwujLj< zodrx?4n}{TC((boS|#~Tisy<$22#1&KwQ^O&wbHT4_Q)Ysm=!}XuL{ULIT~sl|Wer z5Wz5K&A%d;H1i1$(OA`RJ@np z%ffT&v!@kwr@ON((B=$2hj<`p)l^7fcQ}-|T)A{j5(UEFJUqtORFp!X;pZ19)#YB^ zdQnAxGvDv~DWB9_rf~LMjwR4qyU>Yosm{ z^-bAeMwQ$nnCHJEdu3s9)ByC!Ob)y9s&C-?&07{DRumae*mhynBs9R2gx=8G<6RNWVo^`0oT;gf#bS75aRsCVBM~do~?=F5V`_ z9b16sm#bm0N|J=M0&0@D^U3CZ6Vi$9Q~OQB5oPwq3%~fT14@sz#*Q8A2VYRAFcp(a z7_Z#-o{YcOI55z=ouPp<2L%(dbHH6aBqUt5*CJC$g(kI3eZ! z!n%H#k>}c{!&S`?SN#v^EU)aTKFxjNkX;o}NVVcG9Cf1NO*dko>(fdO=pv)|5^-7g zrx=HeVaZY^ZIj)ER_i{u{_>&z=!N6wHA-Q)|LCWI3RBT5aPi6WJZd{#jv(Mjeqw<| z;a#~hbIl3@Ca^WGKA3(n5ZGxb!{oatuLF8aBdlhcCwy?Ah$5sL0!xGjC;;E6H3`(N z0-}E>lv2ulFD^$+=@c#i#5Sg}7F1gV7`Qml_5}JovX7B?GY_Cc6DaPxGkPi_7yI+i z;!2f&tpNl!`PHBd$!DK+C(sR`^imYRXn~IY0;#_!b!oo07gmyx3SR_%%A`}8xeQL- zsr)B3q|5Z$UtL%G59l6{d+&>XNYO zMLkA6s5D083^*IT6BR82o1a?7%lh}4?;I0#mM;P`dok!t;XX%3DW5N_iYLrn7%9`m zTHXMLm0X@e5-R#Hskr{1)$gbKa#`c@zed;jY;2xCMzm;8BfoRZ`_iepH}dR9V8ukH zJmlrz%8l2`)M`E^uB+eMe_bx_-6;HQM`}@T&6t&6^x4mAQRXiU&v;|si{|;HfmRLG zOp}o58lB@49v%7h(l@|P;?-_$xpXDujy3ELT45awlLz)fG!gv}^ zkOUeP2E+);g))ckUKwF+qcw=!hEq|4zDz1#cuY8y6uvtbr%~e@@txw)-S#Y7n^PeH zqvrN6?x^>Rr90E+OTE}AJ0DE9Zf8gZ^7q45J(?Y7Syf-#Ls9QJ@L5mKLSHuc-pG%! z`7(UQav7@GIkSHoJ5&C;Ny)q1_1V)jyXS^bjU3aX^t>mhrCa@7&VOa_31?E4E zlJsAw8fkKUJeT14@gOv*@fIxQ6hM)hwI93qBKpW#hbtJId%fV-?tR2VXTC&adCD(!Mg@ty zlz*&P-g4gZfTA1pk2FCKAIAfLyH8i2j+v4iSUE8x*xzbN_KS$*Z5jW?P7vql^a~p9j0>&NdVWMGQ$=0UjB%U)t|FJ|Nj!H}<-V$daFWT%nlfqiIw z**42z{Yk4x+p?-oA&EIaS)a8~__-{jf}R}!;tiC>gNaELg!Z1f_DOKM#0<@Y>%i3< zi*EO<=i2+#N-&PnD-XM8_KVB$1Ky$j+o?eSKRWrxni)(OcH%PjsV#T|+k{RD+`Js) zS9@~+agw=t%v^qZOhc$%D9#$FxnA!k!_EF&7mA$|z}wNNUSq4}%Ggrqv((bn@4 zu)ps!77(#TAs<=SgxZMDUTy?+aJ%#x3WY-d@mwD&@w(B%HM5POi(4 z%+@ZgPbR9cy_7wOvLvwO?=v{GxDG&&0G_og^{yr8re%BbMb4(SI>6 ze{%YCav|2?7@0rF2v~6_bNEkL<*>XGVeUq<_Zr{lG0?nDf}~q-mx3a+AdqAeH?-Q5p}W@$BAX?$aqIqmD5>Wbt5c zOzH@K;9%-3KOsnY4k)pF6pM`&ogtrM;8y zOeXhL7|&%J@oBvES1b=7i6=R8?}QHG^@WPEymkeQ1JbWumaWXLUxq)X34Cx?=rw=N zgxR=MbAv3Is01~Kdd|G_U1qi=Sxq>>>s@6ZbIzHeQOzBo>EZ6tLZS;G9fVl!ULPs> z0Q(NqlhmkJgF|w5T{l8Fb~vVx6ZRG)OqY;4B%&WjP_4W(v4GmL$RrPa#?~ZWPP?(< z&xtz4Xq)0ccbb-9O=80cBd?9b>57*GU+jhUD#7p$Z4ci|uC0Mx{k4qUV87Q9FrDGL z&}_R`ciUZ?-o1wuSKfn`T|gRV=|GQ^eN9dLr)2^JCjz7Lm@Amd}~+cPCS^7!kvES!_{f#&-adh5B1 zGF(rKC1=H4t+I4-0|u11hf ze&lIzJr+9hBFS#zmn`?FcHS89kbk$e2dOIs_xArs*LTNL`Nn@|uW;<_gA_8d9eXauiW?;u+reYO_DnJHHq2tsp z(`VM*&89iTO#2Ontpe^A3UprP3(9W~kY5W_c<<}ipqx7a!3hSL71LyK9>NEoPILx> z7l?_kq{Cqz;Qi_kD3Kqd)4{wEWlrPoqZC!w1DXEJw0H>a4t(tvl^ZPDU^a&~AZj5H zxHc`8wZBD{7M%M4iI+X`2ALkoYjC+Bh%8^~=sJ!PTzYJtsFS}kM_a`ju|W}(#7tmk zc(Oa4j6*U`P+)O?rXu*qT{4rGeE`Jvz)P$5CE}usBqF0v8wR#j$#3aZMJoEPdwj_4 zE6(vzti$ZucM%cU?_h`Bd>&Drs7E*f{wG5hQW;7?OudWlP$iC#NWv?7NlOI1EUJ>| z1|OX5!%tA#&v=WG-day3C?X55`vx+E0)goNH|x-%xBcv2D)`(cUN3+@02OE;&rEeJjQog|{FyOcd3{p<&p#ah&jAyyCCT0gygiOPZ!?{y)I5%_I3%Hv~{tS z48!PjS*}sLzx-#keiJ`5`p?a^AY1<2a`T^r%0JEGNW8lzBy5GcYhN*5_CJyt7Z@zx z=N)Dl#iih&)S_ps?eUafdgX<9&sEOQZm?@4BNOME>(I>jnA72Fj}aD)0u!&IU>er=fV>^$Dd(47r?G7&D9A}}c)ms}r`+NmX4h-vt~YnaN^SQ`S}991K({*}?xvZIUSOYNyVK2~jaERi z*=^TSK>T|3cH9N=s3Byf2!ptU4bY0X-|OmJTtArpnEBCHC6?PXGR$Yn<>a8VsXz4&4Aoh^Yr6}dho(~S~oY642 zap?lQgGO!;;Rvp=&Q26%14kdQ_o%eBykOrr-J7S-J@ZxSjf@_m&8J$`*hZHZ`M`qXFj17<``bW3JmHF?peV$8BcmUW8m$YrTmL@^uO$oqi1 zcOd>D76EpHuBXd(wy7@H5M`d2Bf&nf!*e-8c3R za0c#ai~_apWAi)~CKr_#MZ*h&rDde;pR|v9vHJ3u7MId~2eH5VmC*QOt~rzMe8|97 z&N(dhDZA#?;ZV$x`E)M|W6^R+W~zbhYrXc51J7-{rCbCR__gPgrc}DC@OUrqwb@C;;a*u?^6?;sr$`FUb=ho_7BhE)l@7bx7TCIGsQna!yW&A@= zm`Dt%2Z6N?ISKp|^ULUDxv!bZ3Wfa5CsMh^5zJ>Y-5A*ze-+gTbPY`ZI_r<6c@eq^ zFN#W~t2?{}CDj9B4?;VP2$i`}1N!y(UOmJ&4Tyquu}vc+D#9!Wa)85Ss;EvSX4=>E zZ(9lN&6NatSOXzd52qaadTQ-w;Um4`$6l3LHvOp)mVLCREfqm@5$Mkmxh^9n)_fXAi1FG!ht^_vnkXtdNO+N;Wz zXUfZ}`rU%A_O`t7%)-MMLa8=ExOv)W#Pa#9^8-}Ec@Ld2uUkTs)?nk>hOe_=k{x|h??&A&vG0P~ z*t#5^2cac8Z+jpP@_fcP=X4E*qy7tMWA3?SwvHO|>z1DJY^>=;7+5L7mGcfG4>yIX zuMdl-ev7fm6A;b#EmVy@TS7rLB;9jarbyU=h0G;=yT)K}IF6gU@Z7xhL}}Z3R$r#e z?V{*?@cgakvc;14&$iqH^dSA#S0{|_@rPgOsX<4JXR>beL{*^8#R)qII~k~ia~n(j zh^-s#y4)K6DtXq?(d$YLIn6G9KXa3`OxHhu&FUp@0c)EXIGX$U$$XNjT5wSPJo+^F zPCg`@L9lBU-?#B~_LJ{#T(X3;eXXV&p9~s*kyJ`IQjZ>v?<<@z-%uk%Amv`E(FtQf;ZyEn+zqmWzd<83M3dqEdYO2H7P)!Retf z48lxoytjK2m#6)HNr_L0riM9~2;KwUt|o$`-SnEj(ML1YSj?Qx z1)^wpx;AaQu|5Cw$Ft8uAL?A`sBR`$&Hi{FIIwyeIL3KTL@8UTBoKZOqvjj^d;CQo zW&yL-`y0pbrwNd(BC>8&3GU@Fb!qiF<{NquFk&ByX16f&OV)mM^KHOgQ?ytW4Z)em zYxkS*HPzPNS3bPDW}h%M>@Do>&)hi0>cL-EFYUDa;H@D}JRlkUfPDZv8R0sK;XvOJ zrlKscSXo!o9X0YND1+%_jB}k-+l-|FijVmHJW~PrhM<|fYf(r+4^@xMJ}bw}CCw*NZ-4t%N6vuYP5}Gt#7&cdT_;Ml4yK=-HDpGKW0zx0j;tYvDfRB2!#>90z37 zuX_&`UuV&9hZPR{!FJ@=B(tsCC23SUPCVgU#!>qId#32E1!c(*JJ8xc*$p zTu7Yjuc|#n5aPsLK7Jc$Kjg@=@$ktRdDTe?|E7+IxP(r>^#qGQfBR?}f&K!_#0C?^#<#pfU1>AbUKN&<8aw|^Q0JTW96~mibZ=XebKgRC zF7gtLkU)XYFP+QMzg8r+z>aRRS{zIaZUU6^v_?Bor0oIt&GR$W1W)D}p{#zahK0p^ z!HGZY8}GF5VelVAt~Bw>83R-zt=#Psjl3s%xoq?2Up=ZE4i~b-4Q8qWYZ}Bj&iwI{ z;k&R+Lombp)pxXLi}m?j{)i@V8fm(=@9+p|-Cd^E%KAZ5R0mo|=U~V$X;iz6o9Y}oTw6}e8 zMTdGVbwP!C&=$L_LKpi+MlmulVdEIOsy;p57_x#tDsglcY@BWA#*H%JrF6@h)*sVq znZ0N||9MMsyi*y@tdk+^hHB{Ff2(7MAiIGn=U2k|XjXV=@-e||v}vFvkZD9jw1JQGGH@{Er7 zUXK6IW)H-}?4K*J=f|*XK#7rRjO!}GHFPTx{0OygYHYE~Z0W{7iU0ToKS8ck#1_le zCHpx(*6a!eWMB8js|?=QH-HC%{w^1sGaoHkJq5>Bs|Ux*B@h|k!xN=0^zY0w=?su^ zZviimC->TyV6Der#ZNy@eV*RqvQg7~b?Spgc@WomSlS21ihB+B^XAK&qbqJKI7m2g z_BQeHr?(JOft<1ABk#OarHG$hPJ0r@d?DXOZ-xgLxYL+a#1?u`o@FqjT<^Oq3ASJ{ zXxT5xpFuHp%s%c_Q9L9N(H$B>Or?#Pq@@kA#3rR#KI<#KZ4V^FnZ9ZHXMgXC<~kTV zmx&%8v36VZ$<5QhCU3J)cg1hHNQVX!hBGB7WTSd3lD=$qzar(Y!k<4$xUhG?D~gQJ zRA-l^8m#D&Q|dqLQKAf}>~I2*pR?8uKd&~k@oP~vBf2mAg#+??uW)?spB~IJRloO! zYkyWb9;tVlFHF%WxPome=;UJzU~vCBOv`r30N{72`uObc+o|);pQ8jhDv{H072(B< z&rL*Hlsh~*i+HtwvslpAIL5Vw1FRP6q8nOgOq0c=HToJZFN|Dc3k zL~u+-4#DCtxc9adin z*6Eo|?3QD&A4A`$Gd)S=V;x8ONO<5#9AL8BqOSI_(JtU3#PoZNa(-5vm_2`yXj*tj z9c|9fFQ6u%CGeMQt8_!&Fu?T#?Sv{HtiN|AdsZjT&TA<0*;7)M$WrSy5~JoI#D~C> zL)6}gZ7?n-f(Ehl%}8Xoly4d$F(kh)h>h{mLF(m=+()XIlVP9jxx}NE%F}2Qj1(F+ zXg@UDfWOqIPU^0Sw^D;F6&Bu$c=$xa!i`jueuPNr9k1wFNqoEMlIG6 z^?_Dbt^0Zw+FLE@VDG|UoM9&U zqy(E`cLe{-1qcr#bj4k74hWL&Bp<{bpOT{1J+(JD^tW4VkiWUIZ@y|=d&tnIePf2J z=r7%;oJ|rjP-Hdz7(LE-zf|{u$)dtR|GI*Mq6ZGFe(?R%XG)n`TH)`VLr8^-WV>JM zmFvgg%CP>N;(GtcrI&yw=xZ3WS}fh@DE`d7Ca+Hj)#rf?zska@9LM9UE@PHauY-^_ zU+S9E-QDMKGzAeo9IrOK&YfqyrKS-fUWKziFyrG(J1TFyL^fN6WX0blo%a1)j8CFc z9(}QvtJC+c@*Kl#@Au4o*!KEUGV08mnTi(TQSmi3yL@SlJR~FcqYg(L#X%IuADpCQU1OVn&mB(msx+WmS%bAb-b~9gU2x9{l>58%D zEYX%0hkGv|7Vy#){QxJ9wDs~H=619Aq^OaH?>!kEFK9K;sKrV!1HU-icP@-b%|Eo8 zzDI%*yEgKc#D3W@7=1cxIN+Np+M=>}0OfW4eagHk?}Pk}zFMLA1=~}PeM^bfyo>uifm9n$Cx3LNU4KF{cvi2mzsr50|cMgnq*z26y)N9VoGQ^`Lyl;8JYCWxlEBH`0bvcK%l@DUE0z9MXyn!w|_+=*7+NOQ;snl z&S5kkbGvf6hut*Ysal-bPwpmCbCJ_<6bE6e=~+);eTteXMbHeRHtgz8bHULv-WW^_3<<5J^@JE5rEw=d(&1cO7KK=_Oh8o^ z{1!fBme=Mg%RjU+a7g1M`d)jw?iIoOU}cUtqzQ{PnP}MVGxxkiDHm-0PG@H;ZsitR zrlHnL_TA4P?L=+I#1bSk7CdI|HII@ew>X#C7~W+-EQ$t?MfSwN*Te#LNSUkgNi#~- zf2b{9S+KZl+lsDCeL8{Io-Tq@D@A##>8rH%x6Q{X5d$?$-~zjyIAycEw}YB9amq^GD&y&Frb-Bi>GhuOD;l z;gKpma85qY2q(}zw978DUTtm-Nk^ket3p!F zRQY}GwtU`)@SeFSwBj~Lw_DaByQh~d^2D<6NH=ZicgG9ZX%J&7zd`i%$LLiN z@CdnJ%ym0m{b%`_nW*gTGoBvDvlW%W!a*d5h4L-v!OiO1^$hmh{w<9_AThq-eaL2M zaJLm*p8aUOLB)0iep1?_h$yF{_hhWjzeOTSqGiZF zS+-F~get?Ox|orsl#eWmnxEA>v?V`R>$4OiPt#V%i0$lUKhIx)`BW6&cFI0a5I?Hh1P(!lqa)TmrqV4PpDtUzf@d>9(qJ4QQ>)Bni+5^lZt+}hr zeSee-G^a4Olu_2v+N67R*CU}l7WdPgSGSb%HoEmDxmo|B*~t(=xn^U%qItTXuvb2x z^>+T=;alXY9$$!)p}V6tS@jKOH4KgC+FRXqh`>u*Y(GFs*^d+FG}j@Ef^dqvK5Dmc zN!VXV4{8eatuLBo$l)fq0tn3XsC{pyNfERbYSCOqO5nRXsvn*G(~W8^HDyim+<((Z z<6A(rV|8WegdHWLMT*{~>jGMdSbloCo39V6VVjMC%RQA#effWCAQ;ii)j1F4e0|h* zdUI?%S!CyBl)XR3Gz?{~LMa@v=cO18PYcn7Nd?V>_J$BP%Lw$e zxZAHhmYnT=;8Ei>d9}lMK+eV|@krvO7j^|8%qgbuSOka%ypUm)UH&x7F>Wj%k0XFT z>lpKJrXfad%u?`;Ax4Pp)6KoWX2l{zrBX(;2{PFMDsBlc1eP;P#GT5%5c|K~3j{2v zAojG2@{zRUJAvu;3k{X(7#A3BehTP-|8q->-K8qM!*lo~=u?cmQD6Ec`Rf4Xncg{F z1G-|Qp(Ed@Q?hKB2YzoexuLhz4)z(r`nMo4*|p8fuC{S4<|ENnKU~;0_EOrg;5*5R zqxX`u;d@0TlC=#^Go2&G3Ure1gB=>Q<8_&nS=1Rhzq2!J75^w?Q3sGRZ<4p|a+{CT zvdGnv6iwW>OS!ynUY}Y=^uLDEp)il<^eHL-GwZuO%(48%n%xIGY(Mk2Ydw=Pr2A)1 z8ZJ4-_>CB#HX1!S(q>GgWT~wWN-o~bR)gUzJ40V$6r%WkJ-rcLHyk}g@D0wCtw6hW z!(rticIVp-YU&IixD`~ogN@dIM|Cq7P-&mh}LVK%TNUjDl1hyf6Evl%2~dc zUT-J>W!U(xQ#jM)Rx)e;VYx8V)a|L`ZvH3>3u5*6M#Cqnh#OO_7cLaDD*6IyjZ^wh zFHWY}3|mfZ*D+1eW*1qk#DRd!!7R!W4TIX8UOSWJQH6BPTCKaQ5#EzcdS_e_UV%iJ z9+1@$nHsHPC&=}*#ujBfx~>xY7;})^PPn!1rFQ-nb1(^bcFZ3O!LLMpXq*!S42+FXO4Q4PSkB6aOqdRo^uSN-$(f&C4&)k@7nFS zrP5vRO(D7=8CxEeIdzz?29LU4JgyoPO@^Nqr;u=S z&L@NU3jAcp8cXInV2iUD#>GmzLpO|VS?BXU5UC(~pliD@UAPMPhqe>pL4qDed@~`B zNOtw})R0D^nVyz0KrCQ>Qpi4_(l0XLV|i#~PWx(^Qq)^74XL>F%^PEx*%R~7E?;%? ztqcbG_3Aawx!rWdGptdqrDc}3{yyzu&7y{^>Y$=Dmoe>xP!GyA8L!Ra#>Hr9NE<*| zomayiVxDB~-lHD0Y(JyIq7+(i0#sk>o^p9RY?fGZY9oF9zqgcIN;eJqjhHK9|7GfC zdyLq6qS)1O6zhwBA1XjW_CyDyU~n>S##x>=rAz0{(y$=u*DH^RF|#e_Y9}IUa7Hbm z4V6++rkHWeTBx;{jWZR$r1cOrFUA^vR7*!u*sTuilHo|~FwZ~JU-G&#I$g~`ujpAs$@d(wiD=!n;HR0$v(TF{!TtioeU1k1dSn_U zzCi2jgu9l@1df#7_;5+V3U5UK#N05bisj@qBHawqCtA`%ec+(yTrD+4%K0NRO?bic zdS7`HWtET&!Pn`Dn5|se#xuXeM$?b`;|{N_fi7y3*Xj$bE)>SZx=&?Wo(EDQ$(0L% z4sDg5N8!O~fu7Thqul+4@VvW06oWNjqK-lP?VF)L+Z@+)VSPLDMIjc4RBvlPL#*Sd zT06H3E$-CS`LRMZyG)Y*{mt_(hD1-s@#ecZqr^dVzEji!C0EC7BrQH!zUjb;yi|hGyR1mmXY^g0PZ$zZ_M-hgIhb3Vcjy?DX$|LnR z2$s|)vaT%t0v%qckkwZmi0$pAO$%868D>F}Fd`yA49kcS(_)|AEDkOU)I#U+yFFD<~b{i+3`ucoPCQSc$6 z2nDQvhqxNpCOx?R@>x^2yilbRW04ZtTLniVLaNvy~8Ve%TOtg%UPL&_p${|t>~ zv60>o+vlbyJCit-6e>9@);gsAc?wYGFg}Fg&%k~z?|3@ny{x}kui!OYBl^9%=5=)B zS8kbZHEqu(`0I^$UyL4B;orY63;RAAYKmN*obARv)!@z5Tv>gdQu4jPe^|3sOnyF0 zu=)OGe$SsK@zaCyfUyzD@c?$^sb+hNQcW>t0pF6UWP{JSCb8=x=w-Vo`Du3@kmM|md)%Mw|VE`1W_{gB4}rd?<1`@%+YP*zANK$QD&>SbfxI|&)vf2g>Y>1Y1C zEdMA;{`rEW!Y1Wn8LxQq+9#@akO&o@Out1*aGsZWd^L@!Rq5}K4E12Fuo}Hp{VP0) z=A*vl+yFbIp;!gF6cMR0^+%|)k&=VN*0yg*^qQH{#=dU;MIHWc3I2QM?4+Saj2u+p zzYvJ_MF3P(1y43j>+hEbZjFA+H3HMVcw%NHIItX82SGZD+lMc<$ow_sZ(oC!`GHQ2 zjpFx3k*%kO|K5!M`+o_g_SX%oDb>tw4Afxc*k_%>`@b(G?v8%~)A+*ue!~#8nb-r3@YW{n9do*g7Sw zdrR>%vkb{=L! z9bt@(532!pe+W=%^8xipqtSVzH0`xLE4IIw_vtN@eE8s2qRsa|KQBoHCq-4tW5!i1 zQ}|y?`@a^tUm6`cPTq2r2h`ruE$1WBvoOoLsNChBE^M)NmLpWwfYM~r5Blf0I{W!S zz#4w2KdJb{n>(QL4*L3DWj716{&uHq(^QvukLdH5}5QCZ?L7MLlPpGx3EHe{)IR;tY7 z1*#crAp9ieV9 zX%f?1NLEpw#;RS55=)1wV*?x;0Rmyl_fpTM*57Y^+Z;`{T(h(Nni4EITTEf8H2Fa% z;>N3FbhC!FVwCUwqigGC5x-+gW8ooiSv<5D&9~(`QbMJD!Kvzp#wMHx|jiUv|82y+1B?HgIJ1 zx^M3KG~3@+X0bh{HSN_hHB}}Uv?Vq4)#KG4#&W4O)#qx6`$%Z>R&!pOy~R6Yqt3N&6j6&N0;y3w(|`(ISz#IjlNRH>&>nwhIu zxHZ@cmCU=(N4Wkm*Is^4a~)fh>fLX688vsp(;ibZo2Yj^_~VsVLDb%SFQ3^#pwZ$^ z!F4+R?&In{YTN5E@sDO@g1m!$$DjKnea*Eq296?+sEwX%-9nkRd}i0zV=~|WY1BekplX)WoOKsHjLPM zR)QBPGDWu!{N`h0#Fa#Jw6mOWoX&=ZwyG9$>q-(j{Z@yJo4{)_# znT9HaR>RdRP32NVJRGv_b+0$M?GBH^{NeM>9v^{@T28=z?mkj7UpYAmd`IcMs28JD zJaOj1Or=bLTBgJ16-O>>EQZs0w0dNwxG|GB~dL<`S^e-O37NhArgRf1MBA z9j>{pMiJ<7lmOzXa&-Suq$!a0%Dv=~7H;`q*HkSl_-?-{xqQga?a%fp;T$W**-$n5@fqp<*BUxW7JVm{4wk!Qn8(o7IxL0W+KHNSvkMJ2k z0DQTCY0PerUepr-hW*yLvehX5e#Q1HUBM4tlDLN?v1Ey&lN6`Ns|qW!X%?Dj!itDl zj)3Wua_;>=>;OAaAj1r7`U5DYif8+axpd5Kj^=0RAJ>{c|fVo4H*kU5{S(o z-b#lMIvvL#?Ke97@rHCl7%4S0TDRcZ7TtcdYHao+B$&3QNC5T z?e)3q?mkHOMy-q*=g_zUQs{!r;ai8<_YT)h(_0DW5kXjlqNGv1AUiHnUL}Qg%`vP7l!uC=@5QQfsfp%?2VmnrX6~%q z%2m$CemwXC0`M4sPf8hs+i$MAXkF2&S%*MT6@@=|7o$4Ut-450K#<#Sljz0GMY#10H4p_Dt(qTdyWUu{MeC;%UdZ&y@PGP2UWM7zx9 zhKyCCyPm~U1@wcjPkShgv9(KB#9JG2UN&x!yS(Wo1_6vkzyd|YgkrE3ImuS$zw5y9-DXz^9HQ~JHvH;=h6fYf3hURpk86?Mx13mV1$k>>{inMB7THLK=as#c`F4! z!4xS~_?aE%21&-~btCIg*+(#86{EJ?vY;ErU+AkT=D*UNV&B&p z!Py6AO`_`U=cfwUZlyjQ2c21tD_xsbq0K;Zb}x~kE_44Xd%sJbTSN3`2O7`wF7&67 zZkChQR|{=E-e%|6VT0G&EuKzKqZ?m=YGFj^Y9h)PS8>W;M{!X1$BCZUn^?!O(SN#A z;uuLK5^FqP$hpPKRVhWysPwxu^Ytp<%m%>FAzd=3B-fgJ1?vX&!y*KHyc>GebhWWMBbWH~w%A)bSo>J-bXp zJNEKZUgey*%u0gS-?QJMuB$QXG>H&Glpxwjt0eYZ4$|nzOW?di4ws^a_`TlTY(#rj zD$LP~%z`9Nt&+~`*@@$@Q&fKcg$JJpdfM67-A%5?%fVC<>ksT3{Y@b`@!p@g*w1|c z0}tbfdd?Z-i3-?$!bG3F9jFL@_8yJR+$_!T0)Nvkw?S zpgSu_-G~B*Paa?$BB_T>UwVYdX$+#lXfgi+3fz(39N7VJcjYK6UoML`g6a-!EpTDg zs{J=mJ*%kl<>=SiY#-SNcO8JXB}?7AsjZ!X`bE9QRCjQJCC>VpOWhXt0~R9fLK!nostGzZ)i7moKLcP!`{m#`D8 z3W*m_Iu96TZvBM)=7#M1dV-g$_xpntDl9AaYHTFA3QDsP=WEc1*71IbPjh@4S%bgI znG({G*4bUe*0;TUrDIJeRTZTZ6}zno>EA~;X+<9Rg4XY^0)0!xs^_22$E82U z62`pUXW3D;6Q|r}T+cTo2fDT2cg+3B{&1lE!Tz=NU%Vkut-rS&c+poTtAARqSF)Ky zVN}xP`6?t1Z!!*_OK)uor*e(W-C#(xy{=NLyDD1pT)_1^;`k3|EG9#j(1PEK09Pr! zO^RE4j&#Q^oJ}SPH%K_0a}kGb1vK2SnERYedl)&DhTQA*H3{7l36Q@P@5NKbd7t`+Y}a58Piu zHW>o`P3!gkSgH26znVeBP#(a9aTq2H7^C=6Qr1VX`h>Gav!^sb`8cBR>l|2K-c5Zr zb@%udC&AiyD5Ja6-(Rw{3A>9I^fOe6Pc#0lqZ~XYiwHC?oqLnI3?USYY#Yy|mN)@q7zwK<@n`YR=frsi>n+{&!r) z;$|Y&14^Vp+KR#BcLSI;Buo8J?nhEXJg0c#+hVOoLW~!Ui2KU$;(mdUYQ+zjfr!AY zPrf_}#g8=poC9a79M+f&3qXTM-+hA06PNCSzWeRXpG)Iz8z=z-wY@K2JKj4y<)uSo z9VbPvO-S0nZPBPIdMNueSm&?~SZ9U0zZ(`|QwF_28+M_Px>=k8vLBoK{p>LXksZgs zI5sPG9$#$IFf7>4m(Pxtn(Td9+UJz2*R>jQ&@HHmOFpw1v3CRy_2)DRW442sm+xHs zreklrfC8vV*lo#yG-E5!6J|DZ6w1=6e^p$i(mOCF&WfrS;^zi|*B#hsg@^>LUA5_{N3pONq{jRZBmgvvf2X;k4Dl;=}$S|*STKS!C@EO(j~ z8RVbhU5U;&ABfv_zI#!-wP|N&4=$mP)Mei4rgGO+>usfJhTbuStwc@B-*us+>21Bv zEmTkfkcEjU?s&;58}LE|`7OGtTIQFr2|9lX_?mq?y1b(_Z~ox+pWu=E3uI%jLvIVp z8S_m|#xk``@uNB0kCcuG?`-!$xTIv(4FlN3E&AgSD|7T3m|ei|WmBq$ArC5#n9W*e zK)jL?pap^Gn^s)0n2LdWjOd}%x6GrCQwPxS%9F``F}B01tgRm8+vzysCUznwc$C%` z&VyvGD+f+6@R3yh;6rak0rs1Ui)twe#0eRfk?2nmxE!3D`t~HhpDFU7oyID5bCNmr z1;tT`>-M<(A!aW+thV0^i&gf^gY#c@k3Tza3=R+}&=5_~1l`5upL$EJYh4H4QH|+w zpM8ZqsnEEWKQcU)a1!1^)(P3tf|_Nf1L8zhS%)~WOySRBH%;f%j_nD6X^Rxxy90SRUhNu(Z9 zb-m?cJzmZHw&vPYr)>o`mKu5R*p350;9?W`L2R#tkDJ57=#k9q39NHix88e~7k!FT zMY@CdRY7zLCxFsWnT{#r%0*zlUGMX$5)fcLqcAG)js{LcbEUTlv+qpU^E zu?h^{%W2s3PI+hgBR!&t+u@=C49SjXQ$`O7x&a!XNL41iH6d_gCfzVbNwn&6d}=}z>Atb3YUY_ zYwdIc?6m^!5f+09I6FBdsKwf4sSIyYM8ijyd==PV4Q><6 zX@H_1kv4xfZb-`qWV=lx*)j0Q`Lt*NECsaoX_9{!SOHW;TM-oGciWhaZ-g-!Q-zBk zy?UO4gQCR8{ZvXQx0hhsGoLpP>aw%|$5c{P8lX?^BHwK1su#Vjh!4+nFU`yZ4o;MB2V-#ysCa?y{<`x8_s@GO(lS?`5@G>S>QBq zu4(Bn9O#w77kI%VV9tZ@Bm->B=|g_|eenm@4b!n_;k!_UP;k0T7up!~khUur1}b6m z^ssp?TmS@9?4GS8Y-zEep4{4xzdpsBOIu9WSbz27XK0Wq_H^nd zAaNd>Giy5WIuL=gmGY^h#aZFi60g;xP-4Nb)YpvgmRQ;l#J$AYWfVjFkkm-(RYGEH zp3tn9pn>ICUk3$3O1V<$-O58*80LUJs6w7%29ThR;ZM=o;tZ*ku)9hqxLM)IU3y<& zpllVhEZRa(5hqgcrss+}b3vqc1rH3c&H*1oEU>nD(>{ac>pO{F#b}9xS0+B$O=gCY zugwnLjh#0G6Co8<0qP0-Z5x-%9-el6?Z0P_P?y`|$HkGqmMu0Z?3>Lbc(G)mvtc!r z9<{N3`z#M@i!)Qv#-JE%@No_rHed>yqgGv32e*-K=NI ztu&$t=8ws5*Ogq5l_YIW0hda#iAL zx242d_fI=urP6GSb`-oU!ji`0VFeyTCd`VQoG&Gdv&gH%B`#s;5Lj7@4eRCkRM|89 z*j24BUb|S2O6ebI7D8`BJieLz3|#k@4I_m-XDPXYe{h`U5%_^a*)Gxt@j~XXwC99@ z*&=06rp^e(NNs5>aOM`ts*Bj98g!(U)x5bn59EBlXgc&F(RyV^Ml0lE^kp>kJA0+o zuH;Gobw@iY25w%-+-GK6ROR6p0S4X@S3hMS1C%?$n-Ok%hPz8glqu~|)Pht2Wa9*= z?!eqx{e&a6(uVT(Sw<)I?}maIrm5qvGP$stC+IpQ+UU+uaO7-sC{8lu-$%tFynb{{ z?#o>JSwc%ym|qeP;)Rtwj_OB*bDuDz=)%WeDe#Xt6!_h zf}Ego0O zGyVMWJI12F@GO5drDuJwD1&)4R>9mmlaNN}J}71ePJO$_{WYQERAlctdX5|-EOhk+ z;)y)1I+Krj)7_3FGkY~I*1J*`Qnf!~%f{SU{u+09pav@MOc{=%fB8UvHE>zj-4VB! zbeEiQ?;T(@&e0wch`D^6|A$As2_G_eSL-eZRbc4AR7qa>nr}C$uL$F;b$>EwJ*H}b ziW(zvmK{mcJTq~%GCaRt!()xJRQ<@v%Qk9(-=t3TwFk-em(8mmJMzPO1*oyw`QO-9 zGUbn;cf#;f7W1UMD35GY5H`bN|5?3EMx?z=!qX4JC2~$vdeJTsNEDeoWAYN_|!=66Nje( zq{A>CviXe*9G-g~{#;pQY+S&9?6=|8C6SZ*t@(4o$(E*an8C@XKd%)<6gx4)A~qpw zQ~m}E$D6%of<&K_1uyd67&ODLQp&s)zB^mqvGzR}4leQZx;??s%^A#Tq4|Iz z({}sSwEm|7){B+tALaQsk`@x`l2Nah@j#w^^Hfk$hE$Gab!ui%ff#?z{~X?!0KigU zj;G_E4yiNny@1d^{jo|^N8sY)UT@`B(lA6GI=kZMNXT)vi+p#nCxAD(QcQp3-JE! zT-5=gyT=?}v4f`LrdJ0ltF1q6Sv;d|tmkX5y}F@P*UUFlnM)B zw`F?C<;aCA)1&Aw#>HCO&hGma@{u|33Z<01+OONKGrd~>=oPCUIWy`rKoRgZLEnHm z*R!Wb)5q1jd73BccwC)=mxBr1Yh~;wgXs&jza*hZeU8aKvPk5Hxajt}HK;c)g%`Ut&y6kP@xF$|wu?_gZ(|%pen;|J zua>(TohLP2Ac@(QD&%V)hUHmxybe%BJxXT=_Q2FfpU!rsF81GvzFyFSt2|wPx^eKt z|0BqL1&Js~=+=0%DzA}(rX}-4Q*7t1N(p!mUS3=x9vyae?Xn@RD+izsKQP8%!W;PK z9Ukixo~x%Vi!q!=Ht~A)CFv@o^bNG&sZoBPS(?frq<%qbJ6{&|QNwVVqhu4*jfS`B zb9Nx7o$|-oC+PE&8g{M7*1++_dYH8zuTVbxpl0br&;L`^ywBOwRDkH9XY&2)!3K#{ z4aFP7(A(Ys@wMIvV6{2Kg}v+ndh02q4tsPCy$Ytf0mGxa;+1U7~ z*mNi&QF-!)!5-Qus_E0fxzoA8dAr$6k?(ff_;J$cwg>+icQUfxsjC;6cI?%Xv&)nF zWy$??}jX-cf@8Qab-7UKB%wQ>fH*_FC&oejk~=XkAe3OE-MA0k##sWyCkq0sahVr+7S;cb?EHcrxH;lFaB@Wh8$Kz&tQc zAe#ih6f6&~t>#wnPh;jRS-OhPNZA%G{bG4i?{#tb z(URwON0@=o@Wxq$R@_YanH}xm+wz2LkNI$GPBL2I>qCnrEoE#Q#&Q;6{(Yz1QtAFl zh#QKJAt$tuiU#jF4zZT&XGRqRb8RiUlFI6dWxIzp?#}MHVbz+r@7=k;2msRhKJTl@ zb^t9TPy7s|Y9dQ@cHw%%o4wBqj;jn3b#J;+wxQ*vX!?qO^pJiMkyvT#2 zR)4en;Fb6)O3TI2X3c)Cy+YGSM`c_;OL5G*<4OdVj?m4Dp8DdIihE3IPrTkW>kq;EsP0Wi3f{C_EgP%e)dK|@Xx(WN^Oz8kE&Ey{oxcxo=?p53{ zwC>zttn|My!GCRM+@pUfY4Vx?nIqjF-^5Gxww-HxKkKIA=N1*DiA?UnK$Gpvc@ls zXW~T^Z0L>NtCF$y-yXuQqo0V*C1!$RA~A9+pY-TE_?k(5I`Y3<)EDsd0$mzquHYlH7eh(^LT5&7N zSnyrer({#|lcsNqSjE20ZbWN-sl1XDm zaHiAsg(>^KbFtTP&m?tU!JX#ov?Fg#&TKN=GSKGIyTrF$29itR8mCFio?`v3%VT6L ze2sF9L}x4YYh)IWTDsex4Ly17xvfY@+#&)EStsLj=_>pL`_5a?T&=86lRP2J@vtpstJazVOAN9Fm7)&&J6#`9ISEW|44PWqMSU@+v3H~cn(Ed zVTVs@Iuj*;dQA#)mG~b>DkVBiOq>L9;j~o5ODdXf81# z;pdAYN`a|!`ZFyah?vdA6ty$=lW7eiDzaxp3`B9Y4x^xR0ue27gUMCy!(``&1yYB{j zW2JsURoRBnqj+Z!z4(elc8vzZO7qwoUh{H4-=iZUGi=a*#vA%|>6ENx(BpCa$cigV z?k^J{ddF4ar+DZY@XL*Yw)quFGbFNL%xbiX1-NsoW|_P=D=lc=Vo}M54*|QfmC$MOCWz zf>R0~xMe>c>%?ycTtLxO?CLhz7>k|qrp1+;3}U&=fQ>@j;%X^SY~O5|zh6y)upD3C z^f;Zgiz0fCxrH&`&?oQrZScdr7uGqX10Bwc>K2LU+iT>I&oW4gw%R6}Qv-~AMhdoH z=`~yAgonQ(`iC{Fu)9boq4yPwlBh7mCjxf#c$)O zxtw?k;-jV)7mAjye>`&I?^v_!mkC(B*>4%RHO_rwSS>kWch0-t3i7peabL;kAAP@z z2l7(lwai%Y zBEqY?WNat(3)cGngTYnsi}z#iBfWXI41ZcX?#y(~V5(AZmAIKty!}aFqY8*+I>rBg z+3c6_>R&*`{v>96+R@RsIp{$H@fc%T;Ad0AkEK6eon9JFx41#8SYv?lN{Tu=hBbUQ zQ}xPH%KCJ*i`Qa4m!_4xxboyBB$YzSQA32@zLbthl}JM+p7t*qrD?8zxHPJMe@0$J zgQKgTe#q^5oAKEvR)BLY_q%lURB#(70&~*`L9#YeQ<%ZPIV4Ey;Nb~4mq6c@&_I#v z{rw9zyS^}ImwC^1+D}I(oGWud!A_=AV!a=+8kQRcYqpNc{a00rl-Q_|d$&(APcjjWpagIT)^i(4w*&r2~Y zuuQEmLit+Hfvw?nJ+F{iajI+rlZt%iiO%>8+wEDL3$F&RGe{ZoN_raT%}DUpqb%)x zLs3GcvAROLYLD{*t$mx9Q;+By-DaH(qTA}S`TckTJ}#)fgCS8INC#cfG|y=RFNE5CyrDp)v&wC|#O}FnBL-WP z8@(~QZmaJ5^|J}o@r39`2=E%ctc6P}sR@aAdmm3C--3Na9vjUaPK%5*7CN&nuCgJq zS4FUSaY6~D^l2jB4yDwazBwzV-Pjd8UN`dX-?tD>m^Amb>*;EFYrAbkki%*n@5k-&!P1xcdT)LpJ=Z#E>0l$A%q6IA0?2*$#EE!atBb?1j+(}r zU!sPP*qlaWeA6g-&!+>{S6e80Q?>MK4bdiP1j(7QYiDan@4Z|ngg~zq`J6M&;Y>G!<4QF_|Sd?rTc+X=I~ws7v`;7 zy!Y;C;9H&@FA?vCT+X)5piT|pK4RG;`#LS*Pa`G`x(bM z6pwYvL_$}cl`Z-p)d%Cv$ z_IpivQzrJK{46wBFYp!L8AABgnIIp1RaEP>iMaXNFUSpr=lTN{$=LeeY)n#5U*i4< zd4l%TSaSfECd?mK75D3N8gt2~40H-9tOk!h3_W=MgVZ51*&OgLwz6;I1k(}P1 z1ugWa177Ryr#h`;1_sxfE++#QTWR=w^f+Wfmxt(MKAWhuN=NAuJgtsi_`IR}+p}Hs zd?_T-dxr|ubatmVkP8fDRKLPW+?En!u;$_#s$ZsY5UlEmhbx*{_Oqe&kRUCVNnXom1 zU%&k8xzbjBKQY&65bxO`B=c(+?T@Z$K=W2bvilZPtXv%pfh6bNjUgxEEAw=hwE>e5hyDuofg5fF#e#VI z2=qG2vJX!7hkYXKOz4WPc8GFL$kXU{08}PCV6)b3=!sFIhWs4hqnb*t4 z5WG=5X8ZTNQJzc zrj@Prfw#~b6YNy&F`$fu|4HIH=I*JgJsb~7QrIAn@Jxq_y9CZDH6%S)=)LV zQBFt2Tuzhg6Z++G$lsq|RFqWA*!d5mij!g{Oc%GsCCitXt4MsWU1lJiFVZIqewk{$ z9wFU9O0Ikty8MG)YX&PFNOKx6&uG7ld2zy4)Hb}nKl|y4b2s)BoDbdLfv0bwlfxPR z!=9xMuIeELEA<`E&qqohUFVm}_6H^NWBe_T%{)_W&zk9KAv3}(3V}|U@k&+wF9wwc zd4_0iKM%QET(NRBzaBtKced|35K{~*P;D!(U7eH9WTUCHeKDHRboOq{u6P1H`=Kui(a0uAzc5UBPcpH!^x|$wr8ULt6uB@l{j{k$T0QkS z9DJ~t9sD@prMgvo%nL=h+msYpWKp&GI;|}+G}Rmo)Vgauo+;$A!ce6U4>804g1-`A zYvo0hyNyN=;LVzT{imSH!a3NBCZW+AmHCkH}O@a_P-~jX9o?nkRu~TQiWV zFYOd?<EGe}Mwt(8fSzH+SXBor^2+s0)HqI6af zeD*wP;Ttjp4)*k9^^)f4vM7vymOiwz z$KAxSe!m)&_>lmy7xLC91Lu6CeCgfIw3ftLSwEHb^Q<8pwxz079~Vy4&G7^@M&3LO zyo34k2}n_Kb6|>^sys!f&`DARMdI&IiK2*@ZmQH5UFkf_Z5I*cF}IFQvu3$|bAvj~ zDb!;3QSXk`a??-MTt`x;p$6AH1XYl?2s1A2M(?#WW#QX}7lmh$MdT7ZTez{G&@4zd zuN?mRpq18GTHfM+BJ3K`1oX$;f#Qxh{Kb5$;Oe`RCB5IeTtdTECf3}+rqzAK~4_{C8=Rsakhle~` zoRU<^OD1{yZRz_~`^aJHj9Lr1gE-w+ZEaN#?%Sx17C+vtVP9%r9IMIc5*-^f}jd{ zDWhW@AuPaDQaik!&>pWg8m+zFvUAN%q3t~Q{asS0kHxEUB!)Nyx*X%T)XN$?Q&es2 z8m7Pa)hY7r;@fTko?d;={%{?C!4c4;;kRI&&)H4Zwk64V&^(Xssk$U7szKX72{D>+ zzcp#7DIfmx8TS7YSjVOqX7w19$D?OAUkhMzcYiIKb`NR3ll#!VjBHhJY>awpfsWlO z7{3(*jkVfZ5@J>lz1UOf-0+PjVZL>u1_flExA7lFD`UkI zevKHCk)+|0xNIALO}$u$u=iGdj5;A>;F0MTcK9r{PwkKSppQt*GI>0Sjj232-M<%F zWdsdA-D@pS*1Uc;>Q&LOiJGeZlbUmGYNy74p8Zb*8GAQUiTM^R@qEF@#lC+iR9CdR zk5J&sDLr7e(qw(oho*cCIU79?mXc@0#5~!haP!$CX*s3+P$#AB;xySj*c)ukx(l70 z$vz2xLj3)^Y@>qkRF$30f@jR;f~PSf_>DWsIKe1g`(fzjbR+MlpG4S0H|S;ds7T)R z6wZ-rB=$gIH#s;lN@H8^bS+4(!XBoO^1zRyMj{Jkx#js(BEN^t;p-mzFwq;oCz<)9=${_8cD=c`3w6d4XkHXsS$P zUKY3vtg-hO7X|6CHQ5-SbeOd8VYfYpjkq{YM(Np$7w#l0ihM0<7^_M$EvLnyYumzc zVt98Glr=2c__NU0ugY7;rtdMO9 zcZd9X+jaxe%o9XxOK14JJ!++DI7t7l!wLhbXty8D2$}DW&n9_!B>dserPx(QpH``N z*w##)vAimeX$EQ;-d=6n>vbn#*$w?1olhcFk|S}3aA?!e<~`?<36o)pfDGY1z{UCd zBZK|`17t=V3^1qO#3{k(?S;#?E7%p+ z;_W_3ZReg=y~FVNrt9Ge)yB);+FSMI!zYW22!r@sMdHNBa zPg{Nw5|=_D)y{S1tT|#Vs4g*h7iw5wOIoeB!}?mjj_TnP%}lQY?;)h()yr zw8yOb+B2N;o@`GiscE0u7bGkaT^>U@@r%2`-DlMFr|aQtE1r`!wS#!p{*m7M%uYZn zdS70XzJB_TTy~vSSxVS(F`8E*axzRA*}DJbE?`hZ?gu6qWyk|k`O55;!<1v@5N9bn z9x7X7Xyof8ww~yz$9!S|>QAYHJlJbtT&1brr~4G6H%exU52SbNP8#i%Py;Vwwf5|H zh7i7U^Qp%?ExW_hX}-En>8V(5FF~l}T6#em-aZ~eR;o*_uRbtY8hKskZZ-_k>iA+$ zbZ21`o%B>qW+Jte90QOtaM_<%Hy4r115K+HlLH(4M!latBVAgjs%I~&^lGU$bI3u| zqd^%}^_%eODg$I*`?1?&^zAT5Z&FSQujBH~nfxX?0x7U~vhGgFky|Y_iPUjYxF)7k z>p69huYGc6OL%$d`hariN)G?|&Vuv;*P|#XKW0Bo<5~TP$xvDhVZ^KB%YkaIA?yS9 zwTzC8t#Ah)j@i%-@`ie$ccd$i4dI+0_DmjsZLwSI<-@Yba4$#`Un^{%@d=MIU*T=} z7?n>q8a5C9YG5@KTTrf2ib@sfQm!A>$zZn=21qW))B}nA9qyRiR6bVVCtq;c?fH)o}(&2fs^TIxVK(Cv`Migf|V95=+x!$7cp~1F3^~J$uYfouwqS z9y{PhA4N3hi_gCF{X`y#eX`!NSVdv5S{QMv?o4=@X6W7_;WQyR=%RhyY?=>_$v0H* zXg6wVZytQ`qrC+YQ&w5{bb+l#(=?9nNB*CLE>|zA-B1cw8H2oXHU0v}i6Z5HG&tqM z6NxOkuN-K9u||^aH*#!K7S{s8vi;}_*{X!)HFBGRD=hr>_Bfnkz{2Pzrv8%DVQ1gK zBNSC(mX@$exX7`F_lV5FUf`s10NWF)`C^@d+nBxf@JTo^Dax%6f+-+nb<}KRqMmTq zWV_bHr&$_0Xk>n6w@t8$&uIubZrZH2cWQe*;P#~jDtLVrY`)lGUwfMhqgtU@N5M-& zRTsJ#@;V=JhM12k|6ZLrLuE*74^V2RS4S}O;Nn`p43A=}V}(J_9oN2zUUSuOzIald zHHPv#cB72vbZHrpA|6d-3RHZL{^7HV1y=vSmLbvi``gX$?ptvDkoz}DxqQ}V3N_tm zmAjL%N9s`*QH(=JG+*?gxWcL2Q+bZk)0T4lU49<4L%2JOZy7lq%{#y$Po7#VVky4m zh6Tu9s5#Ik5pT$us$2qpUI5wrf5p#{kUl77({iPqKiAa zaRt{3Ch*Gqnz4bIEAcy~%cZLl3R%28@4q@9^R?v@3Uux2=O!(aXBL9$m~~1H7I)jE z7RRnj@1u3+K^yHl2uGp5w49=%L;?{_nh(|(({6`pmG>4LQdv0aZFK~)W3&e&F z=NHgyK4%p!uYL=^I3dRE4?%I=rJ6gu>9f#3174c6#x3r;qW!vSHYuFR>3eO72+s7H zJSOqdIs#8QF?X0p_@;Z=PpoSDdf3#4rCuF0a(x&ZXC-zXZR;wZ-Y##8AYv|H07PEc~)-&XQgMQ^m z{LG`#h~fn5EgCd@tLkitwz!^PI>X-mQ9r>c!al59 zJ$0O0A&jb}o{KQLebLt0=CB?LvD{Ml1$~+Wq=X6TDUquG;3J?EM4m zBsmed`2`BsEbNm0By3l1Arz5h3Y94wSkxyYQ9LGP&*z@aSdi8Bh#h@YR7a^VwfA9V znwc8+Zr$n%HQ)F;sLHn2*2NF>0^56{NT!h2tC)OJ(~WM;`c;tR@sI>=cX{;lb)tlr z7r|#=;^(K@pxfp>=rf|#*dVSS(=c%>{m5wGG=Gj^;7Hc z+dY*&598IVp_dV_1EsYa9(O;>#`#f&gE>LKoENDp*zK*n#*YKZ95oM~t7Zt1g$2>!C1z^7TSX?VcklA*gj@aI)l}UPUlLfC!%-Ru;{u#LFm3N`g zNFcGKlG-Y3`&$p+hFsP!gViVj1Ya2Pvf|3 zbJJO15>h|I$aZ~pxwlN(4%aL+pL*^N!UhG7225DUXK3XA%74Z}#&`=ILIgCYX>T|0T8)L^Onl>NUjeku_%QG|kXdZv|1_vRSPk`&J6xcncg4Glh38 zWxRlfw&oCUZ_F2%FLxRW6lvTSdI|^gCnFjQGkkV5xn5(@c-TQ7G@9jmtRVL0*DF?~ zotvS!w(MRjV}oa_FG27knXGX4=bjjQzQOB=CFPDKSZP!0l z!EB3&>)uj&oTGapK5X4O;R(_j+~x=mn5VHcu8sLLj-@jNOwl8(7(K-M~zHX zAh=M0b@CcR)F+Zn_l8{;m+<*b2|X422$_=A*|#=HcC&n^6;4{JWE9kYV*%W-x_jGl z&+HvB5lR{6s39;Yazx6L8Qz>2sdP9-9rrUvBdA?NZL)xU| z8ZasqI3;RVX9N+y_>$ZA`cRviZeHzSR8 z;gNDHef(YobnNCp+QwY{D<2Ii9p|8f_9cI(Eb6pvi~J5L&<&Xv@l{K>no-JW-0=6y zMtp&9W9h`U5*Ov)=BRn?PeQ0n%L6=jPA*fQC)o<^^;*zFuA^=G_<}E{D{QUVPsVQR z9E6;*GVS2$FG=~KqBAXa1KKDZ<)ov=#%Ie=@w?`91r>bAAzW(_0)El%0sM$kETD_xxHIdw+j?}C>KiPoF~ zC)(Wf#&&=fW!c;O-6}Mp33V@Xekkcxez;Y{Y9qVUPada>knxkAks|!Pb2gpdbdnpl zJfIxqNb=m!cN?=-J#)LPXn#jA*v$4bmBDVxC4FkRlwh(>OMo^1!&PQe!+OS<&xKe# z4v#vn$X!)yffv(_wkVQDU*#pnnVZds4YUDK#sT$ZddM?j)j&-RmP{7???F78&6 zfv0u>qy;fG{ZzQViN#Uq@>H08pccO%#lq;k$Lny~ciG=LQmOsgQ@|kJ zL&Wuwq_$5kT#^iY!W)H3Uq^KngLjy#46Qv`;(JpYvpH->#e`(8p7P?F`NGiFq<4)U znT+_rf{ccLwaENd9_bOvMxEz6wXO?Mdup-46paQczb*q9fBGi8!aL#(CloAt`OM_~?Y zu(pjCy5xQxFCGY&v?ux&Of)8u%D1)SK2LhPT1gUMyz+jE)Hoh}8_ya=mDvPB3mfS%qX%?`ZxE3PvSN z>6fY~ua(l{pG-nj$r!2z%_u4ha!dG)82Zb8h23sqg4PJ ziI@sa;sUyQ!R*oP`H}sY`EPf?%Uk2_chR1bx^Xr%3oT2C&u`@x)}5@R)$Ox}`^TLA z+Q1xK&Xv~4-!o;@nH1Ao^$A}4pfcd3`?{k3CcRpNbSs-|q8>ZFC0|WuyRM2g{cwBe zJ;g%|5b)*lcTVIkIg<7GAt!U5BE)21IrD|%nVCTS$k)2|+vW}d02k<5cv%`<=%n?L zC>Tly?kYZ61OU<`j+*$~YCug`G2O-AiUs296~(PgR>B`5n?=84g-tX%E5OzPz`~oU z=EV77N_na8l~gDDw&XePt8F)Th&I^~3VG7C`dj0@ch6GTwU!!G!idKq^cJl*)82Ae6>aJMJKlR2_ z@0*U)Dnt)C8S@m=ct-XmTeYB~1!EPP5w2E&215YK(Z6Xa%tE1ibv6Yki)msFGgcS6 znXqZ@e}1}nm-r-Yxb;X(9c&JJ4CnEy<4-3s3;1hHW?L^(SYgXY>0!rP5{o-K_wqtk z+SU$x#&f=AMD7wi@py5(kL#P2HVSb9AS{2P8;a@v-f=GYCp#M=a)JTRi;?m<0m|WN zdvuVe>w1S#2^P7nN0cfr+j&PS$%7#*vw%f^M!Gg?-32+460#MxA|9W0-mP(d-7S-j z=U0a-(=tXxRX%8A1TH8&l_hD8JC)wnlXWbqCcr)4Jrf=zo|jHB^0}Bl-RhK%dKb>Z zW`l004+_lH6E{e%<=Ayh|k)AIZkgX+~21y{FoTc0@jqnH3@br2Uv4C?eVU! zc?xF>cX;ZM4DNWnJU=@!N{h|c6G;0E=sOK*()C$sqHKl#rL zt+vt9Be&d>@`~WbZ2P@E^hGwngy?3Q^2%KuHxH9ZPIBLwg<|k`DEPJ;0i|yMjo%wga zZTcStrjl9Ncf17KxAvBYX&2Gw(+mSi@ImW%p++o2*C7`37G}Prii4OW4|1>g&ARob zJEk{lQ_7A6)Luf`5WZg*ZHy+B?TBWVvprk8oWFVJEp#|2H z&UX67Wv}wydvtAi+-LOsSHRIq;CN)q=^xX@3=~Pa9XM%h`=~^6qaE};W&4!VKvSh6~7Q2lTotRdLk&a=UsccWvdu$_ChX9zB^n*96#l}Ps8adKVE$^ z&GFF~1Lx>Zx}1r|ARmG4wKeF)sm0M8CI#d!M8(9cwP4ASmER^sEH<-tv^c2(d9-ED zwk;)*^#o<~O@(6}IatJ;c zMV)6qaKiw(2#+?4;#!hE1b9*(r5lJbaSUZ`0F@9?p3ni*HFiFg00J`yW7GEuKTZq$ zE8>cT*CRJV`|f$PejJnY4&QagW(H34LCsc~&7_a!6CQ_%fG{ZYY!^ILUT&twksn-&Cvx))lB;GPIeV6h?SZJ}jmOX84T?2)vUD zr!(JYT!TB===YS>c5k%>EIU?;`EGICaaf^w_obwLo?8f<9ajeHL13Lpw34Et?@zuQ z4$ES4au+2OHOVgwv$$G9@kp1*W-)q0j-SW#?>dbb)H!RmB7n8{ao7WI$kuhGCpSCY zUrQfOkq#A>fHIJnoMeCfs3fM;ve1bN?i}@)gZu&M5WZoml`G$Ns>WjLM4iU7Xg>Of z#nd7zT>@lovbMU?=;2rowa4DKDMF^(WuA+>NTEnj8UVuJIX5}ribZ7(0mtUQDTSgt zf|{*W@`23I%GM;aupciu>)vP0r1IYZ!i~hRn!S$7Pw=jXB=}iukYK zqia|sYrMI$?Df2*qWm>ZaR9Z7%R`Ol9a z;9d1;*&J)%8)JWvm6e>??M4C+)^@dov;IRy9KV-$#@iQ-9jbUc{;s)Cw(%h1`e-1* zVNgA|>4l5q$49j^iZU+80q(F%=R`!PdUW%p1~+5jGCY4kpMyL99&^O<#=BPbi?eO` z&}sgr(5-jASdJ^Ox~-7EVjDn%&A8rGFqE5|qLKeV?aL@t9Tg z5!5agKGcHK0(XuoedkT{Bpa>;AiAjTB{!xs7AZ*jhl#XHTxbsC0JoO!bjo{ihJt9( zO4cN@lpYHlbYKH{))&gF^MG1dttwK#e}Y{kfbh~+w6RbS09GjJse8gYX(mBgj*`~V zq$$bKo#;U-rw0KFBKm}im_4pyH2#$cBW_S9T8qDK`WR@rfTpf-k-UB{8 z-@w%!v$7PT@q*VdN`CT?f*Ha1$|lC05rRc55**SmStAj4fZIhaI6RIIP`?J(f#gxM z3urQ@;e>hY8OyAT{76+`otlaU$^9i#$3R3BpMZ8}I46lpJBdk^6moCz;K!C>BFi}Y zxm*rBXM%6rI+x<3!tlqME5?Tcc{Af0v?7<6!{qUeZt}AB6d7VaujcqX+4^;x`HN?~ z=6QeC)TKofp{c>7F5miQJtZC*&9F9%&v{SNiE|__f@*R8+=xaGPE2I6rqi;EAtpO?}+2Wtr@ zeXOV5Rf5HSStr(Cj_VKniKPO;_~Ua;b{QATFWqcIb!q;DXsG^?*LTcU!Ohoz>68ni zJFY9yMu+nwKAkXH2}#Y%w_gx*DnllBuEY%Cq>z;XM-Ci3y*l2+$-bK4&eUx|OXfV|8nrndH3@|X%7huaahL(+M!$lyXR968d5_Kc8 zxFfy_7E29jxD;2mmjDmj&^M0A8F~aFtcXk730%=6}oj-9aH#LxQT zXR4ka`pN9O@b@!gyvWv9d6I+V-YoyaXPtNIjTD*#qqD_f3^*5ES3^Ibap)t#x1CkR zW{(P8{>;>zOKbC;cTqo{rx55x{%&;;W4z_FKU0eZ^$$i`UXCI54I_pfcV|WzPX)OZ zdglXvz>QqXy*28dBV{^!xkggT;P_)+J)sB31%cO`^LX><8_FjP9}}^Rw?m0Ye$grZ zmbOT-(rZ3T$F84?lrh`q;cxj1P@i=n258V%+fZyE6u||T} z+uhKZhtMi`9y-I3$w^#0ZtEcozl%H>?--^E`iPp^*np%7<%Y-96EG5vhJGw{rBnrk zrx%u)NRztStsH$i=rR37j=!F|ymFaIV(RO5F#mDs*8amWlm^FLia>XUX4sz+kYhR{ zE)nPa54F&^vyZt;R8aK=)|kmxt}J*-KA+Z za=e63h>l*F`YnIMu_mx^qOv(mk9Xe9Emte^?GzHuPaB(4SEFi-aSUN%dok+DoQY3A z%DQ*`oZ607XY5aznW}ZlM9Id;Ks`&S0S7-B)x*SBF$jK%HlfNpNBVfay$Vs1NDRpk z^aKO7uZeDax8O4sle&!N%~AIzE#mR`&b9^2TH04CA^7cq$*@@s#gu~vkZ zs$6IdvM2VB@Fh+Z8N>kL(<{}rOjWgaK#1w;RdSV7<{R%#<=+QXgy(^gjJ1^&n?Xwf zJDZ{y*u3iAH6qOTGOzLu^3&d~k8@yv#`7wz|L0);>lt}p0Z*weA`nS+kDXOufa)1P z+SppSuM7V@-bw;)XeQI0Pr3h7fTLCiAZ-@k}B>~76=&UWsV*o@hjQ=kBp8=(? zAEUhzM=sh~9Xcl`=QJM(#3`AV@A47;_P&w9gJPv51L1MZVOEL2@^rRJ^Mteh|1Cu8 zjw8k$w#@(e1rZcAg{%S~#L)p!2p-y;cS-)^s5N>2|NkCarF_934UqsajDrOsbsW)A z$p2ZqBxO>J6b(?BrM8%QbRRXn-57F4{;~N?$zF7o;T)-dZ7p0 zC-N(c>8@&T%iW)JKD|o37_re$*@G#Q`icUC`{shX7LrOm{QgD%85=89KDQ3=53HMc zNq?et@5d<9z65d%KD|e*zm41?)`#H@Yz3aPGaGgP_r9#CK#rV|bLyyKC2&E*|JhQJ zT->6>x~Pcoz&a^Ndb80#&o6rWkdr8uj;g$!E_)9!vHxD}e+HC9euJ~bV+HSPoJw4P z-?fUJbh!`9l@q-~LD=cLjLNZIS&9Fj`?FqPz~#I-&Mv)&vqVqbu7DDK*0_zxH~08z z`1>7S9p#P&36{M5gC!8`vi<*3Y*+=wim^O5ur3G;Zq~UsdHK7vGb=IBjx;;j*Vv9C!|dnG4Rif}J(!T)=UaQr;zRS3mq@H2^zP9i)gUe9OV zd-{K*Ck;N2PrqyGY;w#*54-5ueTA+f`_P5zKe0SbJV*uYJu3Yz4H9XVq;s)|Ib@2- zn1T(p?t}I$9qw*t4GNR9-cK!?CH(KS{yp&Hqg%=uu~L*Ul}VVXj-oHHQ~YO*#9u__ zAA=$it@1g)M~pLv{XgXU|HyjFs3_NPe^?QehM~Jtkd`iCq$QO`Bn0UgQVHoH1*I86 zLP8p81?iBG?nZ|0&i7`!_c`zSpSAqvF!MZjUhxZ1sUdT9QRDv;8G2mIoc*|c9w2nm zS4vxO`E5#mRILFiZ?oxd+vRj9$sA}VLy8RQq^N+&Y;tQvpelK0&fh@=8*YXWgQ;Z1Yl+r5 zX+ZV&$(=Cmz~jd+s%6n$8p-H8JKpN)>%n>-Z-qjsHp_o;bx{tG<2;du<b&y3Q6mfySdrl<0cia^&;fh;XjD z&gr)sMPGo5T~&z^_VOudT4Gox);syexlZcee#EWuYY` z_Vwt;>F=(kleU;pYF2gB9~_hAjGMm@{)ETv6e|lIiC1 zKxW*{J%n*Gzfh@lkvHDf2P!oRr{c9b`;5-S-mm}&~bC6N$%N1Jd|L@84KWqOZL>js=D>xxi>FAP$VFg8x zabCMRnG-7cahyypWRCz4(TSq>D?9CYl=ZmOqKV*O8U=0$qn!1d<;T(bc^~AHi^X=n z^N+f0PF0uC@B6=ttz?=PYhTKqlR*^a)M^&-%JVEG8G^LE_f{kL0E}>oJdJ1THFx^L zyf5%x=q;@1(=RH{U9W41*2c23gf#(0?;Vw!>#JT$hwmo15{K&iuYSHSfB|^)&;r;1 zGq+w(RXemkrzQo+HM{B=izu-BbrB{__5QKr0({Z`VFBXG<52Kk%^Cxp24!h4dKpXfB0yEX<*>rbu*7XKmRFIIt%~wtz6c0{(Yb6)R&Hnh_WE+fnZ1CJ=X|#iMA`#{9PLxfHB9w}z5bD`Z1lO}V~2!>)dHKC zEY+{)$YO0g>dzKfH<1A+pVTBVwx(3Yw#*eCSI+xmY5&-@-;vVg?8(PY`v=m2aR2baKLsFJ`q3>|Tr*urE)r zibnG`;fEyETM0`2pu3s|gVF>1wO-AongmD7VajG!zP`cV4HC%gshV+{QV`cM_O6U% zXtS?bxL?u5k^)W3x>t@N5D~p%pHgQ99xN9b-Ve{4ytd)-h3ST>;SB9m- zN%ZDi{B`j7ZNEFJw3W$BVU!suqVoe#WW%bg`Dl zM7yFkOcgdnyUk*~$uXh&+<4U?|6JC6w6lum~hc!JzUd3RdETMM`g)+Ihpx)sAm)m6PhHN$Wpx zI#qp_e-eym#X%!Ev{)-Lz?;6;UFlO=bh0t@T0Nmnh+%j9Sz{}K^7E`;`QN|nsL)Eh z{iX*FDBG|OpcyzRm!e*8lb;jct@P`K4J>DH9s*N*L}7914QwQ;5DVRgO#ZQ}j|WKz z6vIBvNqmjlem7Z+#IhQ;tOJKhFF3~R6*v^KY1ysykfTQKGtYCKZuN9~6>t)kW?_f086jqMvC$T-X&Zl;tcB=ZUktJ7|XQv-2Vr(;JD@@-@ zOXu^(cLotPeckCU74>0`uO8n%WTY+`^h#f=+BNF`qP=qRRj8+(tz}VSo(f&Z@{X8F zXO*)Qv-dw4`{C~5WP5%vaB~yg)0X>u>$lHy1E=#ALv%h&Om<*A~+PqUs`SU2WP`G7N@rQ#!g{A8}A$ zKFLdacie-{TRTf^z63w_@o2rCnDcF(TzqHIu=DjY-g!}d_+&)W3y-_)aca$jgkFYgBz-m{UvOYP@}LYn*;vL4-0&YV2jQ``|R#;e920I{X4$WO_00R+22E zrnc(DasB3c)li*uEZOIJx4|_g_>rxsT_W|}cI`?xM@f%Mj4xw>oE|&UqOAWK2+TUz z*Zv`y`UB2~kuX-PssKDm;ZLe@u2QFlgYNCYtD@~lV5HSMjaw;`pEa5%_v}Sl%WatR zi>toJUOluNv|DED&@kLSoAhg&q+XiQ8UB!16II35@oXAQe7fe0&Lff4uK*O7epyndzu1!6>OHIM zWb9=9x^+$MxtLRWc%Iwhe*SZ@obM&2Zws4}s9lY@9)@z)ofT?s{SNsyLu#8T$OheG z2igfXVmV%1i|DG3oNXtO!b>!k64_F5r;;QIu>4bKrB>uMs>lOIj3u9R?vb5Xuf`Po zAAOs&vTqEFzOKD{`N^pHD$-R0$?ppp$jo%+SfFAj=9kvh7Xl z#pPJcVBN#_i}MennAqXM?*R=@2(_DT=0jO%i7B^k1uNZm;~f)v8FX-F5wwF-!w-{aY0Q zuu`yx1*yVzt!p19Llp){_=zp`8maT0ARyC=tfS%EbQ*or!AhDdyi=0rp0T0)+*fHr zb@-%5rcpjfLiKVs^nBJ}vmNEcC~Mqp5i_#ZN9YV$zqeff8sVv_rmXP;!|LX&-xqs; z1jPP1t~^><7T0G;JnHfv$CJNAy&d=QA4RtsCUaBC;z?aPe$+Cc3P*qXPzfr{&;)P( zEQwh;PNHWXlR3F!?$-Y4BY|1Rg@!!!NM>)k@AZTiNVYi!{rfIm>`m^KfxBo*z!O~wD)teVf7MI%!tgWANaM|w1FV}pHxc9x!W)7R_CC=K zP7eD&eAcMWJ8g;Sno*P9AR&6wx8kVHcue3K*x6c^t%Q}VT-$ZJ%pb^}CN>D=qYY?B zs)_Ff68F`TG`}f+%)BY8h?Kbg6)8B`DHw#_f`BGU$2uKV>AEMD6cQIYokb9R5Kj=^ zROIiLSPoyj05Po{6B+yEtKQ1Iz1AZIoHc_o8yQ~MmuXl9QU5hKj#5MMvsEoOMvKC0 zU)Rq@QHc!Rrel~#=zSqHZ{H}QV$R+z9wpzH7%ww3IE-7(1SVHKDrw>qqvKTk7Ao-` zt?y#p7W<4>p8v)VF=?xZzcY_2sa;7X4!7RFAUx6A?GUkj59t*ge|2vtN13!JE^antUhs8~2oo{Lje|z>*&6XlyDH-NdbvK4g5-@@!TS zfpqX#NR9L`f)n%Uc%G2g zs=Cs#3qCwh(pEf6s0E}}=GkYnD3SK<@5lzn2!b-A*M?Z~wxz-NcIuXGA{i!bO=zUL zkPiw}nYg@A0V+Rq`pwgh0n!z0Y&qPT=UQAvbarP)y>QLjK(=UC0eTl#6$*_|Xcf*c zC=k(^Uq{Tr)t|_-XfPk*O@Y&@g74Gm8p#<|F&s-cgZzW$C<~>yha=0n9q>Bj%SLDH zzKgU)xL7rzCugupGoi67rP5dN&v`wGvm_rF&RITWY;o>2P78h2YEX8N_C|3`Co|G< zRSZIrD`11ljz?Y%;^Uz&8fI6SwBk~#*chVUv(lPgc`HsbI0svHlUrTl2d6R{5oVs_ zUn1aiR7XwdZGRU^5AP@k_FgcXVMHg_sJ7gA*A$H(be%3_XhRT*w2l3 z{g1{Ytk02x#^E%z_R6dAcIIQUuarY08&Eg&h zB@^>>huNG$18~{CwD{q?b7w_}!E*ddQFcE{iYC01f#O5i6BqHd>`%7Fa3#8PC&wLBckj_(z!-4!n$-q>%{#Rz-aVVY zrkp+~5~t^vsgNF26?5kfhLz%*HQj$px^L)EYFjJl{PTv}aRODUAO2VW#Fxp40jk+f zjw-|iF~M-zhb(jXfd@37o7^v#6l9)beSx;@$qRfU6v?}h)xLYaC_faNd4CGHVNp=v ztbDoW%~T$I(~)1_jL9+1mV-v3OJ~!Lni{?>OXVPZBrI=E|$tO{h5$eH>H96@Pkc|`<`qRI&q?~^%M3}MZLUv3-7&mAG=eDR{ouMJsFbl ztnE8a7*G-987tH5c{ez8-v7RymEj}YzAHg{(A|S|;<;jhq*NWj-4B*QmXjZ17ertv zcdwMnS)h@2yD&|35H-gOCI?9h`&A6WhK{~QTc%f{#$Yf?ux)U{K9yn1i4aU|2GXUY zF{CJ0ZeS_GdkY__u5wo0PoX8I5Y$%H&8gzOS$c{8%^xzPh;(p#hMbHLvuWO}=(kVT zVraNz>&h5kI*-b$0M5SO@X=DEqh1LC+n%1Spb_jxhkCn7XPIOt9g_sFzyBJCzNbHq zd7He0acf_0VdQ2<*GE84@=XRA1{Cf)Wg6`UCqE93CK+qRzb$}Y^}$Om#UHX~)Y>R3 zgeSlLpB@bbT-tE2N4^=4O-DJ}Yn1PQ+XK580_D+iGsMsmnLq)m&%+O#WhjmmfMGYa zXl*l<)%CV7)%9gH;gn;q*k<8(>%s~p zM56Buc_ZOrBuqbviiU#d&enJFr|9^x+l*xaoX{$J7fRb4<%S%jylH)r7rd$~uLNXy zWbWniqofgvIDq;ELP08TqB&g1%ppozw^j;NB}Ortb`X zs#h*qCU+hqCwXs$zBwlx|5(WIw>(2r7=+t!xzK=H*CwC3>;C;TwQ3gmNVCDS4daBW zRI(N0kY{&$?q=2_=-;@n4|iSXP8GiY-A}Qyj#+2s*&dqt=R)*N-(`%mx}L^)F*!Te6*8YglRYZphc&zI%R>m|=kEqNFseF)JuO7aUs zrz_rd$n_>^dUMeiJ!cyEuZ=#;<|oryk!KKBL-JH1{oi&pfWkP+Pz}6w{!K z&_7xw3xhfIm9^GpBlm|=AurxXFKG%m_ZT?*h*NwNq!pbk;qV5=M*RxC=VR##i4$b5=tSga05+P$IAL-geSOy^W~m(o!K9swX=3eL>FgkE3Jr_G5M6cMMF;Wv9$%#RF{8N>@6MIrD?gZ+F;nuK z?@3Q<(VT)eQzH%Gm~5xKp>)Kdme~EQFCU9B6x;jMAY?4X&rR*muO2N=oTT%Px}qvc zJ!54k3m06{=h`1N64K3$?0l{1@lhta_m2H_kVL(rF07ESg4|cLfF-|(^t<-QvyE^8 z_#wJpZO@0@gPjQsD_ij=(JmVAi>Yhshv7|C-Z52)mQ4<0C4};G_&Zq<-`XO$E^r7u6QEySWes%M#CE)phXyxGRwf3KXMjjzJ1oH9+CLXr1lHT*SK4sFM2vy!Ae`WNUbn${kR z$yTl(&M2kIV3e3(*X0r8&;6(OhN`&NPp<&y0MS6e9OSq;E98SyVVZ_^GwI_(Hito` zGv~prH5B!{sK}tYiuO-I*J@*eZiT`T{0!3C)trW?>qS{dlrUCyalCL0I zGVg9={c-{I$i@f4uHe!PDps$vgn0(x3(%)Lus%tufNb1AHQh*t^cdO&A|jI2#;*n~ zPO8ygM-89Aonk&diRsBnIo!d~=K1y7_v$FYL{cNYqxXe7XP@cHJNiXZvo+1)TZ_3W zpXXdz7Wg-eraU^s8NOVw;Ss@uo2cJiUR_6C3-dm}-*uB6T@yZMH&xZU9?z|LF~FOX zcrr}x3@P%#sS@u0Iz@+1Vx^3Vh3nOd%8<;%utBD#1B4#YP1-{Xq2+_=uk>H^J*#7B zU27C;2PXlskxp@~-e$#4?yjpHq)4SeJ>g*tQImZi;o6$d&>XnE$e*ND21n9}r>njS z!pJw!GX}N3G^RHORLXC4s*~bfq7L)Pl=*zG%oY|MM$wP`R&^Qt%1Yq^Hy$f?>c35j z84LL5jIyg5yE4Fu(0F`Xf}WEg+vx9%VdSU%WHD|hE_~~}1=<*!mOh6ybMgJHC0DCh z`fWXNub>o^JkwtojKz;Hh~ng8-RUXu{dcSaMFnkkv13~R@IIhm@?SEi9}&Kz@xxOF zh|b~SFFSSdU+x^=HjHz}r?iziO)=I1?Dd}xx&p1A9Lb=gOnCqW))&rj3iiNzQh&&! z=&5!ZWCZdGX9G71f#=;m%Y;e>X_Ojn=iXhjdvv+HM^<%&(AiI zu^ixOZ{3&27U;i zINqfc#3maTYcwviQQRHfFc;w*re~d>Q(hcCf9IXldY{z$w+`sjTnw!@*iVKr>Mv7m z=-*eo6lLY_bL#8J>xC)}YWBWcDI&a!zn7OqHg@@jZk@DtZ+D}54ZAwpL7CM zs4tS>V5u0x>0*Z#DUWmEy_Bfb^Q@6ONcmwy=Y zgG-)bdWF~J75c-dU)6i`eZnkBjXtgRx`!lVOJ|KByW^LUVj%Fs_bmhS5AydiTEE`1 z?^&L+-n_rmJPkK1=Erw8@sq;Pvc6xQTV*rLee3XeP(IKil=*(bd@*HCUbE!m%j)sk z#S(I^XGO**aVIPrUkP!iAEZpaCet7reiUxwb1vA|)D(z5 zpR%LU;wfM?$g~kCFD|>>6c3!XI3$Ta#d8>^JDJw*_-bfSJ8jRnCqLLYL+$U_>ne7! zgg%AjJO=eN3I@7U`%STN#~z5&g8bvNu_YLkma1D-p+!V#hK%&tYHl)YkvR(4mnvq7 zN({{g87P0>R+Vu3hy6^Neh{TtexR=;iLs9mx#}R_rkWW+aAdbq3fUX3{@^oS@ceoA z!8jXpgn}Ze=dvc(J|dbV)&<_s6!+W~o}#+EuSM04wkd_@)Q>?U|Likxx}K7{0Z4%r z;N;h*gzWs@Vih?~9-(PMrP#49k619o`%;!|m-e}G?B&#K$y`*rPZ`m{H9&Dx9Z+Dw zz95&D!!fyD(4f#p7=|fJ5wtgw^s}K@#e$ZF)NOd`<^5#n14Z%h^x=g;X9aD9+|dyF zx!nPcTLVga>f5BIw?-yAiP_>XYAK(~Q_iOQkfd*)g7iVyk(=@7E!3IbpT5TnSa8M% z7;{7%5z}{+d?h0q#COE^_o9E4C|C|Wpxv~BX>Sj<=#AQpWA+r;@fts#c2{2CmZv;# z2SN{;cz4_Ms<(;7bc$;hG3)yR$-#n~*qs-|#UFTgI3PdOqG#Y?86B0tW*pe?>RfI` z5H{yMw`e4jk|PMv;w%Nn|6V{D&8V2f{i`etFKRd9YV#^JvjejG!}P!Iq7MD}?;{ET z=a(ELFgOTFCG7BD>)FrA%8DY%-{nD#d>yaXK1$rYx7_*wp(I>(IcX?$b@++c%&}%q zilGtz0Z>pK6*lUj3WyFeqs97~6r0Cuw#oI5bRmH4Nvr|a63w{DPUiK#5!Ql#!=m_6 zulryuDTtGZ6L21OYPoxB39b(bO6C%F z@xB1FY}*>kpP39l+-rL%)txa33%X{AqBA^~TYjLbhWGfc^PWiRE*38zKs#| zu=^&T_A*MKrDt;A$Pb#5!p~pfE(oxk^CXnnW0UhSF-pdn&R*mTS*0Jb7Y~pk_Q_(z zrmWjIv3Q zRgT9(;hx7LW2EJwDCXNiBk+AjD74f^wif;sc?mA}kEOYXA zF@3el7{zR7#S>@sobno}xWe7fl!+aapwV9cF%ln0rXWvI5(zo3I!k!&4wVSCmwkU1 z=1p>WT`v%G+56N*le^dXKP&)bWOX*(=Q&%4A+Ur`(zh0`9=^s3kI!+VGiBUTzel)G zKVI7`&d|mLv2R$IG8w{K69h3C!vAbdN+iK`kR0LxU4%tV(H*AWTy`{&8a`+4*vCc| zXpld~bG}WC)SX4u{)JZ*D9~*!>PZUth<0j*+Z0r4w<+c;|Cb-(qC|3LpH=EzrY<m*uv?2O-v!YD5m|$ z(ez_8S21J6DqUvPE9j4hbB@>*V(E3y&?8KO1CBtMv^uI5Sl0E?$S@J*3orb!?ma~^ zkkOsKQXO8PLXCf=(mj9Heocadth37lk1BjyZDViODdToAB?Sxnx^Hpc zf?Cc1fJX?{!z-_yfbS0JCv#t+kBM%8&5AUowj_GO*7I{MLYuv+0IaK0p`$%0EcL{P z;z^*R@oJdq1{S(W$G$j05R$UbBM=P0BZZB#+xJoUx+WjXbX&RG@!dvckz(dZ*Ri(0 zf02AR;R|{le3Sy2f%iyX{Bh`^%b{l|OCKE`2{o4u4&U9o==yS3kcEkN()boa#$Iai z1DEh}u`0>sx?J+W$JW{!(hnvib;Z=l;gm2MK}Gb`sLqLJ|<;oa2_ z&v-%REF?AJP}*Pk8a{I^2g&4|NNj$)F@}LtZ(M!m=h_{*($+`pvAgZhd~`8xOE9gl zxL$vr@_f~phu9wB**xv)in2sSizLIaa$;K}`!DXf>!(lBpSc^yZ~bghpUC@vNCg`!K0G2zzN zl7{ja0=R}oyEt?Ay#`T*ynY`Z{Yp*P(2m)lWjbtv$S?XAqRWyh1pQg|NA7h^tf*BfDIEJ^H;<0!sv*+- zC7u!6~CQ4Db0JbtxWtn7+6DE;W?46krYHw&;)>im?y^sJFwDYLP(w7ix z6LJU-j;Ppc{!kaeuj=#xNE#%>M*Ry~^?Qh)XSv5ot14w3$*r8jlM~2^_O$Xp7<$)j zuo92ZUh9_@&p5`h!g8uvfVP-?2Zhu`*HOKWLeTmZq{!91TX-l@GDETuL8cH$Yx=NH zXAq5`cRsN`*`{`zz>?mIS+OE$bp;yateL-J_~cv7Msa=5yPY4Fv%p1GHWt*k1{>*F z2=|_JE9;OJBdGQ(BLm3q677YphRWFBiPA?3yqx*re0Jages$FQAvycK(%ZQdXfsp>b2^ zFXxI9CrXAKS04FK|JlNR z?R0<=%G<8z4ju_V{bw}2tZgr??fP*3p4xEC--gZ$AR%7#aNJen?_bC<)9n?OGnV94 zcJGgl{Fg9C+=A1wZa>k<;@C#4lW5WsJRucDD>chmIjkx356^@l`j(oYDK5O8{7)(_ z?TsJp5nt@YX*oRk)9>DpYsGrxzd3sLdq6WF!uGEN;O6LuD0t$#??pCCTWr&##P<~r zN_?+4UR-He{{8WCz=9Zx_-}0Zz;|lj&wFiMPNiW3=oRHZUWj(`;Up&mu>kOyJa+I1 z*48z{04wf?iJvIxUAH!v6aHgx8rE<363C+SUu;(B%y-uX{(VGxFx12{&yfFu#Q_dn zrj6g&1v2h}uRg3V+WzFn-yhDy1K+!DM&(Kh1}%rV6!d2kEz`Y61awyD(jfN+IctHf^f$5H+hD{s6@Y&ztuap6ESrid_e!FNC zQ9g+8!$knFd5gItlF~9B)S{GLz8w4eRlsy!Mju62^!dM+I33-d%0ULz8lB?3i6R4` zoPgoOzaPvKyM0=F1y@<{8_W#5heK*9pg%rd2#^=d)*8Kk-!}G^2jZ;$BIWOcxXRyI zFbAx~XM{od?F|0?;U6?eaN@ zqy-vs7z@iEo|C5G~JNOFD}s| zlxjwL|GZI#BY12~%Upi&?FGv7087meGMuO)}d%j+sobE04 zYAQc^F%ubSrLE(q%pTI7pLIDMchFSpW-1_W8U2%(T z*aStOFgGbKj<^QCQPtk|N zqE}{r0l0Fh;i*Gr(~)XXr@+8dC|w*Xeiv8mGQm_efK&dKGkTTnx;ax{eRX1$n`!}~ zlg8)AbFS+V{CzyPkjiIjXCQ|EQdhE$0B>f8e+ovl2Vh_jYn!(qQT=LrBg$0nj07+f z@4x(uKetYQ-&!$A+w%5DfTnyAJGJ?bKBAd~+u0q)^#daA_V->OC~CBFRg0*{*YnYr z>3KZ&%{P{@N6!hqO`{_2v_Wn$JfLFjy4mzW@;nc)21>3@=9>a~fd~4-Fy1xYG@tXe zm1LXZGVj|Atrrv~UJP81?zi3gB;#XGRy!E~s{Y(CChV8p@5O9?QdB+5H)U6Cw4#~a zXyiKbg2QR8z))63|3&FW=HCe%0h^M2k(&8Fa}x@X=h5)1&z4QKg!HHk{^%iW)UP5cRvPV4`}sV|LziYls33!fyj$| zjX~Fs`0ApaOy67z|L!LW^ygX%9Lx0?{VMs?Lp%Y)A)5GPg0`SH62@Vx1rR%>YoPMa zo?LVxsIc`G3}^NH=s7@yG5k8h}$o-4{z0lTAp;s+}H*28%{At%$Y4|?85BmZ~Y|1iww zt|=1ySh7x26z3T0%$sp0VABy*7zt!Y=H=Vno+3bZA&zJe^NNd1kiv_*Rga6%?=9WD zn5jdP5+U~Ly)2Y6V%+qxDx zzeR)|sH*mYl437tV$vMgQjfCTzAHzQ1sF6T?uJv-6-^)NE+xap!7*^LTP@b5{hfg> z45D?O7!U3J&*}l}^y=$*k8=W4x_%b?L&XN5neIo~#L4Bnn7Nvwa*#n}CG@9zD?!q? zt*WV&Ey)2J#8SktsexVPi$^ogisyBJ-Z1eTKAx@ksmJS}*Yd`DEhixvthWB^l-N*! zsnb&|Ce4k>1~xUf`!^EN@*gC+wf1=n?Glz1z@nFY9yMg&0(BLBiMNNH0-nF0JV^Sa zDw-dgpl;wQoe^!>Ku{g2wgvpldkn3oYn*P$3;C@%U!8G)uuxNR_+Q!&k#ffGIt_yU zFy@j2n>cCqtWl4sI@b*g_i}3?o1#ASBZJ#>`k{OVm5hEFJ7w1POLpokzzo)B1k=|g z`unR6x53TM?Q!dSb5)%L7&pB#SdYvBTjUY{Mqx!Vz{-~e$;C11@qYO|(@xMY;0?`S20_6pPrRz` z5;r@fQhiUJ?c7bgjufvTF$CZ;=~XJ0NxgT3v-~`=xR=R~28u%;{~h2u zk_;#%y=nl3M0wK}lzEpd&i*8DZ`hIY$Gb#KKFwxnrFdM&vwes6#MAzt6awHA%&mX@ z5%W#=KIR37S>(IW!Xhiq%A zy1!24$A%n`xRLle-0*j$Yka)q9PZ!Bxq?E*unfi4(~)Kz`|L1| z24aTH1(nPwBG=fLK4-6G1N~s|c*gR1KrAWs@06poGY9ud>SGGu%e{~!yQ&EwCQePz8`x}@79 zHB)$>xI^EfWbU>HlrVG7Bg(Ui)W~IkDWU%zXACTx_4P9!zz@OEkR^lU4J!k#lv!8t z2s+M-#VhSF%Z6#QrtkVrZN&TudUll~Js@T<*#4zm=?ykrTS@rene zG~*kpQWCDF>!^~L;NNJ{I#fD8=o^m)r_SU8(;SCYR(?J^L_d>QRpd`>AqBn9z2Rrh zeaBunjL##eMEJA z4iIvru$ea~q3Gv|SN?V;H!B4f#CU9=u(T8We$a%>0}F7S9XBL0-rl&Md$Sk6KOQq2 z3X6Hdx_29103w0Og+exk_^;Ps-rWYw)^gdhUsCkj@oIO%bb5}Ioa_;j7YJvgPXN$q ziQWeur`+4ks9UX1aUW4W%E~({0w+c{&3?t4vkaOsWE7CDFKF$_XP? z-8`A|b;x?P(|F@^F};WTIgN3LVsxP2F1?f%Ig<&VOHd{LV<8rWaS z6hOQMThH4$MPmPl{G#0F+ILXU4Zb)40bZ$Uw;_;M&eV3BcIrTM(6!PA6A~WzZ*^T@QlTqE8T$M{nTl=$w6ynF}5`{7}3`7PZ}RaB$DP50 z&>|r*>-oMn*Q2}?0_|@AK#c26GI4Vh7Cq|rZTy>DJ>!;AbU`5yC5zL!H_%RO2A zEeQ^)3Wf$U*kCzi;G=RZL-N8c4=kU=XgSl@o2tWBdeZu9k^W)$HD58A7wfZR^S0rP zy&hgQe9xB6Xj$B{qw+9Ci7Y-h+}{SLbk8?JW-6Wat9bJ(_BQ?re_7KJz$3ry}OUB@fJ-sDxN~h-=YdnDix^LO8lA zT}x7r_l04@#kN>W-`kD=7`V=rQ*isqA@sLUHxZoBhq9#@UoHa3V^p{*^&32=ON^yJ zskXyBG+lULjneIw&qj-bR;qia>`T z_M4n!Y@hbDtv-Ok^JE*QU_9Lk|~kX`p}0b;}@BLtiXrp}5)7?744~OFY@=g^ZD`8ZTQun}hXBY`ykJ z5j+Tc2lFR1BWEcmIhbZ%Xr|~CT_23)D_Lc1#v4%L3X8LhZKy*wVFX=QVy^MaVDCUy zs8Ld<%-`2U{-k-Wn5G5Az`nZTRO2``gHA}(G9 z+@s{z<#4tufY()frIQ|rw_Iif;C8QbqX@CHr}D}NP-;!L6U=(wvT&d1&VcN%ybgmh za|kiMs)Q9ZZf5K&8DS~+hBm$XVKI*FTNPm0v z;0y(e6ThB3vqqs~6`?MCS4ZzPvFuC?;A=`PNkh#u?34I41@BWA05<}~%TAQc0{r9Y zvcsgjls|RB^ZaJ z%c4eRV&KE8b-_Wr#nbi)QGny-h(2>|gSWPLZUmwQvLgnz$uvb7aD4!s*8)VnSyA3dB5Sy_dA^(lN{?|x zc|)P7*bK?|(y1WA(9wSL6YjVqELAYjsOEF8xkacI+WOt_@ihGVk|)DDUI25yJbimD z0B@*?DKeqmm(TP-oaO&I6-yUenpmX4XL||0M5gY=u1HWs4mZ!d?i|2vW9KWYiERl` zt}RWWks9JtKy-Uxq$d_Ly1WUxUm+uj27P4m(Efy%Z@Vyy8UUyWWH^>rMdOkerq_-{jT`Wh=WETJ zM(Y6C-^h{vDP1r>xn&7#xjDX*H)03cqhTpb1EEV*ShKlCfxjw1V6Q%%XzV=Ue- zs(Ux0?Vp+LA0w0T%%kwF_C$*B;bFh0ot`?qg01wB%NOW=Yq~ha<*`A#U!L21q>E{_ zP{&6_iV=MW1Iptk-O7I;=ZVTV|6B1r>NLIr+$FlOqJ2vag-IG^;ThfMAc3#aCWAa1 zYjw_F&loe;uAKr1)Y1dgvW?PEy<>3=3(5O_B+W5lS2 zu%F(l3*Zhkb*tp+wq1vW^T#gq>nC5}$q-W+>6`x?-}4OG(Dgl*whefb!$>xkDirZ8 zI=JeTs;rKx?12+?&0B@Bhcak3J^Bg0E_sp5{f}uosTSsk@Z#s)i4X%8)H2!K0*!b)+TyVTZB!SLz2CuEqFYC{gY2!|g;1uhz#jhH$3w z$1Q7OHf{7pg_%HYFzft1I(BY0yWr0&E8@=@c<4uK_+P?*xsWbOc;A~daB8#n_VS!d zuWYrX*8Hg7@;&$#mKL`@P-oHfeS34o3e(EXZjU^?-)-wK&`cvdvx%yLWYBQLPo`Vj zFa$sUsB*2}wLnWO8CM>jtdEX@g{Dt?7nbNsJ3uR0y(bdzK*VsQwPNYR$-N(G zz5PmR$O_E*H{p|!c@L~{#8)-)HJOk2P#w{oNA-h0pZZ`O9&{iQq{h7HU;>TEc}%$< zqSU9`tv=PD0xI~rROsTN;gq@p)>zy^jlz3W1v(V;)wh;p1tnILYvSSW(N^#k>0;1N zIeO|TimwZsqzK5t`T+kzW$EYx1?ubSwR81KHAUYtzz?-O!loYDF063ao37{HG@h?> zgot4YJ@~||{6#atstikL#Yu~Jt#~k7k#Hy0ViJI`Dn@N7P$KRn>jp!vYt$fWRe0xf>Zvt`+AbhrVn+K`UR3QVVs z@2fE0n2ZNIxCHH#+|*NnC8LjfR)jsHQX@@#%Qd;X%U!clUhxbC3+ltmw(P}c{HrDa zh{he_4Rddi&6=)KiFto0pIezG;FRy_C+>T0y5HUt5B=B}XYgcvy>{wC%2RKDS2kT- zm=RWdSSK##J5Y0UmV)mbnL$~%X^-vn@$y}baY4&L0m5FDj$=VLY@Gpxkk?Jfx@&*F$(w`NFu2o2~XZ=PS)Z32k98`%?Cs#SQ;^3V$PQ#jbM@;tj2NI-cft zDFYteS0yDL$p<8w2=N!18-XL(?b@Lv1V?Va$c*^<4KVRJs^%&ts(iyu zBt54^U4uYOp_)lzn?b3|7PoBtd9({x0GjwFl@k#HSM$c7^iOkW>Efnc9WF73`9`Q2T72W-JJ+^ff9=9M@Pp(x_ zah=g7j=)_6A=vSP#Y^{Tv z-oS-4IaBigb0Lv_i$tvlvahCcp^H`?%wV(V(ZYTq(F6%jQ-~AT9&mQlcH*&-#3m)^ z!ESnk<7f2s9=@SaPX&a?XPq!@wLk>w!w8b>HX6RvyQ@7e7X~d%yUUcKgI`lvd}v#*gEv?7jw~Lr|&og!p?9f#in(7TAWd!2Ju+Yd{AmA!BmIMe0^21QAF_ z(=#n`k8{yK$Z7E?vqf1Yg?^p+q?o|&Kpt2^(YfhUo4@e&1?|bq?ezuQF>%MEF5-na z*(6l-JG&)DInVCXo$(Ua71VapRTXyL?)&3An3W^Md%t>c`QnqQC(FP2EE{~m8;Efo zGqn6jHBEe8-y-Y0t9W8jJsDGw&cmOW{A_Z*5`AuHx<;BqVa3kPAg)&^o$?=^9sMj<(rV)`m}EA!gEA_%+n0U7Nd5R8%{NOW z7M8g`p6Mx^IwuDHW<+O{Whl&u=+!G3Pnr6U!|6gSAnDWS$&a=k_yK2)w+j!dGj$qK zFM8xrsClZt7v|Aq=WjS%7!h_z3o*>pQ?zeoQ;NAi{hZS4>O?+ju{osXL{Mwl-rwg= z@6Wa4Af})kcMXG2=86QyyP@PYHp8Sjnad@w!=lx-YvS@=D_m^r(Z;W7|IjA{?zg7z zch3XtA8|MqgpG=EuQb?s*8LgSJEU~5`*eezQho37RDU=1y^B_}<4L25M42Fy5_k45 z!8l7$3%uU}m44J5MbTmq-Jxs~W`YRbA%@qZK-E$4IK9!1cPC2}qWx_x$Mco@^zUJ! zj3p)W>3mbpa|WPT;+A&baqLDo?JLLF%x;R6cthr{Kb{ zR9lO;tkvDuFNr@MB~rPs<(HA=U%uy+^nPS(qvE|z*_+H~PUmR)O?XnUs+*z1Oe&DTw%%%XraNvjXSw`C`t_ntX0Of28o1>|$6; zJjD!R4Y4H%_*5Qj8Ho~bze{FdR;g&`&?Qu4Q!xo2`=z~Elo|Ww zn{MA@0W7yKtk@FJF*`Wa0iOOII+a8xE*UnFc?QdyD%D@V6z;aFeNeUPJT4hbrMREg!6tCQQ06$VHpz=o_((e1~pY?oVF4pv@GUYcJW_*h3;# z5rMx?soyqaH558H~8i)5g zvrpLlNrD$+?_pgk)9UTevX=h&1`&=1n+rk-L47dxOGCgQ7~gv>h6HdKVIa6an_J4 zz49@kjt3whDWt*d#k|8ahE^SXEawYNU6`@mG?0w$h%jEbsl!-M1Ih(8$zqTDbN&yK z7_`$T^|P=2ofL$^-+kM`RY!GldXU7{g<2A*`C-Q5y{flxSD<1dr^kYv0cqtFrz8!` zuu@L#@7BhTPYQ3k`72CTYNf=}CW{(wXSor-Rt&oN2imTrN_p&ce1HF7L9HV~-NOsT z(@3U^U_$kR@*NPsa;n*|BSmxN@0(vXCKRqhO|hq2S)VtMSGfi!)91HNr>m%Mb5Oif zX}=Ay#rqgDN8rDQF(eI@Vb#bD1Ha@grqK}(d>JvDB01vesEf~d>6tG1QT!WMY1Gcm z#8!tC4#F-wKmCtD$c4iqEjr6N+k)j)Rj2bO&wiR^k$l?ieFtD<@;|F(;yWR`ZkdAs z;8>JJd5iL#R}}Nu+f2E;+wlGwg&nHT|v<{Au%ZQD5h3v_tx zfZahMJc{sZl}s@Tfw&b>o^2aqS+~P?3a{mM*>kG{#Iw?^Grq6n6WfjLrFz4Up_ScA z@f!#3!jq8`rh?v#3)(m&>}rzY`AW&n#;|(jBVw^giG9kZwg`SGqtgmOmk__k#gO4djL?4qV?hH)L!LXCB7C z#FL;|mPbteAuJaSl>BqMdAJoNAm>~DM|?BP=`YYB_q`3bC0yRW%y839B+BHPamr5} zN#uPW1QwLuG@f4;xmr+q6mKb1qpLOH&+a5$GB0(3bug9i>oCw`N5hmrWrU$YZU~Tw zbV+!`++}J8%l?iNeL>fqoT9aCHEE=#0Ktv*w-;Be{?W>F#|Qj)*56i!B;G$39!=-7 zH~uNeX42AJ{3Cuw)lJIJ&mE1W3-Cs942%Ga*t{V%3&wuXOz3}O{_B9>WQIz_Q>&p8 z`@!SfvEQp0)nEKmf1CHksfRL6`22QJYN>5?SPv=HtCSQFp+(R~WOC6be%U%H5YZ5~ z!6ci~Yl^+uVM~dUFReNK*@*M-uAP)yW2&7aeAse71t;;32RSB$G^_<-v6_t^b_aW} zPC=Bpju`5Yp(s6VnyPg75?Pms0)jI`5yOC|lJ7cdq7K#G^}b9at@?s5K2xS%@6*~q zUe`MPj&X3*?i=9=0B+&(nOn?ANDm``N(*zRKcpk)RF(P{#7WZ5?9d+H3n=jv34bP# z5r;ITgfV_xk_K6vJWeV6Uwjbk8ZuGRhR-wR&{66=XsPKzcBo{m@M(bRJyuCz9r(`G zO`?#~-vDtJkvo`k*cgI50yp3Ssv%lDj^rK*o|OXfaa7~ z=2koZtgsSB2cMTibR-L}Qv3-eh>$>C6~D*(3XeuqDTbx3TYOPu;-U20r#EE0 z%P_da`HWdqk(k@wlyctcYb1%nhhjXu`c0J52!VVfp4_?Qzv+|(C?_X-D;)4^aPhqR zoqvIG+tXZ>XA|U(;H0rx>7fUa({t1e5I8S?Rr*2twu$cd)_9>hgMN)o{6=5A;w_)` zSZ<715o~w`Soq?l7`)v6G$7stq8QnpNGdj9sL@)}PJ!5Y*tXtjZ!6J2{elK__XQ4w%1CKOwro zpL!n|7)$W!y5A^OH=WqH9q_&c=Thc-ehLIqZp^G@d`;7MQUh zFZ9r)^8-KrDC?5{BrZ*aV9H(Py``8I6lffw_iXs=a|DzOWz}zHH3q9Z&vu`gb_5k> zI!P)a?r#3%Q2i;tI$UU|0umBtI+a0DFwFr<;MLLoUz;iz#pyWM6N3Z66w{)p^O39w zO4T?0SOH0Y?gQ$72E-nx(n@r=nMN67tIy&o+?48x z>YaCDi63jhaZk#d4q`!9)!^&sPS-?c zf@-}myE^oAe_oeaHG_TjtNF=JcCR$qo21Os&B0XQ$1~xFOW&v%f}8R{J6cmwN4zND z%oO~lxi6%7h_a$d221)IVgSbrL1{wWJ7CVXf4<^96&V(mw@HiKifwGD?FyLIqA%MI zvA&E{5rEG|CGd+5dHJ{(f;wO)rLuB$w)gvN+Jw!`J%L?c(&x@fm~NMy<3+6!pmbUO z{Qmi&ht*Mq5ylP9c<+El?}RjKZuf+v(^oLA1Lz9PS$6Xe(n5EVzDmbwkXLYniI-ikMWi=7ME^<-+d%_G+fu(ob=XV6=fEHGP zZGffyNkYu~LyBd~git53M<5*(XOI)=!)g1V6+;Gb9FGd5P}LRgWokEWeqkfPZT&{J zs(7!w1Q0^3p=to)cerIyk|Dq3f8X;21=||ye$wJ6aC*5=bX9vLtFfoVwr?K{S1aCQ zZP+G-F5h;>fJuxN=O=*5rt|LWbv6@L4W;~v#%aMJa$;Yt?xDoNk|soH`h_#<{MMu% zA#wg|mVrqjE?VfIo*_2jhifVDc8NJMABtT;*z9^UdoKR`{|%AW{}BV&p?xHADN?XhIT9Wt;O0;{SxWZHWwQ!AN>1TKQ~A~Jf6n1K2BazFfn54a74T{^V{bh9WdMN zv@1V?L+(EBc(wp9Gf}Fq>3X=tfsE@;4;F<;p`H2o6ZJ^@NRFQtTw^!Hu z{JVYYEi(K4!MJV;tcG7!FRE&>|z+v{w>6p79Qt&v?IK(!t`&E z;BdhAOc8z^N@+T@&KFeqPSw#OPsg$H5uCvqh+E2k7@BPA2h zKx`&Wbv{|5`xEp^?;A~GQcRGh!cnD`dkOl?D!d#_ddd*( z%ZFlbxedW9^C{Z(6tJgSMX?5-fa&>BVcOZ@=zW?+&S%HYrduAzY19Y@oy*?#UV#b~ zc`!JwCU9)}vm^rl4Pvp$EiswfvN&55n8~kiX1_+`U;qBu{}l-MlKJd2N)2lI9DKs! zVH`xyXcw52Q+ReYVlY0;c7+q=0cFW=pzi!ps$Uf_$#D(#2iP`Y2;`Y~ha&I}{Ob_v zuJAN4#cCKE7)rz>ihf`gPY{EiVNf2S9 zFO7Fk(rjQOIm&P;g zU->GyPP6iDsFU4%t+LJ+V~)M)FNuSxd_qI1Y`UBtApJbK6j6KSQ~Oewhm;?YrIhqU zqDJrQ>u_RDL;mOkclLjqQala@b|e$d4{NZ@^~@{sH)DS*F1m(jjz69a)l(oXnja*` z-%kZITx`MyZW6{&UO0XKgq)RW+i5$7+PO zG;y4G40&pcH1dA)FM+R91b#)E!v1cbc z17!sgxHX{u#mYEvdKt8&H|hk0tqm(9HcNEOvN5gsJ0WI#Nw>1&R$F5G%pkbB`@_S2ps38-&Jraze6dQIAB~ayJ>97<4b4y|jF3s; zJ7`BuHZ*=>^9GDKR^|hVz})jUGiqRGZ(Ux4p;NK4A2#lB&bD|r$<-yOB!=UyFu$lr zWFxuJGq>|!`alY`Z7XC#UQ0;tuqbRJ|Bxk%eA-AgkqW)V?2bm_!ye>*e*#B;T+(X2A0-iTbc`^h zTY@AYISocUlqRjn#`*@kQ1z=_;1Lq|ZTqW`)(e@n^M5&|UxjVkXkXv6C{vwFjq^8t z6KWRYmo7D-xwr}@% zb|lGzJ_CbY;%RCD^x{Hzx^%{TdrPZ_Fm2l0`u9)GdcFh8H}L|d^`hD;`|bu5PIN0` zVXdOC>4Sdd$bhKUcEvUj^qlVprhqE6T>?r_Xfs(%-A#=!_2!8IY(>%D20*WUv!Ohx zuKs&8UXRn(*1A7DHZL){?L?4s_x=ORF_K_|=av%pf{f!!#kTU122Mm|i=_`EPzO!8hL7mJ(k|1EQ^}WvSRyKZVw7hwHHvQn*-USO=IiL?+*YWGoOA~U;PL- zh4#jCsh8?KP3E;tU=X1j(>|E5<65J#rt!V0M0!bTY~8c=qr)D+z?amz>`ldkhW@=m zcpV_6X->&X5rg{7`|7lq%FqW{gf#xtzWF#r{FlNbe=|@*g-3_)vKVc{lYssV8nor!m}#6fXWm{Hh&fA(TLbRBC7s^QL_UJUMH0xd^rGgIYEGH=tr_mvn*) z&6m67@12+RTy>Er>x&!MA~gx z@TOgkMamB(1o-xov)uUGV`Q6`l~$M;IO2N=f5BiTu7R&=mFwBY@!|z9js=jy{cQ{h zf#Da!271s;M29}N&fgm?2AV@q9tiwsu~s}Fm%hw%R#4AadM>YdUW4Kg z@$ZSee78rkp8@%g1P70se=V|Fgq*wl6UbvLfKHOacz;2q-eZ@|D6zZ3In#Y`8!9cp zPOpWZP9|3F3aoRl0v(sGlfwh>`+B8x!O0h0Z{+^@;uUmoppC^}5rI`aVtSeQs%Jh% zQ}`r-c>X_g7A<}Rg_I1X6cDJZ;VgMp7R=DUybzk#d@RRS1P(E1PJ-?~a?io`WOGpT zZ8YdJFOV1P#00vp`8GKIq*Ng*d1>Y*nM)q@qFcKy`>cydb;gBmSmYv&@CohLGQG-< z+HXx5FnwA*3Gph7OK)JZBAsJ>GP}C{5s?zP(tWZJ!yp*2YIKGIV=KE7Z~3XKRs`!nrXCGMxkBkwf1D+Xa!aE!H=DfFWZvLDEVCqHt z5Zi9s;I0T$3b~dl;1r_Kj{yBv{@oR*`zZ<4EABP2S|P zx5<0uv^B))0I}nOiXj%Q98eCPg^{_ce=!#M1Eyvji?NUiU2f{DdH)7zSCs%jW#MU5 zIcnsSFj{_$0m^aR!^5zE{Qrb?@c7cvaKpb}W7z8BFlXHQU7&iOzP)t9yhp9Ji)x| zx=2a>x&$tha*b7RBbH)1xt(BrhLY)hYkImu+L}x<_#e!zR9A_1nV^YgSPX5Cgj%2; zD!~x(>znk?9+YEn$!&?3H*gN95A3Kq8iN`{FyU^3VG_4jXPRHk2H-?teiZwaz0^(v zn33EA?VPmbL#ceK;Yw590U`lDZ6nK17R_9}L9*)uj_o};vhx|>sj}0|Eq2vPn_LgF zRdZP&niYms77>I2gCh4Hk{GJZeM4vYyz?GaF4tT-r6*m;O)vzDk1~keJB?LqR~DB0 z1cdQl3sbz|Wmqv9m{V1j!x?yP6jMXQrz3c2s~@YH9^T8|i`O+)H*z~zn5A={cL;XE z+jkM~@;RTiM4x_UXj8vQK>83ON7eH2!8PP$!oRu{W-~ZU(&X^l`@d!Q3(nR_6h#!^ zTj0{DcVSkI8Se$a%`;j1K87r7rye%{Tdgp8)W-aj@`z3Q2wr=8>R!gzDuVe~?g~Fi zw>zyyALZ(g|DAnH4Mjmn?aV3Eua;|0wf~6|@p3KT+yvb5_Y8l&=vOM!8()PIn=a_$ ztfn6Z;Y`?m#i?H*;V{^MjYap2?1qhc*Ar5KtCq^g4(V2)oy#>dAs)7TdKI>U?I@=M z+{66&p{D_`H!!#x799-bcnciFs8E!0#!pcsPnBaZbBGo^4>X7xU*XWLZH(JX@lZ3i%GKT$=-#JRxGpHiGYNpY}R<0G{Fj=TBb-PIX?%1vVK}<0W?-^C$K1TKz+v#$= zr}*XExdYPgK--+h9JyqGz=#E^)S2JG6@^rGQ#{EBcrEY#e08j{HXS9_tK6)&IQ8s& zU{hYjWd>Z3uXdwySe#&mTN}y2=*v9pn&2)BWcUCJ1RQMlN{&+>BWwp!`e%#CQ?z+C zVI*i)?4M!0hjk;@_Bd&k%2$S4*N_f+nUWB>Cxtqy(l#DwbJsYcWC0eYT{-y5+(P`d zUlZ0@bu6>;V|b?3l!9bB^TMSZkL}dJYMZ1t?>N?L!I}{gzP{C1`Aku7@fQSZ$trZ= zsTcVp8|7vkm!|h&sLG)Pl%gMY#aXK@Da3Q~rW#O{gSh5V=v)eR`ONX3N!X$+6Abc8`1`RetJM%wrxla{7Q3 z(@y8|?M!JIp)pm-q`1Cc&caQrA_?ud$S@`{>BSz!Ih&&OYsBWyS*eipl(rSG9`7Iw zqA9WMqvW1KDHjZTmtTd`9OF1<6!8^=w1PouRgsz6VIkb3#0SC-Ga%@3jHO!%2n@4) zhzL%0nWBCC%0yx&;Cm5OGU+Hs^DoHP$utOffem$)eBZMoVX863o z-1GlxMLed4kBi4frIQ%$Lv_E#JtTDxHVuQz6rewH%JrkW8vjH;YlW!>!Y*ig9XwuK}>H?$A}Wtq`;=M+zy!U$&vP~ ztFRxNufervnmwFYd=P5wPa!A+N-|dG9}LWaJ#-R`uaPCSQMYCx(aQ>s|3E;W;fmjw8pt|B#g7mVcd)opp$x6gEuZSs z&dg6GxHg;)AAd`CSq4P0SS53&Hj(X%{0=_34#AgJA+2WJ#?;^fB*Mu7zbuSn(wd9X zA|13@OyLA1a(M|Sgd0Ju)oggMqbrXw2bfj^m>fD75W6a zlPf;iTpcu=W%k5+Nh7u5_`pBkvHF}WLNbMw_+`r#MvKb2T7sWf$#T6_w`7yLfq9MJ8NMpBDBj(@D}=n+91 zL9g-9KZ|9KUX0&dtW&mof*Hjc_7|WnI}b_Xz(Qz&J`gy5BfO5D z8=o|c86qg>(=}Bt+c{XC(DVHz0@*G9`8`Hz(q^0$zHjIYv#a_3W@?suoV#Okb4Y#5 z=9gR~rMfja0pfW|5l1`T*-w~Y{068})~1q%jIl{N2ffU!A=Z|c~bsNr@16qt1 zZUYrQ1Y9+4D3|*koxDUkv@k5xrLbp9)mS9#w?fbKZfDPk`Wj{Mkt;%7G#W^evuNDuep->@}@>qZMI00#d^N>ty-=B&O85WY)*Ene0Ni9>rKj0 zk|N5O*e8HUj5K@5Wn3za3Xy)EKJ*p1`bgsU7K4R=vwW1zGPAQaFcGiw682;zjScW0 zhRyDyF(mkQyb~f$5A&VW>ijQjfzU)g_4(W8P7FNCM?}mw7l&r2_%V2AKWGU}mq6U8 zJ;a~e9`s2ahjaU(?|H90MkO344kosW=)40p#3_OgyLfMOg_cj-Dlb4<-&)j2pmo4| z_dUTmY{;^#$zrN?yqE5b)$rrh9YGITwt5p}HCJj*wF-}_>uLQd?NzeF-HiuRq<3y8DfUv}YMUS%!4&#^Mv%Z=pffGG;~^GU+yQ(6}|>J-m9wqWXz?>g3N3aGkgDxle#|M13F(F*q#ag=} zP}NOJTF7pkx2ID6kstW_6lo9e-}x;y+-}sDsVfYJ1UXQTWf-eIqFwxfa1DMAu*J(z!fwRtn{j%E$2drUrA9R zG;%UBl3$&IIxdZa20%wms|(@nuhw_?NMcKK6gI5oUxU!Uk&rHiTD`!f>rc!YF=|;u zCgQ%d8p0nIUeh@f{d{5}QKxbn1Yqi3bE&+p-8~!Oo<1;d2Ro=LY#e5QkbSQZrtT>m zh>4#7`bKx-HLQD^^u9k#(Js*`IwUU**H-I1yPvIu5vKFV5|6j$d`#T`9i5BvP#4Jp_fC;*N%_3JgfrfJKUR6&r$HALO~*lkr0KW zIyoS9CpOTlT()E@O;-1bxnW8uD(hN-7d+ScsQN!2FG0VuyIIqsznpC>a=h8&9UVfL zu=p`WNH?PYaT1bRdfKP^w3i0af-QcR#y}EztbKawIt*EF)C@3abau#bKmQeQx*mog zo}5)#F=Szg=*Uq{jQgZn8l)*Ge6f>nLnaW2$8@|I$;CtEzV=IX`H$a$ zLNds~lLh#6w$bxTAxJSmm;6gki9;~lfw;JB{N8rnAfDhk2gort9(|Q8vBqo3`apjF zzfy32S_>C`j})3Q`IMatwP{@5oCWkWA&V<%;hD7|bc~B6eKb7pxyh#|8y}r`nZw{K zsC=1XrbaBP-YbSlwnJ$GlfIzZJhw|3n%}sY$@X+)pcst+gY{uqCYeRLI5!m|6w!Q<%R>x?tV{C&EiYX`F98Cg5q( z>SOKf0~)?Fv8!zcmQY2|)b};e%G(&i6c(@y>rL^GQF6$niR$-Z2p(SRu`X+DM0?vY znuKBj0}n-;z*d3g1zi%7H+r3j2jDot{2NR`MDd z-ZU!tf;ntt``HP~<5WPL*E9MJKe(ZBIeJv+@aZ2Rv_Uw+r$3?G;`{eO<1oD&hkzsD zQL^~?ui~Z2?*dM7QXEe;M45E}8CPQUaO}x4XaM`D7fYIGA+874re04Y7rr_^)o$z$ z3%&#jb8XL#ml$bwAli2zWCl>!3*CCHRFZ5#1u^ha)U_s~Vwu)cytE0lNuumr0-=P0 zTjBU+Ln=OmIgA5-yY+Uv+MSeU?7CfKLwUtB=-zw38T86-BU){02!5CusO)rNd++JA z6!ZqIH(O;;KT8}%`+DHvF+6I}`I6UaM4Wc)&s@|F960WjP84V;O%PwM*x3|ah%JuG zcc9vVb;uNGMtQCQPFkL6AsdgvFt`OW#t&ql+{W07VdgL$Bdl+*@fG$UhEYyh!N4k4 z$*X5NhMx*Gp?syT`5uBakY3;|OpNAdI`uT6Ua&uiZx3)Kifx6c-+`uXeh_+paA>%6 zeh`m1J53k_;6$t?KfE^^1mp&ms5CreIYB&OC%E%G385OjBBMY4gLPq)sPzt|nMxUp zB@d~rVyc`eS+OAT_cRijLy{6^IC+R(u|uufXLt}!@tj5mF6fw~U134cdao7IE6{o> z?gKk9-`E$Uru@w+_v2SgDsAcLmAC=;3o;KLYpE5nd&}<>&Sr%?fMBJ|4pUgbh>;c6 zOnq9#T0c^yUghIL1fc9d$%U*MVU>&jg5ov@I%8zxrGh+xFrckkTw}KP=~g6O%k1+* z9g+h1u8FR_fc~y;64R9Gm7ugTRM+zh=B_w|l7DuExzm2|o7ctr@}D8LD1UohBIaDm zrC;$gl+{cUQt@N{i|tHRfFxuPb^n{^NKDVuf$7*zP+1Z74Ar2bx0<%_Y;WPkGvg{25M1QV01=uy64WhKn@!zS2tKI-az-&1*KwJk3#WyHY! zAOnB#YB5eS#cg|F&R{9`(P_DEExrE;kzS*7Q87Wth&8&D7&lWQvHMary z{&Hu32$B^DvOO~{lo4)LQX7LXbDhcIUC)Kd=WiedI3ELc}eq}}&Cbu$O)AU;D!|LuC#%+p1 z_ru4ZG+@vy3v!!+?B@)2El&o`U|C;rkVXmm48@z_g@6jkwr?yn&}RBC%Ha5)By!4+ z%0^5$li-ul%baXRBosMNQ$rcG-pf@nfA;Wl@A8*`2q!psi4OHJ`|Z30vtn!{IvA=K~$yCAL1mp7e6j^rppcE z#V&4GlO4@tdC11DmQbRgFHqrom!|y$Ht)_FTOUU?pG(g~@)BZVfQ6r{vM!NXI})(? zXI5=c5uaHJaLbAEoj>l@;5j=M45xn@8%!y(ldZL8s43CGtyZL_p@TTT?|oT67X6rj zugFNIaJSMUFkLdmQXv$NDz>;z3=Om);skQ054lRoV-(eIq)<&2vw-?4QY#PKm!1f! zCqno21fC$@2%ZY$Flb*t7*&fZlx5p=sGXO-YxZ5uJb6~3!u4mXi%i~2RnX(BhszIb z#;6T8msUpQgo!QAI?j1^lPG=KodadA8iUrXtMFX@uNSI+mRE*dKuR8A4`UyD$jk+URm4Na-HzO&ojOtfuvi3bJBbXC!)D9<4qDT}dVj zfwEw%K$WKT0v(^xA3^6A7x{@rRj1R`vlpTNATsd39ccn~psgqY9Zg|md)3js$NIuXn#-)?^XPP_7g|`cU*?O^g^SDVxyJ~MuF+>o-ym0 zvp%a{cExM1IPUG7i9rg!pKS@=zr|+*mXv4mCwtSGzi-;}@f-L{{MmXe-;OQAX#e9T zc5R4QLO``paQ1X?_*qTA+^+L*Z3%~JT_IVqX77RrcK$%Gr}fji-Lxlwx34E`Q+_MW zUO(z1@=h-U+;n5jn( z#OHdAJcXxpxwjs>aawkheH^ET`d`1V=P4@2uXX3W8qJAi)-LWc$%0Tz4B9Qe-f9or zWp5o$WdFMq>ezztDwd4^7bMj;_h=P>0n@pJh-iQuzIU z##lDoLu+29=i?BDjs zF$yD=_pkRc#^v~5pXlU6-`&Z!RV}aP(ec#}cukmt-L+3ue=TW$lgVl2H}zL; zIi0OHoS#$iTm;mu2{JAnOR0b43JXgy~WF=Dx>#etldY+z}VK zWKZq;;y|xbThxXqv9?3|mOa;Iq1F0JsY$);ly@cblJyelybkrdYU$?bE!;FFHcNJ= zX5-aAp&OU}W?%vBIYY7O_J302GRdtPaxRN`{iY!^Xw7_4kSbdEb9+kT=2+uy4M7V&$YKJ9;L5|RYFoe9lr;d;BhjZO}sq6T*Xe6i@Z){B2i0-~+)i0|acW}ZSh}Py#ESaXZ zz0951A-M=T{KLH!Pl}E*Tq>21FH5dkzc^6;?k@J@8y293 zVjb+eC&eXR4}FsHWdHTBLg-EZSOh40cb_b9Y~LSE{| za_g`_1h3u>Q((i@^2fg#B;NIEF0&4vZa;K?-@SAlZZU-MKQS+;wqMS8^B)i*48J#4 zR%XPXsd_BaDzj@8YCK)3evC)yI z_**=Z^6Q(8?`pX5TUcnQcyw>a7>h0^H0|Vwi;5`Ah;pJyFj6C>{&UFx{e6@wK7eE0 z_b6qGe18Gb$B6F%YGi@$7^fH5M>bhfV8dEtWj8B!PSCDP!U-&}!-cJg? zH^G{%Lg0G4<|dz!Xzcj0-$<|%Cy@(BI?!0NKrqc__L)W8u-BQ!D^14US)7L(mpkK* zyP3YZ``e?ASHJY^*H;f_v@k#M(uKZj5E=RO~68oua zDa;ovFZhr1qDfRr+AEO&`~RLx1wYBT$-v)x@%1??A4gy_XX`3t7Zz#muJ(~iW41qN zCCIx!Uq?ZAee+Zj=YEPuKZdcQx#-!>o&h(-fV&=syUr+69B0Q8L?QN}$7dDhMVo-D z$E%^SkSwY8aQ`p${x<(q{O8@>Jhrh)LpHh81e)rEHC0H$l7r6S@aw?^?c(8DO+iKA zp+q>teh}a`4eZi2&3G9HIAPCgIW(Kx zbbXBh%lW5SZ)xC_w{gC zi~%Sy_70kGDK>hkgkJZy2jV@g9359xT;3e?UL&%Nhyh89Ks7<_QZ{PX2>nwW6p-|p zUrgir|7TkIp?}iDF`veId6i{;BBK)W%_@O^I(cZ&bgzviQdEmLZZ&t0=5G<8+y58Qwk9@XB_Q#U|4w<=9Rb zd-{uU;<()3SR%}*AO3^a8(Un{f_d^m+<15bxs1{_;0nHdoBnYQn?^>#>`Bb8C!zHe z61Z2q@$b1HI>esaY`2tW3n71nRW$NlNl@*VnprJXZx~p7#W-6J`5#e`lqIfXMhf<9 z7VA(XQO_NxQZ8N;A)ts;C`dGk3_ZUA z_M$hO=RbwpYO7R_E|Wu_K2$YBtGrH5F(HmG!`Jxf84EMJ;iJ}@ z^VH_$-0+1|(Qld$ft`t^{>0MXBjUB->TPvk=&M4(-P^oSlIXlWJN`p|lQrIq(UJy; zin-@gi2f6_BaNGXAtUTWl6?2`Q%S`(;<4X}thB>!h3l}XW-=_B*qY=C{b#S6dPf(2 z5pj_e{m#m55Q=cjOBeBwjocU8h2!k(Qbu6bL_5|z#)b&+&sP^tyUnUGi8s7gUcO=1 zY^im%gccC+VQrypDf!hJQaqJXh@;l~ zqr^C+?1Wa1n0LS6ridEhQ45iL;kdHb0ri5%3r>!5Utgn?VWm0GUmPZ4%e?2m&9{E~ zI*fg>qTPI%ru8IJSUvyazDMTXl2PscGFKr*-K$fp`SSyEN?}i}@RU&1uD^>IBqsRO zlwX(^(|-1wj|?O$q}^0Vg}Qez*wkf*P~@mqS&UsKTT&KeHaX@w-yKQSt#|vl?^O2Y z>V9JO8D=HHtH!oIkgm46^p>OJAaUi{`bX&_VVF4Ts3L8CFc1Ie3fwFxq3tfh%Y0%l za8iDi-B$E#e5bMnA0bqBxYk4cKGDlY7= zy8F{&4@p`Y7#!3g^xIXBNB*EcP8yTRS_xcfu@3g2?vujFS%W^~)mWMam* zWC6;f@3>nqanr#gy zDv>?=-r4>B$7L{%`D&C{@kPRYs$yx$ro!o}f}3Wqx-5%@#`#zDk^cSV*InUX->l1e zG`{oL(P(W^_`Ci1$@!d!Cx3WCRKjB>#Qj~XqY2HiRvDav&XQ`oeb|yt1R2p6W2&Cu zV>;tf18vzF>(6%|1rd21tQ46ghWf@HYgnu)d|wvQnIjgf|J?n5gne~Xlw13@ASxjt zhzNqTG$=51OQ&>$N;!0Q2nZ?Xg!Z0w@s3=Iw&Kdsb^j}Gmb-0ofQM~* z^+~--yc|5&%t^%dNDJ{bif7T@T=1W$gIv)x-8q$mZqb~@T;s=}<+PPdv0JezVk{!E4$dhbj7?wzM+=qRVWwFctgiiGp`>xtxdllW6^(cr3Y-=!IpAi}Q>I|L{iVbBBV8iY&z916QjZ`h!LO>V`4^t4BbY1Ex_!KN0~ zI$wIUBj-77OrWna+7XNQ0bwWkb6mqdj3qsP}M|j4+Wi=2;O@o)%4UPr)l;Dvgb3! zo6`ijHezw5Qpdq3BfRhBBuwr}~tm9A#2ULClV;3#24 z;y7Jp5jH|taZ5X7v*WBm?NCmXHSNnsv@@)hFEbEH|e6iJKLbMup{l%3(; z%h{gnd!>tBv5`RSUOSd`$}N+<3iM3IcWyI9GWY-_(sY( zBxG}zi?40nY~I_m)qD56a}e>&we6sd%+2<2W0fWO?d%%?JL}_>0&zSL)KvOeScwK* zM!opa=Iz`I6X=u0+G(-c@miAR&L=}olfYlKlgK(8OupwWtiimo`5I@Dwn%>mQp5#}Ry@e0@uSI84KgwT?R&&4LRZ0p+6e<| zmocLbVz(Dzz@3t8QfdtO3NbHBMRk;kzQq3!{U;0kI~PqJEu&5Zju{VR7LE~@9?N=C zIJF&uCluJODHX(4yLHXJ#OoNEvp5i=)k>U!9}H_Y|;7d zs?_(~^^=1uA*G+J&RMQ7){J+8XtjjSrie+g)J?#6VUkQW0XP72{5XGOQd_&y09LKO zdN{u=NK@}`J%9Pn&GB>)TS&9x zRTJfare}|h5dlrbaa%9G-*XX}F&ZEA(JJ7r&@GMi8SJqP;R%wy&}+ZcUK!j~k06Ax zLn%n)rmOQMuYpE93!P1BtBvV6XohW9$_iAGs7AX5&Z_f6l;&XLw0@N;kT$i!Br$W^ zl#(=${>mq5o=YSl*FG9nvN=Y%h{uhYTpche*h1Hs*1I0qQ%iW1K6V_TgVvZDW{;OM zQX|F6E@2V3!ig1UHRGl`g3ihdBqN~Zmd`bRQ-b_C;G%5o(SDUB6~1kz4Jf!#(|4t; z%Q-!-Pt_;eDffxa#PZJ3aXFP;6Ud$zy1HWXs-4Z{{4@Tpd+f9ZbbTEViy>2{0?+J) zbNL27f!5%ImNvthn8(WgR*t5AzlO;>JQoa6w}@}_0y)63_sl}^8Ml2(e^t@zCa&{W zDM_$pO|8C}Pf(jTajRB$Hc9=wZUxf<0-ls+IwBp3!Jj8@{4pmaUduhUV`Bwg^tX}c zCS5N{{n@>!dosCe(L{ezzYKzS&w&ZP)6Wy9T^ErKx@Ga6!ON5g*#d;8O0YOlY%onY=VVHvQ}II&biW$|PHnus1KL`_t&h2%-D zyFTTi7E&K`YUr|4OaB_swB8!@4OY|k1QM-FA<}#)8e(B`ua;i`!t#n=vhH-OQl+3& zV{C^t2jtOqc~P#-Y5w37r#C!@XvX@kRx%2gcG_vOL1}GHb8K<}l7Z(j8VWaX8tHP= zY$Lfv@;n#xo$UPlY&)&6w7VA7cJU(yS#7H!Yp)UMfJ=rPuQji#Cy)<#q8xKbi9Y{N zIT>0AKDQ+r6p!uc6pwifxA#61YNg|X^(r}am1{Gyet&o12EJeO-mhn9*KMV_j$e$6@R@XIfFz2h4BLC31HgL!q=(@NXdikH&JX((!@W%w{Ck)V7R$K6FDkd249k~q4(MTMm z787(mS%JA8C}1viDrImE=6-|6CUcdR_xi{FF1ywz8z`4C)Z;mSweKX4_cH}mN@q3e zL=cwJCvM#&Y4PMF(s)2)Uy{;NBU?c%n~*aKF~1Pp5N$0sTOummPqpVwMfSLi*MfVI ziZ_<6yd8+g1S>3NRle@|)XAgVZX=7F6h!H<_UNCV&=;&^4RSQmB8wFOCFR@sX@rY3 zd#A?(^!q~M(Ac6}U& zg%`$>ugBtHnPpH`1s&H!4d+1sD1KsSl{usbsS;y7&_+KRK-StauvuZ>x1czVkwgwJ ze07j0ho@FiX5jY3hMOMseM-W3j6xo3v

@+)73T&7DGPqbwPopECgb3mrHjKx=%c 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

  • hZQztxIHm%vq2B7t+^~2c%J7f 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 O{KSN$1;6lXx&MEA1Xce4 literal 0 HcmV?d00001 diff --git a/internal/avs/eigenda/abi.go b/internal/avs/eigenda/abi.go new file mode 100644 index 0000000..f80d799 --- /dev/null +++ b/internal/avs/eigenda/abi.go @@ -0,0 +1,70 @@ +package eigenda + +import ( + _ "embed" + "encoding/json" + "fmt" + "math/big" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/avs/eigenda/contracts" +) + +type confirmBatchInput struct { + /* The confirmBatch input also has a 0th input which is not used. A new + type could be created and added here if it becomes necessary.*/ + + NonSignerStakesAndSignature nonSignerStakesAndSignature // input 1 +} + +type nonSignerStakesAndSignature struct { + NonSignerQuorumBitmapIndices []uint32 `json:"nonSignerQuorumBitmapIndices"` + NonSignerPubkeys []g1Point `json:"nonSignerPubkeys"` + QuorumApks []g1Point `json:"quorumApks"` + ApkG2 g2Point `json:"apkG2"` + Sigma g1Point `json:"sigma"` + QuorumApkIndices []uint32 `json:"quorumApkIndices"` + TotalStakeIndices []uint32 `json:"totalStakeIndices"` + NonSignerStakeIndices [][]uint32 `json:"nonSignerStakeIndices"` +} + +type g1Point struct { + X *big.Int `json:"X"` + Y *big.Int `json:"Y"` +} + +type g2Point struct { + X [2]*big.Int `json:"x"` + Y [2]*big.Int `json:"y"` +} + +func unpackConfirmBatchInput(avsEnv string, data []byte) (*confirmBatchInput, error) { + contract, err := contracts.GetServiceManagerContract(avsEnv) + if err != nil { + return nil, fmt.Errorf("failed to get service manager contract: %v", err) + } + + method, exists := contract.Abi.Methods["confirmBatch"] + if !exists { + return nil, fmt.Errorf("confirmBatch method not found in ABI") + } + + inputs, err := method.Inputs.Unpack(data) + if err != nil { + return nil, fmt.Errorf("failed to unpack confirmBatch input: %v", err) + } + + // Unpack nonSignerStakesAndSignature + var nonSignerStakesAndSignature nonSignerStakesAndSignature + jsonRaw, err := json.Marshal(inputs[1]) + if err != nil { + return nil, fmt.Errorf("failed to marshal nonSignerStakesAndSignature: %v", err) + } + err = json.Unmarshal(jsonRaw, &nonSignerStakesAndSignature) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal nonSignerStakesAndSignature: %v", err) + } + + return &confirmBatchInput{ + NonSignerStakesAndSignature: nonSignerStakesAndSignature, + }, nil +} diff --git a/internal/avs/eigenda/contracts/abi/holesky-bls-apk-registry.json b/internal/avs/eigenda/contracts/abi/holesky-bls-apk-registry.json new file mode 100644 index 0000000..3006195 --- /dev/null +++ b/internal/avs/eigenda/contracts/abi/holesky-bls-apk-registry.json @@ -0,0 +1,619 @@ +[ + { + "inputs": [ + { + "internalType": "contract IRegistryCoordinator", + "name": "_registryCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct BN254.G1Point", + "name": "pubkeyG1", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "indexed": false, + "internalType": "struct BN254.G2Point", + "name": "pubkeyG2", + "type": "tuple" + } + ], + "name": "NewPubkeyRegistration", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "operatorId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "OperatorAddedToQuorums", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "operatorId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "OperatorRemovedFromQuorums", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "apkHistory", + "outputs": [ + { + "internalType": "bytes24", + "name": "apkHash", + "type": "bytes24" + }, + { + "internalType": "uint32", + "name": "updateBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nextUpdateBlockNumber", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "currentApk", + "outputs": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "deregisterOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + } + ], + "name": "getApk", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getApkHashAtBlockNumberAndIndex", + "outputs": [ + { + "internalType": "bytes24", + "name": "", + "type": "bytes24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + } + ], + "name": "getApkHistoryLength", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getApkIndicesAtBlockNumber", + "outputs": [ + { + "internalType": "uint32[]", + "name": "", + "type": "uint32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getApkUpdateAtIndex", + "outputs": [ + { + "components": [ + { + "internalType": "bytes24", + "name": "apkHash", + "type": "bytes24" + }, + { + "internalType": "uint32", + "name": "updateBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nextUpdateBlockNumber", + "type": "uint32" + } + ], + "internalType": "struct IBLSApkRegistry.ApkUpdate", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "pubkeyHash", + "type": "bytes32" + } + ], + "name": "getOperatorFromPubkeyHash", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "getOperatorId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "getRegisteredPubkey", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + } + ], + "name": "initializeQuorum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "operatorToPubkey", + "outputs": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "operatorToPubkeyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "pubkeyHashToOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "pubkeyRegistrationSignature", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "pubkeyG1", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "pubkeyG2", + "type": "tuple" + } + ], + "internalType": "struct IBLSApkRegistry.PubkeyRegistrationParams", + "name": "params", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "pubkeyRegistrationMessageHash", + "type": "tuple" + } + ], + "name": "registerBLSPublicKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "operatorId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "registerOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "registryCoordinator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/internal/avs/eigenda/contracts/abi/holesky-service-manager.json b/internal/avs/eigenda/contracts/abi/holesky-service-manager.json new file mode 100644 index 0000000..bc83b9a --- /dev/null +++ b/internal/avs/eigenda/contracts/abi/holesky-service-manager.json @@ -0,0 +1,1126 @@ +[ + { + "inputs": [ + { + "internalType": "contract IAVSDirectory", + "name": "__avsDirectory", + "type": "address" + }, + { + "internalType": "contract IRewardsCoordinator", + "name": "__rewardsCoordinator", + "type": "address" + }, + { + "internalType": "contract IRegistryCoordinator", + "name": "__registryCoordinator", + "type": "address" + }, + { + "internalType": "contract IStakeRegistry", + "name": "__stakeRegistry", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "batchHeaderHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "batchId", + "type": "uint32" + } + ], + "name": "BatchConfirmed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "batchConfirmer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "status", + "type": "bool" + } + ], + "name": "BatchConfirmerStatusChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IPauserRegistry", + "name": "pauserRegistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IPauserRegistry", + "name": "newPauserRegistry", + "type": "address" + } + ], + "name": "PauserRegistrySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "prevRewardsInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newRewardsInitiator", + "type": "address" + } + ], + "name": "RewardsInitiatorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "StaleStakesForbiddenUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCK_STALE_MEASURE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STORE_DURATION_BLOCKS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "THRESHOLD_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "avsDirectory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "batchIdToBatchMetadataHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blsApkRegistry", + "outputs": [ + { + "internalType": "contract IBLSApkRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "referenceBlockNumber", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "uint32[]", + "name": "nonSignerQuorumBitmapIndices", + "type": "uint32[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "nonSignerPubkeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "quorumApks", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "apkG2", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "sigma", + "type": "tuple" + }, + { + "internalType": "uint32[]", + "name": "quorumApkIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "totalStakeIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[][]", + "name": "nonSignerStakeIndices", + "type": "uint32[][]" + } + ], + "internalType": "struct IBLSSignatureChecker.NonSignerStakesAndSignature", + "name": "params", + "type": "tuple" + } + ], + "name": "checkSignatures", + "outputs": [ + { + "components": [ + { + "internalType": "uint96[]", + "name": "signedStakeForQuorum", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "totalStakeForQuorum", + "type": "uint96[]" + } + ], + "internalType": "struct IBLSSignatureChecker.QuorumStakeTotals", + "name": "", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "blobHeadersRoot", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signedStakeForQuorums", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "referenceBlockNumber", + "type": "uint32" + } + ], + "internalType": "struct IEigenDAServiceManager.BatchHeader", + "name": "batchHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32[]", + "name": "nonSignerQuorumBitmapIndices", + "type": "uint32[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "nonSignerPubkeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "quorumApks", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "apkG2", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "sigma", + "type": "tuple" + }, + { + "internalType": "uint32[]", + "name": "quorumApkIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "totalStakeIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[][]", + "name": "nonSignerStakeIndices", + "type": "uint32[][]" + } + ], + "internalType": "struct IBLSSignatureChecker.NonSignerStakesAndSignature", + "name": "nonSignerStakesAndSignature", + "type": "tuple" + } + ], + "name": "confirmBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "contract IStrategy", + "name": "strategy", + "type": "address" + }, + { + "internalType": "uint96", + "name": "multiplier", + "type": "uint96" + } + ], + "internalType": "struct IRewardsCoordinator.StrategyAndMultiplier[]", + "name": "strategiesAndMultipliers", + "type": "tuple[]" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "startTimestamp", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "duration", + "type": "uint32" + } + ], + "internalType": "struct IRewardsCoordinator.RewardsSubmission[]", + "name": "rewardsSubmissions", + "type": "tuple[]" + } + ], + "name": "createAVSRewardsSubmission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "delegation", + "outputs": [ + { + "internalType": "contract IDelegationManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "deregisterOperatorFromAVS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "getOperatorRestakedStrategies", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRestakeableStrategies", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPauserRegistry", + "name": "_pauserRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_initialPausedStatus", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_initialOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "_batchConfirmers", + "type": "address[]" + }, + { + "internalType": "address", + "name": "_rewardsInitiator", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isBatchConfirmer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "referenceBlockNumber", + "type": "uint32" + } + ], + "name": "latestServeUntilBlock", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauserRegistry", + "outputs": [ + { + "internalType": "contract IPauserRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumAdversaryThresholdPercentages", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumConfirmationThresholdPercentages", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumbersRequired", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "internalType": "struct ISignatureUtils.SignatureWithSaltAndExpiry", + "name": "operatorSignature", + "type": "tuple" + } + ], + "name": "registerOperatorToAVS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "registryCoordinator", + "outputs": [ + { + "internalType": "contract IRegistryCoordinator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsInitiator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_batchConfirmer", + "type": "address" + } + ], + "name": "setBatchConfirmer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPauserRegistry", + "name": "newPauserRegistry", + "type": "address" + } + ], + "name": "setPauserRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newRewardsInitiator", + "type": "address" + } + ], + "name": "setRewardsInitiator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setStaleStakesForbidden", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakeRegistry", + "outputs": [ + { + "internalType": "contract IStakeRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "staleStakesForbidden", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "taskNumber", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "apk", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "apkG2", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "sigma", + "type": "tuple" + } + ], + "name": "trySignatureAndApkVerification", + "outputs": [ + { + "internalType": "bool", + "name": "pairingSuccessful", + "type": "bool" + }, + { + "internalType": "bool", + "name": "siganatureIsValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_metadataURI", + "type": "string" + } + ], + "name": "updateAVSMetadataURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/internal/avs/eigenda/contracts/abi/mainnet-bls-apk-registry.json b/internal/avs/eigenda/contracts/abi/mainnet-bls-apk-registry.json new file mode 100644 index 0000000..3006195 --- /dev/null +++ b/internal/avs/eigenda/contracts/abi/mainnet-bls-apk-registry.json @@ -0,0 +1,619 @@ +[ + { + "inputs": [ + { + "internalType": "contract IRegistryCoordinator", + "name": "_registryCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct BN254.G1Point", + "name": "pubkeyG1", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "indexed": false, + "internalType": "struct BN254.G2Point", + "name": "pubkeyG2", + "type": "tuple" + } + ], + "name": "NewPubkeyRegistration", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "operatorId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "OperatorAddedToQuorums", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "operatorId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "OperatorRemovedFromQuorums", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "apkHistory", + "outputs": [ + { + "internalType": "bytes24", + "name": "apkHash", + "type": "bytes24" + }, + { + "internalType": "uint32", + "name": "updateBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nextUpdateBlockNumber", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "currentApk", + "outputs": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "deregisterOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + } + ], + "name": "getApk", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getApkHashAtBlockNumberAndIndex", + "outputs": [ + { + "internalType": "bytes24", + "name": "", + "type": "bytes24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + } + ], + "name": "getApkHistoryLength", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getApkIndicesAtBlockNumber", + "outputs": [ + { + "internalType": "uint32[]", + "name": "", + "type": "uint32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getApkUpdateAtIndex", + "outputs": [ + { + "components": [ + { + "internalType": "bytes24", + "name": "apkHash", + "type": "bytes24" + }, + { + "internalType": "uint32", + "name": "updateBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nextUpdateBlockNumber", + "type": "uint32" + } + ], + "internalType": "struct IBLSApkRegistry.ApkUpdate", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "pubkeyHash", + "type": "bytes32" + } + ], + "name": "getOperatorFromPubkeyHash", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "getOperatorId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "getRegisteredPubkey", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "quorumNumber", + "type": "uint8" + } + ], + "name": "initializeQuorum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "operatorToPubkey", + "outputs": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "operatorToPubkeyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "pubkeyHashToOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "pubkeyRegistrationSignature", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "pubkeyG1", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "pubkeyG2", + "type": "tuple" + } + ], + "internalType": "struct IBLSApkRegistry.PubkeyRegistrationParams", + "name": "params", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "pubkeyRegistrationMessageHash", + "type": "tuple" + } + ], + "name": "registerBLSPublicKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "operatorId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + } + ], + "name": "registerOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "registryCoordinator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/internal/avs/eigenda/contracts/abi/mainnet-service-manager.json b/internal/avs/eigenda/contracts/abi/mainnet-service-manager.json new file mode 100644 index 0000000..17bc356 --- /dev/null +++ b/internal/avs/eigenda/contracts/abi/mainnet-service-manager.json @@ -0,0 +1,1019 @@ +[ + { + "inputs": [ + { + "internalType": "contract IAVSDirectory", + "name": "__avsDirectory", + "type": "address" + }, + { + "internalType": "contract IRegistryCoordinator", + "name": "__registryCoordinator", + "type": "address" + }, + { + "internalType": "contract IStakeRegistry", + "name": "__stakeRegistry", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "batchHeaderHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "batchId", + "type": "uint32" + } + ], + "name": "BatchConfirmed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "batchConfirmer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "status", + "type": "bool" + } + ], + "name": "BatchConfirmerStatusChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IPauserRegistry", + "name": "pauserRegistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IPauserRegistry", + "name": "newPauserRegistry", + "type": "address" + } + ], + "name": "PauserRegistrySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "StaleStakesForbiddenUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCK_STALE_MEASURE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STORE_DURATION_BLOCKS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "THRESHOLD_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "avsDirectory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "batchIdToBatchMetadataHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blsApkRegistry", + "outputs": [ + { + "internalType": "contract IBLSApkRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "referenceBlockNumber", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "uint32[]", + "name": "nonSignerQuorumBitmapIndices", + "type": "uint32[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "nonSignerPubkeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "quorumApks", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "apkG2", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "sigma", + "type": "tuple" + }, + { + "internalType": "uint32[]", + "name": "quorumApkIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "totalStakeIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[][]", + "name": "nonSignerStakeIndices", + "type": "uint32[][]" + } + ], + "internalType": "struct IBLSSignatureChecker.NonSignerStakesAndSignature", + "name": "params", + "type": "tuple" + } + ], + "name": "checkSignatures", + "outputs": [ + { + "components": [ + { + "internalType": "uint96[]", + "name": "signedStakeForQuorum", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "totalStakeForQuorum", + "type": "uint96[]" + } + ], + "internalType": "struct IBLSSignatureChecker.QuorumStakeTotals", + "name": "", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "blobHeadersRoot", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "quorumNumbers", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signedStakeForQuorums", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "referenceBlockNumber", + "type": "uint32" + } + ], + "internalType": "struct IEigenDAServiceManager.BatchHeader", + "name": "batchHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32[]", + "name": "nonSignerQuorumBitmapIndices", + "type": "uint32[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "nonSignerPubkeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point[]", + "name": "quorumApks", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "apkG2", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "sigma", + "type": "tuple" + }, + { + "internalType": "uint32[]", + "name": "quorumApkIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "totalStakeIndices", + "type": "uint32[]" + }, + { + "internalType": "uint32[][]", + "name": "nonSignerStakeIndices", + "type": "uint32[][]" + } + ], + "internalType": "struct IBLSSignatureChecker.NonSignerStakesAndSignature", + "name": "nonSignerStakesAndSignature", + "type": "tuple" + } + ], + "name": "confirmBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "delegation", + "outputs": [ + { + "internalType": "contract IDelegationManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "deregisterOperatorFromAVS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "getOperatorRestakedStrategies", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRestakeableStrategies", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPauserRegistry", + "name": "_pauserRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_initialPausedStatus", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_initialOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "_batchConfirmers", + "type": "address[]" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isBatchConfirmer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "referenceBlockNumber", + "type": "uint32" + } + ], + "name": "latestServeUntilBlock", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauserRegistry", + "outputs": [ + { + "internalType": "contract IPauserRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumAdversaryThresholdPercentages", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumConfirmationThresholdPercentages", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumbersRequired", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "internalType": "struct ISignatureUtils.SignatureWithSaltAndExpiry", + "name": "operatorSignature", + "type": "tuple" + } + ], + "name": "registerOperatorToAVS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "registryCoordinator", + "outputs": [ + { + "internalType": "contract IRegistryCoordinator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_batchConfirmer", + "type": "address" + } + ], + "name": "setBatchConfirmer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPauserRegistry", + "name": "newPauserRegistry", + "type": "address" + } + ], + "name": "setPauserRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setStaleStakesForbidden", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakeRegistry", + "outputs": [ + { + "internalType": "contract IStakeRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "staleStakesForbidden", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "taskNumber", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "apk", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256[2]", + "name": "X", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "Y", + "type": "uint256[2]" + } + ], + "internalType": "struct BN254.G2Point", + "name": "apkG2", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "X", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "Y", + "type": "uint256" + } + ], + "internalType": "struct BN254.G1Point", + "name": "sigma", + "type": "tuple" + } + ], + "name": "trySignatureAndApkVerification", + "outputs": [ + { + "internalType": "bool", + "name": "pairingSuccessful", + "type": "bool" + }, + { + "internalType": "bool", + "name": "siganatureIsValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newPausedStatus", + "type": "uint256" + } + ], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_metadataURI", + "type": "string" + } + ], + "name": "updateAVSMetadataURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/internal/avs/eigenda/contracts/blsApkRegistry.go b/internal/avs/eigenda/contracts/blsApkRegistry.go new file mode 100644 index 0000000..d023d21 --- /dev/null +++ b/internal/avs/eigenda/contracts/blsApkRegistry.go @@ -0,0 +1,75 @@ +package contracts + +import ( + "bytes" + _ "embed" + "fmt" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +// Holesky variables +var ( + //go:embed abi/holesky-bls-apk-registry.json + holeskyBlsApkRegistryABIBytes []byte + // TODO: add a configuration option for the address + holeskyBlsApkRegistryAddress = common.HexToAddress("0x066cF95c1bf0927124DFB8B02B401bc23A79730D") + holeskyBlsApkRegistryContract *BlsApkRegistryContract +) + +// Mainnet variables +var ( + //go:embed abi/mainnet-bls-apk-registry.json + mainnetBlsApkRegistryABIBytes []byte + // TODO: add a configuration option for the address + mainnetBlsApkRegistryAddress = common.HexToAddress("0x00A5Fd09F6CeE6AE9C8b0E5e33287F7c82880505") + mainnetBlsApkRegistryContract *BlsApkRegistryContract +) + +type BlsApkRegistryContract struct { + Address common.Address + Abi abi.ABI +} + +func GetBlsApkRegistryContract(avsEnv string) (*BlsApkRegistryContract, error) { + switch avsEnv { + case config.AVSEnvEigenDAHolesky: + if holeskyBlsApkRegistryContract != nil { + return holeskyBlsApkRegistryContract, nil + } + return getHoleskyBlsApkRegistryContract() + case config.AVSEnvEigenDAMainnet: + if mainnetBlsApkRegistryContract != nil { + return mainnetBlsApkRegistryContract, nil + } + return getMainnetBlsApkRegistryContract() + default: + return nil, fmt.Errorf("invalid avs environment: %s", avsEnv) + } +} + +func getHoleskyBlsApkRegistryContract() (*BlsApkRegistryContract, error) { + abi, err := abi.JSON(bytes.NewReader(holeskyBlsApkRegistryABIBytes)) + if err != nil { + return nil, err + } + holeskyBlsApkRegistryContract = &BlsApkRegistryContract{ + Address: holeskyBlsApkRegistryAddress, + Abi: abi, + } + return holeskyBlsApkRegistryContract, nil +} + +func getMainnetBlsApkRegistryContract() (*BlsApkRegistryContract, error) { + abi, err := abi.JSON(bytes.NewReader(mainnetBlsApkRegistryABIBytes)) + if err != nil { + return nil, err + } + mainnetBlsApkRegistryContract = &BlsApkRegistryContract{ + Address: mainnetBlsApkRegistryAddress, + Abi: abi, + } + return mainnetBlsApkRegistryContract, nil +} diff --git a/internal/avs/eigenda/contracts/serviceManager.go b/internal/avs/eigenda/contracts/serviceManager.go new file mode 100644 index 0000000..e216d44 --- /dev/null +++ b/internal/avs/eigenda/contracts/serviceManager.go @@ -0,0 +1,74 @@ +package contracts + +import ( + "bytes" + _ "embed" + "fmt" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +// Holesky variables +var ( + //go:embed abi/holesky-service-manager.json + holeskyServiceManagerABIBytes []byte + // TODO: add a configuration option for the address + holeskyServiceManagerAddress = common.HexToAddress("0xD4A7E1Bd8015057293f0D0A557088c286942e84b") + holeskyServiceManagerContract *ServiceManagerContract +) + +var ( + //go:embed abi/mainnet-service-manager.json + mainnetServiceManagerABIBytes []byte + // TODO: add a configuration option for the address + mainnetServiceManagerAddress = common.HexToAddress("0x870679E138bCdf293b7Ff14dD44b70FC97e12fc0") + mainnetServiceManagerContract *ServiceManagerContract +) + +type ServiceManagerContract struct { + Address common.Address + Abi abi.ABI +} + +func GetServiceManagerContract(avsEnv string) (*ServiceManagerContract, error) { + switch avsEnv { + case config.AVSEnvEigenDAHolesky: + if holeskyServiceManagerContract != nil { + return holeskyServiceManagerContract, nil + } + return getHoleskyServiceManagerContract() + case config.AVSEnvEigenDAMainnet: + if mainnetServiceManagerContract != nil { + return mainnetServiceManagerContract, nil + } + return getMainnetServiceManagerContract() + default: + return nil, fmt.Errorf("invalid avs environment: %s", avsEnv) + } +} + +func getHoleskyServiceManagerContract() (*ServiceManagerContract, error) { + abi, err := abi.JSON(bytes.NewReader(holeskyServiceManagerABIBytes)) + if err != nil { + return nil, err + } + holeskyServiceManagerContract = &ServiceManagerContract{ + Address: holeskyServiceManagerAddress, + Abi: abi, + } + return holeskyServiceManagerContract, nil +} + +func getMainnetServiceManagerContract() (*ServiceManagerContract, error) { + abi, err := abi.JSON(bytes.NewReader(mainnetServiceManagerABIBytes)) + if err != nil { + return nil, err + } + mainnetServiceManagerContract = &ServiceManagerContract{ + Address: mainnetServiceManagerAddress, + Abi: abi, + } + return mainnetServiceManagerContract, nil +} diff --git a/internal/avs/eigenda/eigenda.go b/internal/avs/eigenda/eigenda.go new file mode 100644 index 0000000..3888325 --- /dev/null +++ b/internal/avs/eigenda/eigenda.go @@ -0,0 +1,369 @@ +package eigenda + +import ( + "bytes" + "context" + "fmt" + "log/slog" + "math/big" + "slices" + "sort" + "strconv" + "time" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/avs/eigenda/contracts" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/avsexporter" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/rpc" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +type eigenDAOnChainExporter struct { + avsEnv string + network string + operators []config.OperatorConfig + ethClient rpc.EthEvmRpc +} + +func NewEigenDAOnChainExporter(avsEnv string, c *config.Config) (avsexporter.AVSExporter, error) { + // Set exporter status to DOWN by default + metricExporterStatus.WithLabelValues(avsEnv).Set(0) + + // Filter operators by AVS environment + var operators []config.OperatorConfig + for _, operator := range c.Operators { + if slices.Contains(operator.AVSEnvs, avsEnv) { + operators = append(operators, operator) + } + } + // Get the network from the AVS environment + var network string + switch avsEnv { + case config.AVSEnvEigenDAHolesky: + network = "holesky" + case config.AVSEnvEigenDAMainnet: + network = "mainnet" + default: + return nil, fmt.Errorf("invalid AVS environment: %s", avsEnv) + } + e := &eigenDAOnChainExporter{ + avsEnv: avsEnv, + network: network, + operators: operators, + } + if err := e.init(c.RPCs); err != nil { + return nil, fmt.Errorf("failed to initialize exporter: %v", err) + } + slog.Info("initialized exporter |", "avsEnv", e.avsEnv, "operators", len(e.operators)) + return e, nil +} + +func (e *eigenDAOnChainExporter) Name() string { + return e.avsEnv +} + +func (e *eigenDAOnChainExporter) Run(ctx context.Context, c *config.Config) error { + // TODO: Add a configuration option for the ticker time + tickerTime := time.Second * 30 + slog.Info("running exporter |", "avsEnv", e.avsEnv, "interval", tickerTime) + + // Load contracts + serviceManagerContract, err := contracts.GetServiceManagerContract(e.avsEnv) + if err != nil { + return err + } + blsApkRegistryContract, err := contracts.GetBlsApkRegistryContract(e.avsEnv) + if err != nil { + return err + } + + // Get current block to start from + // TODO: Should we add a configuration option to start from a specific block? + latestBlock, err := e.getLatestBlock() + if err != nil { + return err + } + + // Set exporter status to UP + metricExporterStatus.WithLabelValues(e.avsEnv).Set(1) + + ticker := time.Tick(tickerTime) + for { + select { + case <-ctx.Done(): + slog.Info("exiting exporter |", "avsEnv", e.avsEnv) + return nil + case <-ticker: + // Get the next block range + fromBlock, toBlock, err := e.nextBlockRange(latestBlock, tickerTime) + if err != nil { + slog.Error("exporter error |", "avsEnv", e.avsEnv, "error", err) + continue + } + if fromBlock == nil || toBlock == nil { + continue + } + // Get logs from current block range + logs, err := e.getLogs(fromBlock, toBlock) + if err != nil { + slog.Error("exporter error |", "avsEnv", e.avsEnv, "error", err) + continue + } + + for _, vLog := range logs { + switch vLog.Topics[0].Hex() { + case serviceManagerContract.Abi.Events["BatchConfirmed"].ID.Hex(): + if err := e.processBatchConfirmedLog(vLog); err != nil { + slog.Error("exporter error |", "avsEnv", e.avsEnv, "error", err) + continue + } + case blsApkRegistryContract.Abi.Events["OperatorRemovedFromQuorums"].ID.Hex(): + if err := e.processOperatorRemovedFromQuorumsLog(vLog); err != nil { + slog.Error("exporter error |", "avsEnv", e.avsEnv, "error", err) + continue + } + case blsApkRegistryContract.Abi.Events["OperatorAddedToQuorums"].ID.Hex(): + if err := e.processOperatorAddedToQuorumsLog(vLog); err != nil { + slog.Error("exporter error |", "avsEnv", e.avsEnv, "error", err) + continue + } + } + } + metricExporterLatestBlock.WithLabelValues(e.network).Set(float64(toBlock.Int64())) + latestBlock = new(big.Int).Add(toBlock, big.NewInt(1)) + } + } +} + +func (e *eigenDAOnChainExporter) checkAVSEnv(avsEnv string) error { + if avsEnv != config.AVSEnvEigenDAHolesky && avsEnv != config.AVSEnvEigenDAMainnet { + return fmt.Errorf("invalid AVS environment: %s", avsEnv) + } + return nil +} + +func (e *eigenDAOnChainExporter) init(rpcs map[string]string) error { + if err := e.checkAVSEnv(e.avsEnv); err != nil { + return fmt.Errorf("failed to check AVS environment: %v", err) + } + + if err := e.initRPC(rpcs); err != nil { + return fmt.Errorf("failed to initialize RPC: %v", err) + } + + if err := e.initPrometheusMetrics(); err != nil { + return fmt.Errorf("failed to initialize prometheus metrics: %v", err) + } + + return nil +} + +func (e *eigenDAOnChainExporter) initPrometheusMetrics() error { + for _, operator := range e.operators { + for quorum, in := range operator.EigenDAConfig.Quorums { + if in { + metricOnchainQuorumStatus.WithLabelValues(operator.Name, e.network, strconv.Itoa(quorum)).Set(1) + } else { + metricOnchainQuorumStatus.WithLabelValues(operator.Name, e.network, strconv.Itoa(quorum)).Set(0) + } + } + } + return nil +} + +func (e *eigenDAOnChainExporter) initRPC(rpcs map[string]string) error { + if rpcURL, ok := rpcs[e.network]; !ok { + return fmt.Errorf("no RPC URL found for network: %s", e.network) + } else { + ethClient, err := rpc.NewEthEvmRpc(e.network, rpcURL, 3) + if err != nil { + return fmt.Errorf("failed to initialize RPC: %v", err) + } + e.ethClient = ethClient + } + return nil +} + +func (e *eigenDAOnChainExporter) getLatestBlock() (*big.Int, error) { + blockNumber, err := e.ethClient.BlockNumber(context.Background()) + if err != nil { + return nil, fmt.Errorf("failed to get the block number: %v", err) + } + return big.NewInt(int64(blockNumber)), nil +} + +func (e *eigenDAOnChainExporter) nextBlockRange(latestBlock *big.Int, tickerTime time.Duration) (*big.Int, *big.Int, error) { + toBlock, err := e.getLatestBlock() + if err != nil { + return nil, nil, err + } + if latestBlock.Cmp(toBlock) >= 0 { + slog.Debug("latest RPC block is not greater than latest exporter block. Retrying after interval time |", "avsEnv", e.avsEnv, "rpcLatestBlock", toBlock, "exporterLatestBlock", latestBlock, "sleepTime", tickerTime) + return nil, nil, nil + } + maxPaginationBlock := new(big.Int).Add(latestBlock, big.NewInt(1000)) + if toBlock.Cmp(maxPaginationBlock) > 0 { + slog.Debug("latest block is greater than max pagination block. Using max pagination block instead |", "avsEnv", e.avsEnv, "latestBlock", toBlock, "maxPaginationBlock", maxPaginationBlock, "diff", new(big.Int).Sub(toBlock, maxPaginationBlock)) + toBlock = maxPaginationBlock + } + return latestBlock, toBlock, nil +} + +func (e *eigenDAOnChainExporter) getLogs(fromBlock *big.Int, toBlock *big.Int) ([]types.Log, error) { + // Load contracts + serviceManagerContract, err := contracts.GetServiceManagerContract(e.avsEnv) + if err != nil { + return nil, err + } + blsApkRegistryContract, err := contracts.GetBlsApkRegistryContract(e.avsEnv) + if err != nil { + return nil, err + } + + // Build the filter query + query := ethereum.FilterQuery{ + FromBlock: fromBlock, + ToBlock: toBlock, + Addresses: []common.Address{ + serviceManagerContract.Address, + blsApkRegistryContract.Address, + }, + Topics: [][]common.Hash{ + { + serviceManagerContract.Abi.Events["BatchConfirmed"].ID, + blsApkRegistryContract.Abi.Events["OperatorAddedToQuorums"].ID, + blsApkRegistryContract.Abi.Events["OperatorRemovedFromQuorums"].ID, + }, + }, + } + + // Get the logs + slog.Debug("filtering logs |", "avsEnv", e.avsEnv, "fromBlock", query.FromBlock, "toBlock", query.ToBlock) + logs, err := e.ethClient.FilterLogs(context.Background(), query) + if err != nil { + return nil, err + } + + // Sort logs by block number and tx index + sort.Slice(logs, func(i, j int) bool { + if logs[i].BlockNumber == logs[j].BlockNumber { + return logs[i].TxIndex < logs[j].TxIndex + } + return logs[i].BlockNumber < logs[j].BlockNumber + }) + + return logs, nil +} + +func (e *eigenDAOnChainExporter) processBatchConfirmedLog(log types.Log) error { + // Load contracts + serviceManagerContract, err := contracts.GetServiceManagerContract(e.avsEnv) + if err != nil { + return err + } + + // Increase the number of batches counter + metricOnchainBatchesTotal.WithLabelValues(e.network).Inc() + slog.Info("batch confirmed |", "avsEnv", e.avsEnv, "blockNumber", log.BlockNumber, "txHash", log.TxHash) + + // TODO: Ignoring the isPending output. Need to research more on this. + tx, _, err := e.ethClient.TransactionByHash(context.Background(), log.TxHash) + if err != nil { + return fmt.Errorf("failed to get transaction by hash: %v", err) + } + + // Get the function signature (first 4 bytes of the input data) + funcSignature := tx.Data()[:4] + if !bytes.Equal(funcSignature, serviceManagerContract.Abi.Methods["confirmBatch"].ID) { + return nil + } + + // Unpack the input data + input, err := unpackConfirmBatchInput(e.avsEnv, tx.Data()[4:]) + if err != nil { + return fmt.Errorf("failed to unpack confirmBatch input: %v", err) + } + + // Iterate over the not signers and check if they are operators as not signers + for _, operator := range e.operators { + for _, pubkey := range input.NonSignerStakesAndSignature.NonSignerPubkeys { + operatorBLSPubkeyX, operatorBLSPubkeyY, err := getOperatorBLSPubkey(operator) + if err != nil { + return fmt.Errorf("failed to get operator BLS public key: %v", err) + } + if operatorBLSPubkeyX.Cmp(pubkey.X) == 0 || operatorBLSPubkeyY.Cmp(pubkey.Y) == 0 { + metricOnchainBatches.WithLabelValues(operator.Name, e.network, "missed").Inc() + slog.Info("operator failed to sign batch |", "avsEnv", e.avsEnv, "blockNumber", log.BlockNumber, "txIndex", log.TxIndex, "operator", operator.Name) + } + } + } + + return nil +} + +func (e *eigenDAOnChainExporter) processOperatorRemovedFromQuorumsLog(log types.Log) error { + // Load contracts + blsApkRegistryContract, err := contracts.GetBlsApkRegistryContract(e.avsEnv) + if err != nil { + return err + } + + logInputs, err := blsApkRegistryContract.Abi.Events["OperatorRemovedFromQuorums"].Inputs.Unpack(log.Data) + if err != nil { + return fmt.Errorf("failed to unpack operator removed from quorums log: %v", err) + } + operatorAddress := logInputs[0].(common.Address) + quorumNumbers := logInputs[2].([]uint8) + operatorIndex := slices.IndexFunc(e.operators, func(operator config.OperatorConfig) bool { + return common.HexToAddress(operator.Address) == operatorAddress + }) + if operatorIndex == -1 { + return nil + } + for _, quorum := range quorumNumbers { + slog.Info("operator removed from quorum |", "avsEnv", e.avsEnv, "blockNumber", log.BlockNumber, "txIndex", log.TxIndex, "operator", e.operators[operatorIndex].Name, "quorum", quorum) + metricOnchainQuorumStatus.WithLabelValues(e.operators[operatorIndex].Name, e.network, strconv.Itoa(int(quorum))).Set(0) + } + + return nil +} + +func (e *eigenDAOnChainExporter) processOperatorAddedToQuorumsLog(log types.Log) error { + // Load contracts + blsApkRegistryContract, err := contracts.GetBlsApkRegistryContract(e.avsEnv) + if err != nil { + return err + } + + logInputs, err := blsApkRegistryContract.Abi.Events["OperatorAddedToQuorums"].Inputs.Unpack(log.Data) + if err != nil { + return fmt.Errorf("failed to unpack operator added to quorums log: %v", err) + } + operatorAddress := logInputs[0].(common.Address) + quorumNumbers := logInputs[2].([]uint8) + operatorIndex := slices.IndexFunc(e.operators, func(operator config.OperatorConfig) bool { + return common.HexToAddress(operator.Address) == operatorAddress + }) + if operatorIndex == -1 { + return nil + } + for _, quorum := range quorumNumbers { + slog.Info("operator added to quorum |", "avsEnv", e.avsEnv, "blockNumber", log.BlockNumber, "txIndex", log.TxIndex, "operator", e.operators[operatorIndex].Name, "quorum", quorum) + metricOnchainQuorumStatus.WithLabelValues(e.operators[operatorIndex].Name, e.network, strconv.Itoa(int(quorum))).Set(1) + } + return nil +} + +func getOperatorBLSPubkey(operator config.OperatorConfig) (*big.Int, *big.Int, error) { + x, ok := new(big.Int).SetString(operator.BLSPublicKey[0], 10) + if !ok { + return nil, nil, fmt.Errorf("failed to set string to big.Int: %s", operator.BLSPublicKey[0]) + } + y, ok := new(big.Int).SetString(operator.BLSPublicKey[1], 10) + if !ok { + return nil, nil, fmt.Errorf("failed to set string to big.Int: %s", operator.BLSPublicKey[1]) + } + return x, y, nil +} diff --git a/internal/avs/eigenda/prometheus.go b/internal/avs/eigenda/prometheus.go new file mode 100644 index 0000000..f306c83 --- /dev/null +++ b/internal/avs/eigenda/prometheus.go @@ -0,0 +1,34 @@ +package eigenda + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +var ( + metricExporterLatestBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: "eoe", + Name: "eigenda_exporter_latest_block", + Help: "Latest block number that the exporter has processed", + }, []string{"network"}) + metricOnchainBatchesTotal = promauto.NewCounterVec(prometheus.CounterOpts{ + Namespace: "eoe", + Name: "eigenda_onchain_batches_total", + Help: "Total number of eigenda onchain batches", + }, []string{"network"}) + metricOnchainBatches = promauto.NewCounterVec(prometheus.CounterOpts{ + Namespace: "eoe", + Name: "eigenda_onchain_batches", + Help: "Number of eigenda onchain batches", + }, []string{"operator", "network", "status"}) + metricOnchainQuorumStatus = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: "eoe", + Name: "eigenda_onchain_quorum_status", + Help: "Quorum status of eigenda onchain", + }, []string{"operator", "network", "quorum"}) + metricExporterStatus = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: "eoe", + Name: "eigenda_exporter_up", + Help: "Status of the exporter", + }, []string{"avsEnv"}) +) diff --git a/internal/avsexporter/exporter.go b/internal/avsexporter/exporter.go new file mode 100644 index 0000000..98acf16 --- /dev/null +++ b/internal/avsexporter/exporter.go @@ -0,0 +1,12 @@ +package avsexporter + +import ( + "context" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" +) + +type AVSExporter interface { + Name() string + Run(context.Context, *config.Config) error +} diff --git a/internal/cli/root.go b/internal/cli/root.go new file mode 100644 index 0000000..74db94c --- /dev/null +++ b/internal/cli/root.go @@ -0,0 +1,16 @@ +package cli + +import ( + "github.com/spf13/cobra" +) + +func RootCmd() *cobra.Command { + var rootCmd = &cobra.Command{ + Use: "eoe", + Short: "EigenLayer On-chain Exporter (eoe) exposes Prometheus metrics about AVS protocols and EigenLayer's Node Operator.", + } + rootCmd.PersistentFlags().StringP("config", "c", "eoe-config.yml", "path to config file") + rootCmd.AddCommand(runCommand()) + + return rootCmd +} diff --git a/internal/cli/run.go b/internal/cli/run.go new file mode 100644 index 0000000..10fad05 --- /dev/null +++ b/internal/cli/run.go @@ -0,0 +1,119 @@ +package cli + +import ( + "context" + "fmt" + "log/slog" + "sync" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/avs/eigenda" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/avsexporter" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/config" + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/prometheus" + "github.com/spf13/cobra" +) + +type exporterError struct { + exporter avsexporter.AVSExporter + err error +} + +func runCommand() *cobra.Command { + var c *config.Config + return &cobra.Command{ + Use: "run", + Short: "Run the application", + PreRunE: func(cmd *cobra.Command, args []string) error { + configPath, err := cmd.Flags().GetString("config") + if err != nil { + return err + } + c, err = config.GetConfig(configPath) + if err != nil { + return err + } + logLevel := slog.Level(slog.LevelInfo) + if err := logLevel.UnmarshalText([]byte(c.LogLevel)); err != nil { + return err + } + slog.SetLogLoggerLevel(logLevel) + go func() { + err := prometheus.StartPrometheusServer(":9090") + if err != nil { + slog.Error("Error starting Prometheus server", "error", err) + } + }() + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + var ( + wg sync.WaitGroup + ctx = cmd.Context() + avsEnvs = make(map[string]bool) + exporterErrorCh = make(chan exporterError, len(avsEnvs)) + ) + + // Add all AVS environments from operators + for _, operator := range c.Operators { + for _, env := range operator.AVSEnvs { + avsEnvs[env] = true + } + } + + // Run exporters for each AVS environment + for env := range avsEnvs { + switch env { + case config.AVSEnvEigenDAMainnet, config.AVSEnvEigenDAHolesky: + // Initialize and run the AVS environment exporter + exporter, err := eigenda.NewEigenDAOnChainExporter(env, c) + if err != nil { + return err + } + runExporter(ctx, exporter, &wg, exporterErrorCh, c) + default: + return fmt.Errorf("invalid AVS environment: %s", env) + } + } + + for { + select { + case exporterError := <-exporterErrorCh: + slog.Debug("exporter error", "exporter", exporterError.exporter.Name(), "error", exporterError.err) + runExporter(ctx, exporterError.exporter, &wg, exporterErrorCh, c) + case <-ctx.Done(): + slog.Debug("context done", "error", ctx.Err()) + return gracefulExit(&wg, nil) + } + } + }, + } +} + +// runExporter starts an exporter and adds it to the wait group. It also sends +// any errors to the exporterErrorCh channel. +func runExporter( + ctx context.Context, + exporter avsexporter.AVSExporter, + wg *sync.WaitGroup, + exporterErrorCh chan<- exporterError, + c *config.Config, +) { + wg.Add(1) + go func() { + defer wg.Done() + err := exporter.Run(ctx, c) + if err != nil { + if ctx.Err() == nil { + slog.Error("exporter error", "exporter", exporter.Name(), "error", err) + exporterErrorCh <- exporterError{exporter, err} + } + } + }() +} + +func gracefulExit(wg *sync.WaitGroup, err error) error { + slog.Debug("Shutting down exporters...") + wg.Wait() + slog.Debug("Exporters shutdown complete") + return err +} diff --git a/internal/common/networks.go b/internal/common/networks.go new file mode 100644 index 0000000..8a86f4f --- /dev/null +++ b/internal/common/networks.go @@ -0,0 +1,27 @@ +package common + +import ( + "fmt" + "math/big" +) + +const ( + NetworkHolesky = "holesky" + NetworkMainnet = "mainnet" +) + +func AssertChainID(network string, chainId *big.Int) error { + switch network { + case NetworkHolesky: + if chainId.Cmp(big.NewInt(17000)) != 0 { + return fmt.Errorf("invalid chain id for network: %s", network) + } + case NetworkMainnet: + if chainId.Cmp(big.NewInt(1)) != 0 { + return fmt.Errorf("invalid chain id for network: %s", network) + } + default: + return fmt.Errorf("invalid network: %s", network) + } + return nil +} diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..4cbd36e --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,43 @@ +package config + +const ( + // RPCNetwork is the network type for the RPC. + RPCNetworkEthereum = "ethereum" + RPCNetworkHolesky = "holesky" + + // AVSEnv is the environment for the AVS. + AVSEnvEigenDAHolesky = "eigenda-holesky" + AVSEnvEigenDAMainnet = "eigenda-mainnet" +) + +// Config is the configuration for the application. +type Config struct { + // Operators is the list of operators to be tracked. + Operators []OperatorConfig `yaml:"operators"` + // RPCs is the list of RPCs to be used for the AVS exporters. + RPCs map[string]string `yaml:"rpcs"` + // LogLevel is the level of logging to be used. + LogLevel string `yaml:"logLevel"` +} + +// OperatorConfig holds the needed information for an operator to be tracked. +type OperatorConfig struct { + // Name is the name of the operator. + Name string `yaml:"name"` + // Address is the address of the operator. + Address string `yaml:"address"` + // BLSPublicKey is the BLS public key of the operator. + BLSPublicKey [2]string `yaml:"blsPublicKey"` + // AVSEnvs is the list of AVS environments to be tracked. + AVSEnvs []string `yaml:"avsEnvs"` + // EigenDAConfig is the configuration for the EigenDA AVS. + EigenDAConfig EigenDAConfig `yaml:"eigenDAConfig"` +} + +type EigenDAConfig struct { + // Quorums is the initial status of the operator's quorums. If the exporter + // receives events in the future about the operator's quorum status, it will + // update the status in the Prometheus metric. This map is only for bootstrapping + // and does not have a missing Prometheus metric. + Quorums map[int]bool `yaml:"quorums"` +} diff --git a/internal/config/viper.go b/internal/config/viper.go new file mode 100644 index 0000000..721a6e2 --- /dev/null +++ b/internal/config/viper.go @@ -0,0 +1,32 @@ +package config + +import ( + "github.com/spf13/viper" +) + +// GetConfig reads the configuration from the given path and returns a Config struct. +func GetConfig(configPath string) (*Config, error) { + // Set the config file name and type + viper.SetConfigName("eoe-config") + viper.SetConfigType("yaml") + viper.AddConfigPath(".") + + // If a config path is provided, use it + if configPath != "" { + viper.SetConfigFile(configPath) + } + + // Set the environment prefix and automatically use environment variables. + // TODO: Overwriting the config file with environment variables is not working + // as expected. We need to redefine the Config struct to make easier bindings + // with environment variables. + viper.SetEnvPrefix("EOE") + viper.AutomaticEnv() + + if err := viper.ReadInConfig(); err != nil { + return nil, err + } + + var c Config + return &c, viper.Unmarshal(&c) +} diff --git a/internal/prometheus/prometheus.go b/internal/prometheus/prometheus.go new file mode 100644 index 0000000..33e69a3 --- /dev/null +++ b/internal/prometheus/prometheus.go @@ -0,0 +1,13 @@ +package prometheus + +import ( + "net/http" + + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +// StartPrometheusServer starts a Prometheus server on the given port. +func StartPrometheusServer(port string) error { + http.Handle("/metrics", promhttp.Handler()) + return http.ListenAndServe(port, nil) +} diff --git a/internal/rpc/eth-evm.go b/internal/rpc/eth-evm.go new file mode 100644 index 0000000..e2bf8ce --- /dev/null +++ b/internal/rpc/eth-evm.go @@ -0,0 +1,111 @@ +package rpc + +import ( + "context" + "log/slog" + "time" + + "github.com/NethermindEth/eigenlayer-onchain-exporter/internal/common" + "github.com/cenkalti/backoff/v4" + "github.com/ethereum/go-ethereum" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +var ( + ethEvmRpcs = make(map[string]EthEvmRpc) +) + +// EthEvmRpc is the interface for the Ethereum RPC client. +type EthEvmRpc interface { + BlockNumber(ctx context.Context) (uint64, error) + FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) + TransactionByHash(ctx context.Context, hash ethcommon.Hash) (*types.Transaction, bool, error) +} + +type ethEvmRpc struct { + network string + client *ethclient.Client + maxElapsedTime time.Duration +} + +func NewEthEvmRpc(network string, url string, maxElapsedTime time.Duration) (EthEvmRpc, error) { + if _, ok := ethEvmRpcs[network]; ok { + return ethEvmRpcs[network], nil + } + slog.Debug("initializing new eth-evm rpc |", "network", network) + client, err := ethclient.Dial(url) + if err != nil { + return nil, err + } + + // Check the chain ID of the network + chainId, err := client.ChainID(context.Background()) + if err != nil { + return nil, err + } + err = common.AssertChainID(network, chainId) + if err != nil { + return nil, err + } + + ethEvmRpc := ðEvmRpc{network: network, client: client, maxElapsedTime: maxElapsedTime} + ethEvmRpcs[network] = ethEvmRpc + + return ethEvmRpc, nil +} + +func (e *ethEvmRpc) BlockNumber(ctx context.Context) (uint64, error) { + operation := func() (uint64, error) { + slog.Debug("getting block number |", "rpcNetwork", e.network) + return e.client.BlockNumber(ctx) + } + notify := func(err error, duration time.Duration) { + slog.Error("failed to get block number, retrying... |", "rpc-network", e.network, "duration", duration, "error", err) + } + + return backoff.RetryNotifyWithData( + operation, + backoff.NewExponentialBackOff(backoff.WithMaxElapsedTime(e.maxElapsedTime)), + notify, + ) +} + +func (e *ethEvmRpc) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { + operation := func() ([]types.Log, error) { + slog.Debug("filtering logs |", "rpc-network", e.network) + return e.client.FilterLogs(ctx, query) + } + notify := func(err error, duration time.Duration) { + slog.Error("failed to filter logs, retrying... |", "rpc-network", e.network, "duration", duration, "error", err) + } + + return backoff.RetryNotifyWithData( + operation, + backoff.NewExponentialBackOff(backoff.WithMaxElapsedTime(e.maxElapsedTime)), + notify, + ) +} + +func (e *ethEvmRpc) TransactionByHash(ctx context.Context, hash ethcommon.Hash) (*types.Transaction, bool, error) { + type result struct { + tx *types.Transaction + isPending bool + } + operation := func() (result, error) { + slog.Debug("getting transaction by hash |", "rpc-network", e.network, "hash", hash) + tx, isPending, err := e.client.TransactionByHash(ctx, hash) + return result{tx: tx, isPending: isPending}, err + } + notify := func(err error, duration time.Duration) { + slog.Error("failed to get transaction by hash, retrying... |", "rpc-network", e.network, "error", err) + } + + out, err := backoff.RetryNotifyWithData( + operation, + backoff.NewExponentialBackOff(backoff.WithMaxElapsedTime(e.maxElapsedTime)), + notify, + ) + return out.tx, out.isPending, err +} diff --git a/main.py b/main.py deleted file mode 100644 index 0adcb95..0000000 --- a/main.py +++ /dev/null @@ -1,42 +0,0 @@ -from prometheus_client import start_http_server -from api_client import fetch_data_from_api -from metrics import create_metrics, update_metrics -import time -import os - -# URL of the API endpoint -API_URL = os.environ.get('API_URL', "https://blobs-goerli.eigenda.xyz/api/trpc/blobs.getBlobs") - -# How often to fetch new data and update metrics (in seconds) -FETCH_INTERVAL = int(os.environ.get('FETCH_INTERVAL', 60)) - -def main(): - """ - Main function to start the server, fetch data periodically, and update metrics. - """ - # Start up the server to expose the metrics. - start_http_server(9600) - print("Prometheus metrics server running on port 9600") - - # Create metrics - metrics = create_metrics() - - last_timestamp = 0 - - while True: - try: - # Fetch new data from the API - data = fetch_data_from_api(API_URL) - - # Update the metrics with the new data - last_timestamp = update_metrics(metrics, data, last_timestamp) - - print("Metrics updated.") - except Exception as e: - print(f"Error fetching data or updating metrics: {e}") - - # Wait for the next fetch interval - time.sleep(FETCH_INTERVAL) - -if __name__ == "__main__": - main() diff --git a/metrics.py b/metrics.py deleted file mode 100644 index d7f0c99..0000000 --- a/metrics.py +++ /dev/null @@ -1,40 +0,0 @@ -from prometheus_client import Gauge -import time - -# Assuming the structure of the data based on the provided example -# We will create a Gauge for each field in the blob data - -def create_metrics(): - """ - Create Prometheus Gauges for various fields in the blob data. - """ - metrics = { - 'reference_block_number': Gauge('reference_block_number', 'Reference block number'), - 'batch_id': Gauge('batch_id', 'Batch ID'), - 'confirmation_block_number': Gauge('confirmation_block_number', 'Confirmation block number'), - 'requested_at': Gauge('requested_at', 'Time when the blob was requested'), - # Additional metrics can be added here based on the data fields - } - return metrics - -def update_metrics(metrics, data, last_timestamp): - """ - Update the Prometheus metrics with the latest data from the API. - - Args: - metrics (dict): The dictionary of Prometheus Gauges. - data (dict): The data fetched from the API. - """ - # Get data and sort it by requested_at - sorted_data = sorted(data.get('result', {}).get('data', {}).get('json', {}).get('data', []), key=lambda k: k['requested_at']) - for blob in sorted_data: - if blob['requested_at'] <= last_timestamp: - # If the blob has already been processed, skip it - continue - metrics['reference_block_number'].set(blob.get('reference_block_number', 0)) - metrics['batch_id'].set(blob.get('batch_id', 0)) - metrics['confirmation_block_number'].set(blob.get('confirmation_block_number', 0)) - metrics['requested_at'].set(blob.get('requested_at', 0)) - # Update additional metrics here - return sorted_data[-1]['requested_at'] - diff --git a/prometheus.yml b/prometheus.yml index b20a37e..34f29fe 100644 --- a/prometheus.yml +++ b/prometheus.yml @@ -2,6 +2,6 @@ global: scrape_interval: 15s scrape_configs: - - job_name: 'blob-scraper' + - job_name: 'onchain-exporter' static_configs: - - targets: ['scraper:9600'] + - targets: ['onchain-exporter:9090'] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 5c9b59a..0000000 --- a/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -certifi==2023.11.17 -charset-normalizer==3.3.2 -idna==3.6 -prometheus-client==0.19.0 -requests==2.31.0 -urllib3==2.1.0