diff --git a/.github/integration-tests/README.md b/.github/integration-tests/README.md deleted file mode 100644 index 34aacbe1..00000000 --- a/.github/integration-tests/README.md +++ /dev/null @@ -1,291 +0,0 @@ -# IBC Integration Tests for Evolve Network - -This directory contains a comprehensive suite of automated integration tests to validate IBC (Inter-Blockchain Communication) functionality between Evolve Network chains and Cosmos Hub (Gaia). - -## ๐Ÿ“‹ Overview - -The test system creates a complete local environment with multiple interconnected blockchains to validate: -- Setup and operation of rollup chains with Evolve -- Establishment of IBC connections and channels -- Token transfers between chains -- Attestation service functionality -- IBC message relaying with Hermes - -## ๐Ÿ—๏ธ System Architecture - -### Main Components - -1. **Local DA (Data Availability)** - - Local data availability service - - Port: 7980 - - Version: configured by `EVNODE_DA_VERSION` - -2. **Gaia Chain (Cosmos Hub)** - - Standard Cosmos chain for IBC testing - - Ports: 26657 (RPC), 26656 (P2P), 9090 (gRPC), 1317 (API) - - Version: Gaia v25.1.0 by default - -3. **GM Chain (Evolve Chain)** - - Rollup chain built with Evolve/Rollkit - - Configured with attester mode enabled - - Ports: 26757 (RPC), 26756 (P2P), 9190 (gRPC), 1417 (API) - - Depends on Local DA service - -4. **Attester Service** - - Attestation service for GM chain - - Connects to GM chain to provide attestations - - Automatically restarts until connection is established - -5. **IBC Setup** - - Configures IBC connections and channels between chains - - Uses Hermes as IBC relayer - - Generates shared connection information - -6. **Hermes Relayer** - - Continuous IBC relayer for inter-chain messages - - Version: Hermes 1.13.1 - - Monitors and relays IBC packets - -7. **Test Runner** - - Executes integration tests - - Validates IBC transfers and system functionality - -## ๐Ÿ“ File Structure - -``` -.github/integration-tests/ -โ”œโ”€โ”€ docker-compose.yml # Docker services definition -โ”œโ”€โ”€ run-integration-tests.sh # Main execution script -โ”œโ”€โ”€ docker/ # Dockerfiles for each service -โ”‚ โ”œโ”€โ”€ Dockerfile.attester # Attester service image -โ”‚ โ”œโ”€โ”€ Dockerfile.gm # GM chain (Evolve) image -โ”‚ โ”œโ”€โ”€ Dockerfile.local-da # Local DA service image -โ”‚ โ””โ”€โ”€ Dockerfile.test # Test runner image -โ”œโ”€โ”€ scripts/ # Configuration and test scripts -โ”‚ โ”œโ”€โ”€ init-gaia.sh # Gaia initialization -โ”‚ โ”œโ”€โ”€ init-gm.sh # GM chain initialization -โ”‚ โ”œโ”€โ”€ setup-ibc.sh # IBC connection setup -โ”‚ โ”œโ”€โ”€ test-transfers.sh # IBC transfer tests -โ”‚ โ”œโ”€โ”€ run-attester.sh # Attester service runner -โ”‚ โ”œโ”€โ”€ wait-for-attester.sh # Wait for attester availability -โ”‚ โ”œโ”€โ”€ wait-for-chain.sh # Wait for chain availability -โ”‚ โ”œโ”€โ”€ wait-for-da.sh # Wait for DA service -โ”‚ โ”œโ”€โ”€ prepare-deps.sh # Dependencies preparation -โ”‚ โ””โ”€โ”€ run-integration-test.sh # Container test script -โ”œโ”€โ”€ config/ -โ”‚ โ””โ”€โ”€ hermes.toml # Hermes relayer configuration -โ”œโ”€โ”€ patches/ # Code patches -โ”‚ โ””โ”€โ”€ app-wiring/ -โ”‚ โ””โ”€โ”€ patch-app-wiring.sh # App configuration patches -โ””โ”€โ”€ logs/ # Logs directory (generated) -``` - -## ๐Ÿš€ Usage - -### Basic Execution - -```bash -# Run tests with default configuration -./github/integration-tests/run-integration-tests.sh - -# Run with verbose logging -./github/integration-tests/run-integration-tests.sh --verbose - -# Keep containers after tests -./github/integration-tests/run-integration-tests.sh --no-cleanup - -# Rebuild all images -./github/integration-tests/run-integration-tests.sh --build-fresh - -# Set custom timeout (in seconds) -./github/integration-tests/run-integration-tests.sh --timeout 300 -``` - -### Environment Variables - -```bash -# Component versions -export EVNODE_VERSION="v1.0.0-beta.2.0.20250908090838-0584153217ed" -export EVNODE_DA_VERSION="v1.0.0-beta.1" -export IGNITE_VERSION="v29.3.1" -export IGNITE_EVOLVE_APP_VERSION="main" -export GAIA_VERSION="v25.1.0" - -# Execution options -export CLEANUP=false # Don't cleanup after tests -export VERBOSE=true # Detailed logs -export BUILD_FRESH=true # Rebuild images -export TIMEOUT=300 # Timeout in seconds -``` - -## ๐Ÿ”„ Execution Flow - -1. **Requirements Verification** - - Docker and Docker Compose installed - - Configuration files present - -2. **Environment Preparation** - - Create log directories - - Clean previous runs - - Set permissions - -3. **Image Building** - - Local DA with Evolve binaries - - GM chain with Ignite and custom modules - - Attester with required tools - - Test runner with testing tools - -4. **Base Services Startup** - - Local DA for data availability - - Gaia chain (local Cosmos Hub) - - GM chain (Evolve chain) - - Attester service - -5. **IBC Configuration** - - Create IBC clients - - Establish connections - - Open transfer channels - - Configure relayer accounts - -6. **Relayer Startup** - - Hermes begins relaying packets - - Continuous monitoring of both chains - -7. **Test Execution** - - Validate initial balances - - IBC transfers between chains - - Verify token reception - - Test timeouts and errors - -8. **Results Collection** - - Logs from all services - - Final chain states - - Test summary - -## ๐Ÿงช Tests Executed - -### IBC Transfer Test (`test-transfers.sh`) - -1. **Initial Setup** - - Import test wallets - - Verify established IBC channels - -2. **Transfer Tests** - - Token transfer from GM to Gaia - - Token transfer from Gaia to GM - - Verify updated balances - - Validate IBC denominations - -3. **Validations** - - Confirm token reception - - Verify correct fees - - IBC packet status - -## ๐Ÿ› Debugging - -### Service Logs - -```bash -# View logs for specific service -docker compose -f .github/integration-tests/docker-compose.yml logs gm-chain - -# View real-time logs -docker compose -f .github/integration-tests/docker-compose.yml logs -f attester - -# View status of all services -docker compose -f .github/integration-tests/docker-compose.yml ps -``` - -### Container Access - -```bash -# Access GM chain -docker exec -it gm-chain /bin/bash - -# Check chain status -docker exec gm-chain gmd status - -# View recent blocks -docker exec gm-chain gmd query block -``` - -### Log Files - -Logs are automatically saved in: -``` -.github/integration-tests/logs/integration_test_logs_[timestamp]/ -โ”œโ”€โ”€ local-da.log -โ”œโ”€โ”€ gaia-chain.log -โ”œโ”€โ”€ gm-chain.log -โ”œโ”€โ”€ attester.log -โ”œโ”€โ”€ ibc-setup.log -โ”œโ”€โ”€ hermes-relayer.log -โ”œโ”€โ”€ test-runner.log -โ”œโ”€โ”€ service_status.txt -โ””โ”€โ”€ test_summary.txt -``` - -## ๐Ÿ“Š Results Interpretation - -### Success -- All chains start correctly -- IBC connections established -- Transfers completed without errors -- Exit code: 0 - -### Common Failures - -1. **Chain healthcheck failure** - - Verify available ports - - Review initialization logs - -2. **IBC setup timeout** - - Verify attester is working - - Review Hermes configuration - -3. **Transfer failures** - - Verify active IBC channels - - Review account balances - -## ๐Ÿ”ง Advanced Configuration - -### Modify Hermes Configuration - -Edit `.github/integration-tests/config/hermes.toml` to adjust: -- Timeouts -- Gas prices -- Relay strategies - -### Customize Chains - -Modify corresponding Dockerfiles to: -- Change binary versions -- Adjust genesis configuration -- Add custom modules - -### Add New Tests - -1. Create script in `scripts/` -2. Add step in `run-integration-test.sh` -3. Update test-runner in docker-compose.yml - -## ๐Ÿ“ Maintenance - -### Version Updates - -```bash -# In docker-compose.yml or environment variables -EVNODE_VERSION=new-version -GAIA_VERSION=new-version -``` - -### Complete Cleanup - -```bash -# Remove all containers and volumes -cd .github/integration-tests -docker compose down -v --remove-orphans - -# Remove built images -docker compose down --rmi all -``` diff --git a/.github/integration-tests/config/hermes.toml b/.github/integration-tests/config/hermes.toml deleted file mode 100644 index 5e91642f..00000000 --- a/.github/integration-tests/config/hermes.toml +++ /dev/null @@ -1,119 +0,0 @@ -[global] -log_level = 'debug' - -[mode] - -[mode.clients] -enabled = true -refresh = true -misbehaviour = false - -[mode.connections] -enabled = false - -[mode.channels] -enabled = false - -[mode.packets] -enabled = true -clear_interval = 100 -clear_on_start = true -tx_confirmation = false - -[rest] -enabled = false -host = '127.0.0.1' -port = 3000 - -[telemetry] -enabled = false -host = '127.0.0.1' -port = 3001 - -[[chains]] -id = 'gm' -type = 'CosmosSdk' -rpc_addr = 'http://gm-chain:26757' -grpc_addr = 'http://gm-chain:9190' -rpc_timeout = '10s' -trusted_node = false -account_prefix = 'gm' -key_name = 'gm-relayer' -key_store_type = 'Test' -store_prefix = 'ibc' -default_gas = 200000 -max_gas = 2000000 -gas_multiplier = 1.5 -max_msg_num = 30 -max_tx_size = 2097152 -max_grpc_decoding_size = 33554432 -clock_drift = '5s' -max_block_time = '30s' -ccv_consumer_chain = false -memo_prefix = '' -sequential_batch_tx = false - -[chains.event_source] -mode = 'pull' -interval = '1s' - -[chains.trust_threshold] -numerator = '1' -denominator = '3' - -[chains.gas_price] -price = 10.0 -denom = 'stake' - -[chains.packet_filter] -policy = 'allow' -list = [ - ['transfer', 'channel-*'], -] - -[chains.address_type] -derivation = 'cosmos' - -[[chains]] -id = 'gaia-local' -type = 'CosmosSdk' -rpc_addr = 'http://gaia-chain:26657' -grpc_addr = 'http://gaia-chain:9090' -rpc_timeout = '10s' -trusted_node = false -account_prefix = 'cosmos' -key_name = 'gaia-relayer' -key_store_type = 'Test' -store_prefix = 'ibc' -default_gas = 200000 -max_gas = 2000000 -gas_multiplier = 1.5 -max_msg_num = 30 -max_tx_size = 2097152 -max_grpc_decoding_size = 33554432 -clock_drift = '5s' -max_block_time = '30s' -ccv_consumer_chain = false -memo_prefix = '' -sequential_batch_tx = false - -[chains.event_source] -mode = 'pull' -interval = '1s' - -[chains.trust_threshold] -numerator = '1' -denominator = '3' - -[chains.gas_price] -price = 10.0 -denom = 'stake' - -[chains.packet_filter] -policy = 'allow' -list = [ - ['transfer', 'channel-*'], -] - -[chains.address_type] -derivation = 'cosmos' diff --git a/.github/integration-tests/docker-compose.yml b/.github/integration-tests/docker-compose.yml deleted file mode 100644 index b00f4a61..00000000 --- a/.github/integration-tests/docker-compose.yml +++ /dev/null @@ -1,227 +0,0 @@ -services: - local-da: - build: - context: ../.. - dockerfile: .github/integration-tests/docker/Dockerfile.local-da - args: - EV_DA_REF: ${EVNODE_DA_VERSION:-v1.0.0-beta.1} - container_name: rollkit-local-da - command: ["local-da", "-listen-all"] - ports: - - "7980:7980" - healthcheck: - test: ["CMD", "nc", "-z", "localhost", "7980"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 10s - networks: - - ibc-test - - # Gaia chain (Cosmos Hub) - gaia-chain: - image: ghcr.io/cosmos/gaia:${GAIA_VERSION:-v25.1.0} - platform: linux/amd64 - container_name: gaia-chain - environment: - - CHAIN_ID=gaia-local - - MONIKER=gaia-local - - KEYRING_BACKEND=test - - GAIA_HOME=/home/nonroot/.gaia_local - - GAIA_MNEMONIC=${GAIA_MNEMONIC:-abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about} - ports: - - "26657:26657" # RPC - - "26656:26656" # P2P - - "9090:9090" # gRPC - - "1317:1317" # API - volumes: - - ../integration-tests/scripts/init-gaia.sh:/home/nonroot/init-gaia.sh:ro - entrypoint: ["/bin/sh","-lc"] - command: ["/bin/sh /home/nonroot/init-gaia.sh"] - healthcheck: - test: ["CMD", "sh", "-c", "nc -z localhost 26657 || exit 1"] - interval: 30s - timeout: 10s - retries: 10 - start_period: 120s - networks: - - ibc-test - - # GM chain (with rollkit) - gm-chain: - build: - context: ../.. - dockerfile: .github/integration-tests/docker/Dockerfile.gm - args: - IGNITE_VERSION: ${IGNITE_VERSION:-v29.3.1} - IGNITE_EVOLVE_APP_VERSION: ${IGNITE_EVOLVE_APP_VERSION:-main} - EVNODE_VERSION: ${EVNODE_VERSION:-v1.0.0-beta.2.0.20250908090838-0584153217ed} - container_name: gm-chain - ports: - - "26757:26757" # RPC - - "26756:26756" # P2P - - "9190:9190" # gRPC - - "1417:1417" # API - volumes: - - ../integration-tests/scripts:/home/gm/scripts:ro - - gm-data:/shared:Z - environment: - - CHAIN_ID=gm - - MONIKER=gm-local - - GM_HOME=/home/gm/.gm - - ATTESTER_MODE=true - - DEBUG=1 - depends_on: - local-da: - condition: service_healthy - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:26757/status"] - interval: 10s - timeout: 5s - retries: 10 - start_period: 30s - networks: - - ibc-test - - # Attester service - attester: - build: - context: ../.. - dockerfile: .github/integration-tests/docker/Dockerfile.attester - container_name: gm-attester - volumes: - - ../integration-tests/scripts:/home/attester/scripts:ro - - gm-data:/home/attester/.gm:Z - environment: - - CHAIN_ID=gm - - GM_NODE=http://gm-chain:26757 - - GM_API=http://gm-chain:1417 - - GM_HOME=/home/attester/.gm - - MNEMONIC=abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about - - VERBOSE=true - - BECH32_ACCOUNT_PREFIX=gm - - BECH32_ACCOUNT_PUBKEY=gmpub - - BECH32_VALIDATOR_PREFIX=gmvaloper - - BECH32_VALIDATOR_PUBKEY=gmvaloperpub - depends_on: - gm-chain: - condition: service_healthy - restart: on-failure - networks: - - ibc-test - - # IBC Setup (only setup, no relayer) - ibc-setup: - image: ghcr.io/informalsystems/hermes:1.13.1 - container_name: ibc-setup - user: root - volumes: - - ../integration-tests/scripts:/home/tester/scripts:ro - - ../integration-tests/config:/home/tester/config:ro - - ibc-shared:/tmp - environment: - - GM_RPC=http://gm-chain:26757 - - GM_GRPC=http://gm-chain:9190 - - GM_API=http://gm-chain:1417 - - GAIA_RPC=http://gaia-chain:26657 - - GAIA_GRPC=http://gaia-chain:9090 - - GAIA_API=http://gaia-chain:1317 - - HERMES_HOME=/root/.hermes - depends_on: - gaia-chain: - condition: service_healthy - gm-chain: - condition: service_healthy - attester: - condition: service_started - restart: "no" - stop_grace_period: 30s - entrypoint: /bin/sh -lc - command: | - 'echo "๐Ÿš€ Preparing Hermes configuration..." && \ - # Ensure curl and jq are available (Alpine or Debian-based images) && \ - (apk add --no-cache curl jq 2>/dev/null || (apt-get update && apt-get install -y curl jq)) && \ - mkdir -p ~/.hermes && \ - cp /home/tester/config/hermes.toml ~/.hermes/config.toml && \ - echo "๐Ÿ”— Setting up IBC connection..." && \ - /home/tester/scripts/setup-ibc.sh && \ - echo "โœ… IBC setup completed successfully!"' - networks: - - ibc-test - - # Hermes Relayer (runs continuously after setup) - hermes-relayer: - image: ghcr.io/informalsystems/hermes:1.13.1 - container_name: hermes-relayer - user: root - volumes: - - ../integration-tests/scripts:/home/tester/scripts:ro - - ../integration-tests/config:/home/tester/config:ro - - ibc-shared:/tmp - environment: - - GM_RPC=http://gm-chain:26757 - - GM_GRPC=http://gm-chain:9190 - - GM_API=http://gm-chain:1417 - - GAIA_RPC=http://gaia-chain:26657 - - GAIA_GRPC=http://gaia-chain:9090 - - GAIA_API=http://gaia-chain:1317 - - HERMES_HOME=/root/.hermes - restart: "no" - entrypoint: /bin/sh -lc - command: | - 'echo "๐Ÿš€ Preparing Hermes configuration..." && \ - mkdir -p ~/.hermes && \ - cp /home/tester/config/hermes.toml ~/.hermes/config.toml && \ - echo "๐Ÿ”‘ Adding relayer keys to hermes..." && \ - echo "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" | hermes keys add --chain gm --mnemonic-file /dev/stdin || echo "GM key already exists" && \ - echo "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" | hermes keys add --chain gaia-local --mnemonic-file /dev/stdin || echo "Gaia key already exists" && \ - echo "๐Ÿ”„ Starting Hermes relayer..." && \ - hermes start' - networks: - - ibc-test - - - # Test runner (runs after IBC setup) - test-runner: - build: - context: .. - dockerfile: integration-tests/docker/Dockerfile.test - container_name: ibc-test-runner - depends_on: - - gm-chain - volumes: - - ../integration-tests/scripts:/home/tester/scripts:ro - - ../integration-tests/config:/home/tester/config:ro - - ibc-shared:/tmp - environment: - - GM_RPC=http://gm-chain:26757 - - GM_GRPC=http://gm-chain:9190 - - GM_API=http://gm-chain:1417 - - GAIA_RPC=http://gaia-chain:26657 - - GAIA_GRPC=http://gaia-chain:9090 - - GAIA_API=http://gaia-chain:1317 - - HERMES_HOME=/home/tester/.hermes - - MAX_WAIT_TIME=300 - command: > - bash -c " - echo '๐Ÿงช Starting integration tests...' && - cd /home/tester && - ./run-integration-test.sh - " - networks: - - ibc-test - -networks: - ibc-test: - driver: bridge - ipam: - config: - - subnet: 172.20.0.0/16 - -# Volumes for persistent data (optional) -volumes: - gaia-data: - gm-data: - driver: local - ibc-shared: - driver: local diff --git a/.github/integration-tests/docker/Dockerfile.local-da b/.github/integration-tests/docker/Dockerfile.local-da deleted file mode 100644 index 519e29e0..00000000 --- a/.github/integration-tests/docker/Dockerfile.local-da +++ /dev/null @@ -1,30 +0,0 @@ -# Build local-da from ev-node source -FROM golang:1.24-alpine AS builder - -# Install build dependencies -RUN apk add --no-cache gcc musl-dev git - -# Set working directory -WORKDIR /workspace - -# Build local-da from rollkit module at the requested version (tag/branch/pseudo-version) -ARG EV_DA_REF=main -RUN GOBIN=/workspace go install github.com/rollkit/rollkit/da/cmd/local-da@${EV_DA_REF} - -# Runtime stage -FROM alpine:3.18 - -# Install runtime dependencies -RUN apk add --no-cache ca-certificates curl netcat-openbsd - -# Copy binary from builder -COPY --from=builder /workspace/local-da /usr/local/bin/local-da - -# Make binary executable -RUN chmod +x /usr/local/bin/local-da - -# Expose port -EXPOSE 7980 - -# Default command -CMD ["local-da", "-listen-all"] diff --git a/.github/integration-tests/docker/Dockerfile.test b/.github/integration-tests/docker/Dockerfile.test deleted file mode 100644 index b4b4c1e4..00000000 --- a/.github/integration-tests/docker/Dockerfile.test +++ /dev/null @@ -1,67 +0,0 @@ -# Build a minimal gmd binary in this same Dockerfile -FROM golang:1.24-bookworm AS gmd-builder - -RUN apt-get update && apt-get install -y --no-install-recommends \ - git curl bash ca-certificates make gcc musl-dev && \ - rm -rf /var/lib/apt/lists/* - -# Install Ignite CLI -RUN curl -sSL https://get.ignite.com/cli! | bash - -WORKDIR /build -# Create a minimal GM app just to get the binary -RUN ignite scaffold chain gm --no-module --skip-git --address-prefix gm -WORKDIR /build/gm -RUN go build -o /gmd ./cmd/gmd - -FROM debian:bookworm-slim - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates curl jq bash coreutils netcat-openbsd openssl wget git \ - && rm -rf /var/lib/apt/lists/* - -# Copy gmd binary from the builder stage -COPY --from=gmd-builder /gmd /usr/local/bin/gmd -RUN chmod +x /usr/local/bin/gmd - -# Download gaiad binary from official release -RUN ARCH=$(dpkg --print-architecture) && \ - if [ "$ARCH" = "amd64" ]; then \ - wget -q https://github.com/cosmos/gaia/releases/download/v20.0.0/gaiad-v20.0.0-linux-amd64 -O /usr/local/bin/gaiad; \ - elif [ "$ARCH" = "arm64" ]; then \ - wget -q https://github.com/cosmos/gaia/releases/download/v20.0.0/gaiad-v20.0.0-linux-arm64 -O /usr/local/bin/gaiad; \ - else \ - echo "Unsupported architecture: $ARCH" && exit 1; \ - fi && \ - chmod +x /usr/local/bin/gaiad - -# Create test user -RUN useradd -m -s /bin/bash tester - -# Copy test scripts -COPY --chown=tester:tester integration-tests/scripts/run-integration-test.sh /home/tester/run-integration-test.sh -COPY --chown=tester:tester integration-tests/scripts/setup-ibc.sh /home/tester/setup-ibc.sh -COPY --chown=tester:tester integration-tests/scripts/test-transfers.sh /home/tester/test-transfers.sh -COPY --chown=tester:tester integration-tests/scripts/wait-for-chain.sh /home/tester/wait-for-chain.sh -COPY --chown=tester:tester integration-tests/scripts/wait-for-attester.sh /home/tester/wait-for-attester.sh - -# Copy hermes config template -COPY --chown=tester:tester integration-tests/config/hermes.toml /home/tester/hermes.toml - -# Make scripts executable -RUN chmod +x /home/tester/*.sh - -# Switch to test user -USER tester -WORKDIR /home/tester - -# Environment variables -ENV GM_RPC=http://gm-chain:26757 -ENV GM_GRPC=http://gm-chain:9190 -ENV GM_API=http://gm-chain:1417 -ENV GAIA_RPC=http://gaia-chain:26657 -ENV GAIA_GRPC=http://gaia-chain:9090 -ENV GAIA_API=http://gaia-chain:1317 -ENV HERMES_HOME=/home/tester/.hermes diff --git a/.github/integration-tests/run-integration-tests.sh b/.github/integration-tests/run-integration-tests.sh deleted file mode 100755 index 078bdca1..00000000 --- a/.github/integration-tests/run-integration-tests.sh +++ /dev/null @@ -1,510 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Integration Test Runner for IBC Attester System -# This script automates the complete integration test workflow - -# Configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -INTEGRATION_DIR="$SCRIPT_DIR" -COMPOSE_FILE="$INTEGRATION_DIR/docker-compose.yml" -LOG_DIR="$INTEGRATION_DIR/logs" - -# Default options -CLEANUP=${CLEANUP:-true} -VERBOSE=${VERBOSE:-false} -BUILD_FRESH=${BUILD_FRESH:-false} -TIMEOUT=${TIMEOUT:-600} # 10 minutes default timeout - -export DO_NOT_TRACK=${DO_NOT_TRACK:-true} -export EVNODE_VERSION=${EVNODE_VERSION:-"v1.0.0-beta.2.0.20250917144924-05372840f308"} -export EVNODE_DA_VERSION=${EVNODE_DA_VERSION:-"v1.0.0-beta.1"} -export IGNITE_VERSION=${IGNITE_VERSION:-"v29.3.1"} -export IGNITE_EVOLVE_APP_VERSION=${IGNITE_EVOLVE_APP_VERSION:-"main"} -export GAIA_VERSION=${GAIA_VERSION:-"v25.1.0"} - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Logging functions -log_info() { - echo -e "${BLUE}[INFO]${NC} $*" -} - -log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $*" -} - -log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $*" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $*" -} - -# Show usage -usage() { - cat << EOF -Usage: $0 [OPTIONS] - -Run IBC integration tests for the attester system. - -OPTIONS: - --no-cleanup Don't cleanup containers after test - --verbose Enable verbose logging - --build-fresh Force rebuild of all Docker images - --timeout SECONDS Maximum time to wait for tests (default: 600) - --help Show this help message - -EXAMPLES: - $0 # Run tests with default settings - $0 --verbose --no-cleanup # Run with verbose output, keep containers - $0 --build-fresh # Force rebuild images and run tests - $0 --timeout 300 # Run with 5 minute timeout - -ENVIRONMENT VARIABLES: - CLEANUP=false # Same as --no-cleanup - VERBOSE=true # Same as --verbose - BUILD_FRESH=true # Same as --build-fresh - TIMEOUT=300 # Same as --timeout 300 - -EOF -} - -# Parse command line arguments -while [[ $# -gt 0 ]]; do - case $1 in - --no-cleanup) - CLEANUP=false - shift - ;; - --verbose) - VERBOSE=true - shift - ;; - --build-fresh) - BUILD_FRESH=true - shift - ;; - --timeout) - TIMEOUT="$2" - shift 2 - ;; - --help) - usage - exit 0 - ;; - *) - log_error "Unknown option: $1" - usage - exit 1 - ;; - esac -done - -# Validate requirements -check_requirements() { - log_info "Checking requirements..." - - # Check Docker - if ! command -v docker &> /dev/null; then - log_error "Docker is not installed or not in PATH" - exit 1 - fi - - # Check Docker Compose - if ! docker compose version &> /dev/null; then - log_error "Docker Compose is not available" - log_error "Make sure you have Docker Compose v2 installed" - exit 1 - fi - - # Check if integration test directory exists - if [[ ! -d "$INTEGRATION_DIR" ]]; then - log_error "Integration test directory not found: $INTEGRATION_DIR" - log_error "Run this script from the project root directory" - exit 1 - fi - - # Check if compose file exists - if [[ ! -f "$COMPOSE_FILE" ]]; then - log_error "Docker Compose file not found: $COMPOSE_FILE" - exit 1 - fi - - log_success "All requirements met" -} - -# Setup test environment -setup_environment() { - log_info "Setting up test environment..." - - # Create log directory - mkdir -p "$LOG_DIR" - - # Set script permissions - chmod +x "$INTEGRATION_DIR"/scripts/*.sh - - # Clean up any previous runs - cd "$INTEGRATION_DIR" - docker compose down -v --remove-orphans &>/dev/null || true - - log_success "Test environment ready" -} - -# Build Docker images -build_images() { - log_info "Building Docker images..." - cd "$INTEGRATION_DIR" - - local build_args=() - - if [[ "$BUILD_FRESH" == "true" ]]; then - log_info "Force rebuilding all images..." - build_args+=(--no-cache) - fi - - if [[ "$VERBOSE" == "true" ]]; then - build_args+=(--progress=plain) - fi - - log_info "Using versions: IGNITE_VERSION=$IGNITE_VERSION, IGNITE_EVOLVE_APP_VERSION=$IGNITE_EVOLVE_APP_VERSION, EVNODE_VERSION=$EVNODE_VERSION, EVNODE_DA_VERSION=$EVNODE_DA_VERSION, GAIA_VERSION=$GAIA_VERSION" - - if ! docker compose build "${build_args[@]+"${build_args[@]}"}"; then - log_error "Failed to build Docker images" - return 1 - fi - - log_success "Docker images built successfully" -} - -# Start services -start_services() { - log_info "Starting services..." - cd "$INTEGRATION_DIR" - - # Start infrastructure services first (including attester) - log_info "Starting infrastructure services (local-da, gaia-chain, gm-chain, attester)..." - docker compose up -d local-da gaia-chain gm-chain attester - - # Wait for chains to be healthy - log_info "Waiting for chains to be healthy..." - local max_wait=120 - local wait_count=0 - - while [[ $wait_count -lt $max_wait ]]; do - if docker compose ps | grep -E "(gaia-chain|gm-chain)" | grep -q "healthy"; then - log_success "Chains are healthy" - break - fi - - sleep 5 - wait_count=$((wait_count + 5)) - log_info "Waiting for chains... ($wait_count/${max_wait}s)" - done - - if [[ $wait_count -ge $max_wait ]]; then - log_error "Chains did not become healthy within ${max_wait}s" - # Dump recent gm-chain logs to console for quick diagnosis - log_info "Recent gm-chain logs (last 200 lines):" - docker compose logs --tail=200 gm-chain || true - show_service_status - return 1 - fi - - log_success "Infrastructure services started and ready" -} - -# Setup IBC connections -setup_ibc() { - log_info "Starting IBC setup..." - cd "$INTEGRATION_DIR" - - # Start IBC setup container (runs to completion) - docker compose up -d ibc-setup - - # Wait for ibc-setup to produce the connection info in the shared volume - log_info "Waiting for IBC channels to be created..." - local max_wait=600 # allow up to 10 minutes for setup - local wait_count=0 - - while [[ $wait_count -lt $max_wait ]]; do - # Probe the shared volume using the test-runner image (has /tmp mounted) - if docker compose run --rm -T test-runner sh -lc 'test -f /tmp/ibc-connection-info' >/dev/null 2>&1; then - log_success "IBC channels created successfully" - return 0 - fi - - sleep 10 - wait_count=$((wait_count + 10)) - log_info "Waiting for IBC setup to complete... ($wait_count/${max_wait}s)" - - # Show some progress by showing recent logs - if [[ $((wait_count % 60)) -eq 0 ]]; then - log_info "Recent IBC setup logs:" - docker compose logs --tail=10 ibc-setup || true - - # Also check if attester is still having issues - if docker compose ps attester | grep -q "Restarting\|Exited"; then - log_warning "Note: Attester service is still restarting, which may affect IBC setup" - docker compose logs --tail=5 attester || true - fi - fi - done - - log_error "IBC setup did not produce connection info within ${max_wait}s" - docker compose logs ibc-setup || true - return 1 -} - -# Start Hermes relayer -start_hermes() { - log_info "Starting Hermes IBC relayer..." - cd "$INTEGRATION_DIR" - - docker compose up -d hermes-relayer - - # Give it a moment to start - sleep 5 - - # Check if hermes is running - if docker compose ps hermes-relayer | grep -q "Up"; then - log_success "Hermes relayer started successfully" - else - log_error "Failed to start Hermes relayer" - docker compose logs hermes-relayer - return 1 - fi -} - -# Run integration tests -run_tests() { - log_info "Running integration tests..." - cd "$INTEGRATION_DIR" - - # Ensure connection info is available before starting tests - if ! docker compose run --rm -T test-runner sh -lc 'test -f /tmp/ibc-connection-info' >/dev/null 2>&1; then - log_error "Connection info not available; cannot run tests" - docker compose logs ibc-setup || true - return 1 - fi - - # Start test runner - docker compose up -d test-runner - - # Robustly wait for the test container lifecycle to finish - local container_name="ibc-test-runner" - local appear_timeout=60 # wait up to 60s for container to appear - local appear_wait=0 - - log_info "Waiting for test-runner container to appear..." - while [[ $appear_wait -lt $appear_timeout ]]; do - if docker ps -a --format '{{.Names}}' | grep -qx "$container_name"; then - break - fi - sleep 2 - appear_wait=$((appear_wait + 2)) - done - - if ! docker ps -a --format '{{.Names}}' | grep -qx "$container_name"; then - log_error "Test runner container did not appear within ${appear_timeout}s" - docker compose logs test-runner || true - return 1 - fi - - # Wait for tests to complete - log_info "Waiting for integration tests to complete..." - local max_wait=300 # 5 minutes for tests - local wait_count=0 - - while [[ $wait_count -lt $max_wait ]]; do - local status - status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null || echo "unknown") - - if [[ "$status" == "exited" || "$status" == "dead" ]]; then - local exit_code - exit_code=$(docker inspect -f '{{.State.ExitCode}}' "$container_name" 2>/dev/null || echo "1") - if [[ "$exit_code" == "0" ]]; then - log_success "Integration tests passed!" - docker compose logs test-runner || true - return 0 - else - log_error "Integration tests failed with exit code: $exit_code" - docker compose logs test-runner || true - return 1 - fi - fi - - sleep 5 - wait_count=$((wait_count + 5)) - log_info "Running tests... ($wait_count/${max_wait}s) [status: $status]" - - # Show progress periodically - if [[ $((wait_count % 30)) -eq 0 ]]; then - log_info "Recent test logs:" - docker compose logs --tail=5 test-runner || true - fi - done - - log_error "Tests did not complete within ${max_wait}s" - docker compose logs test-runner || true - return 1 -} - -# Show service status -show_service_status() { - log_info "Service status:" - cd "$INTEGRATION_DIR" - docker compose ps - - if [[ "$VERBOSE" == "true" ]]; then - echo "" - log_info "Service logs:" - for service in local-da gaia-chain gm-chain attester; do - echo "" - echo "=== $service ===" - docker compose logs --tail=20 "$service" 2>/dev/null || echo "No logs available" - done - else - # Always show attester logs if it's having issues - if docker compose ps attester | grep -q "Restarting\|Exited"; then - echo "" - log_warning "Attester service appears to be having issues:" - echo "=== attester logs ===" - docker compose logs --tail=50 attester 2>/dev/null || echo "No logs available" - fi - fi -} - - -# Cleanup function -cleanup() { - if [[ "$CLEANUP" == "true" ]]; then - log_info "Cleaning up test environment..." - cd "$INTEGRATION_DIR" - - # Collect logs before cleanup - collect_logs - - # Stop and remove containers - docker compose down -v --remove-orphans - - # Optional: clean up images (uncomment if needed) - # docker compose down --rmi all - - log_success "Cleanup completed" - else - log_warning "Skipping cleanup (--no-cleanup specified)" - log_info "To manually cleanup run: cd $INTEGRATION_DIR && docker compose down -v" - fi -} - -# Collect logs for debugging -collect_logs() { - log_info "Collecting logs..." - cd "$INTEGRATION_DIR" - - local timestamp=$(date +"%Y%m%d_%H%M%S") - local log_archive="$LOG_DIR/integration_test_logs_$timestamp" - - mkdir -p "$log_archive" - - # Collect container logs - for service in local-da gaia-chain gm-chain attester ibc-setup hermes-relayer test-runner; do - docker compose logs "$service" > "$log_archive/${service}.log" 2>/dev/null || echo "No logs for $service" > "$log_archive/${service}.log" - done - - # Attempt to collect gm-chain node home (config/data/logs) - mkdir -p "$log_archive/gm-home" - docker compose cp gm-chain:/home/gm/.gm "$log_archive/gm-home" 2>/dev/null || true - - # Collect service status - docker compose ps > "$log_archive/service_status.txt" 2>/dev/null || true - - # Create summary - cat > "$log_archive/test_summary.txt" << EOF -Integration Test Summary -======================== -Date: $(date) -Script: $0 -Arguments: $* -Cleanup: $CLEANUP -Verbose: $VERBOSE -Build Fresh: $BUILD_FRESH -Timeout: $TIMEOUT -EOF - - log_success "Logs collected in: $log_archive" -} - -# Main execution function -main() { - log_info "๐Ÿงช Starting IBC Integration Tests" - log_info "==================================" - - local start_time=$(date +%s) - local exit_code=0 - - # Setup trap for cleanup - trap cleanup EXIT - - # Execute test steps - check_requirements - setup_environment - - if ! build_images; then - log_error "Image build failed" - exit_code=1 - exit $exit_code - fi - - # Step 1: Start infrastructure services (local-da, gaia-chain, gm-chain, attester) - if ! start_services; then - log_error "Service startup failed" - exit_code=1 - exit $exit_code - fi - - show_service_status - - # Step 2: Setup IBC connections and wait for completion - if ! setup_ibc; then - log_error "IBC setup failed" - exit_code=1 - exit $exit_code - fi - - # Step 3: Start Hermes relayer - if ! start_hermes; then - log_error "Hermes relayer startup failed" - exit_code=1 - exit $exit_code - fi - - # Step 4: Run integration tests - if ! run_tests; then - log_error "Integration tests failed" - exit_code=1 - exit $exit_code - fi - - # Calculate duration - local end_time=$(date +%s) - local duration=$((end_time - start_time)) - - log_info "Test duration: ${duration}s" - log_info "==================================" - - exit $exit_code -} - -# Handle script interruption -trap 'log_error "Script interrupted"; cleanup; exit 130' INT TERM - -# Run main function -main "$@" diff --git a/.github/integration-tests/scripts/init-gaia.sh b/.github/integration-tests/scripts/init-gaia.sh deleted file mode 100755 index 2b29d294..00000000 --- a/.github/integration-tests/scripts/init-gaia.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/sh -set -eu - -# Configuration -CHAIN_ID="${CHAIN_ID:-gaia-local}" -MONIKER="${MONIKER:-gaia-local}" -GAIA_HOME="${GAIA_HOME:-$HOME/.gaia_local}" -KEY_NAME="${KEY_NAME:-validator}" -KEYRING_BACKEND="${KEYRING_BACKEND:-test}" -MIN_GAS_PRICE="${MIN_GAS_PRICE:-0.01stake}" -STAKE_AMOUNT="${STAKE_AMOUNT:-500000000stake}" -GENESIS_COINS="${GENESIS_COINS:-100000000000stake}" - -# Validator mnemonic (same as your script) -MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" -# Relayer mnemonic (different from validator) -RELAYER_MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" - -echo "๐Ÿš€ Initializing Gaia chain..." -echo " Chain ID: $CHAIN_ID" -echo " Moniker: $MONIKER" -echo " Home: $GAIA_HOME" - -# Initialize chain -if [ ! -f "$GAIA_HOME/config/genesis.json" ]; then - echo "๐Ÿ”ง Initializing chain..." - gaiad init "$MONIKER" --chain-id "$CHAIN_ID" --home "$GAIA_HOME" - - echo "๐Ÿ”‘ Creating validator key..." - echo "$MNEMONIC" | gaiad keys add "$KEY_NAME" --keyring-backend "$KEYRING_BACKEND" --home "$GAIA_HOME" --recover - VALIDATOR_ADDRESS=$(gaiad keys show "$KEY_NAME" -a --keyring-backend "$KEYRING_BACKEND" --home "$GAIA_HOME") - - echo "๐Ÿ”‘ Creating relayer key..." - echo "$RELAYER_MNEMONIC" | gaiad keys add "relayer" --keyring-backend "$KEYRING_BACKEND" --home "$GAIA_HOME" --recover - RELAYER_ADDRESS=$(gaiad keys show "relayer" -a --keyring-backend "$KEYRING_BACKEND" --home "$GAIA_HOME") - - echo "๐Ÿ’ฐ Adding genesis accounts..." - gaiad genesis add-genesis-account "$VALIDATOR_ADDRESS" "$GENESIS_COINS" --home "$GAIA_HOME" - gaiad genesis add-genesis-account "$RELAYER_ADDRESS" "100000000000stake" --home "$GAIA_HOME" - - echo "๐Ÿงพ Generating genesis transaction..." - gaiad genesis gentx "$KEY_NAME" "$STAKE_AMOUNT" \ - --chain-id "$CHAIN_ID" \ - --keyring-backend "$KEYRING_BACKEND" \ - --home "$GAIA_HOME" - - echo "๐Ÿ“ฆ Collecting genesis transactions..." - gaiad genesis collect-gentxs --home "$GAIA_HOME" - - # Configure app.toml - APP_TOML="$GAIA_HOME/config/app.toml" - if [ -f "$APP_TOML" ]; then - echo "โš™๏ธ Configuring minimum gas prices..." - sed -i "s|^minimum-gas-prices = \".*\"|minimum-gas-prices = \"$MIN_GAS_PRICE\"|" "$APP_TOML" - - # Enable API server - sed -i 's|^enable = false|enable = true|' "$APP_TOML" - sed -i 's|^address = "tcp://localhost:1317"|address = "tcp://0.0.0.0:1317"|' "$APP_TOML" - fi - - # Configure config.toml for container networking - CONFIG_TOML="$GAIA_HOME/config/config.toml" - if [ -f "$CONFIG_TOML" ]; then - echo "โš™๏ธ Configuring networking..." - # Set RPC to listen on all interfaces - sed -i 's|^laddr = "tcp://127.0.0.1:26657"|laddr = "tcp://0.0.0.0:26657"|' "$CONFIG_TOML" - # Set P2P to listen on all interfaces - sed -i 's|^laddr = "tcp://0.0.0.0:26656"|laddr = "tcp://0.0.0.0:26656"|' "$CONFIG_TOML" - # Disable strict address book - sed -i 's|^addr_book_strict = true|addr_book_strict = false|' "$CONFIG_TOML" - fi - - echo "โœ… Gaia chain initialized successfully" -else - echo "โ„น๏ธ Chain already initialized, using existing configuration" -fi - -echo "๐Ÿš€ Starting Gaia node..." -echo " RPC: http://0.0.0.0:26657" -echo " gRPC: 0.0.0.0:9090" -echo " API: http://0.0.0.0:1317" - -# Start the node -exec gaiad start --home "$GAIA_HOME" \ - --p2p.laddr tcp://0.0.0.0:26656 \ - --rpc.laddr tcp://0.0.0.0:26657 \ - --grpc.address 0.0.0.0:9090 diff --git a/.github/integration-tests/scripts/init-gm.sh b/.github/integration-tests/scripts/init-gm.sh deleted file mode 100755 index c6b5b74f..00000000 --- a/.github/integration-tests/scripts/init-gm.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash -set -euo pipefail -# Enable shell tracing when DEBUG=1 for easier CI debugging -if [[ "${DEBUG:-0}" == "1" ]]; then - set -x -fi - -# Configuration -CHAIN_ID="${CHAIN_ID:-gm}" -MONIKER="${MONIKER:-gm}" -GM_HOME="${GM_HOME:-$HOME/.gm}" -KEY_NAME="${KEY_NAME:-validator}" -KEYRING_BACKEND="${KEYRING_BACKEND:-test}" -BINARY="${BINARY:-gmd}" -ATTESTER_MODE="${ATTESTER_MODE:-false}" - -# Mnemonics -MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" -RELAYER_MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" - -echo "๐Ÿš€ Initializing GM chain..." -echo " Chain ID: $CHAIN_ID" -echo " Moniker: $MONIKER" -echo " Home: $GM_HOME" -echo " Attester Mode: $ATTESTER_MODE" -echo " Ignite: $(command -v ignite || echo 'ignite not found')" -if command -v ignite >/dev/null 2>&1; then - ignite version || true -fi - -# Ensure Ignite home is writable (copied in image) -export IGNITE_HOME=/home/gm/.ignite -mkdir -p "$IGNITE_HOME/apps" 2>/dev/null || true -sudo chown -R gm:gm "$IGNITE_HOME" 2>/dev/null || true -sudo chmod -R u+rwX,go+rX "$IGNITE_HOME" 2>/dev/null || true - -# Wait for local-da to be available -echo "โณ Waiting for local-da to be available..." -./wait-for-da.sh - -# Reset and initialize chain -if [[ -d "$GM_HOME" ]]; then - # If it's a mount point (Docker volume), just clear contents instead of removing directory - if mountpoint -q "$GM_HOME" 2>/dev/null || [[ $(stat -c %d "$GM_HOME" 2>/dev/null || echo "0") != $(stat -c %d "$GM_HOME/.." 2>/dev/null || echo "1") ]]; then - echo "๐Ÿงน Clearing existing chain state from volume..." - rm -rf "$GM_HOME"/* "$GM_HOME"/.* 2>/dev/null || true - else - rm -rf "$GM_HOME" - echo "๐Ÿงน Removed existing chain state" - fi -fi - -echo "๐Ÿ”ง Initializing chain with ignite evolve..." -cd /home/gm/gm -ls -la || true - -# Ensure evolve app is available; install if needed -if ! ignite app list -g 2>/dev/null | grep -qi "evolve"; then - echo "โ„น๏ธ 'evolve' app not found in Ignite. Installing..." - ignite app install -g "github.com/ignite/apps/evolve@${IGNITE_EVOLVE_APP_VERSION:-main}" -fi - -# Run evolve init and require success -ignite evolve init -if [[ ! -f "$GM_HOME/config/genesis.json" ]]; then - echo "โŒ ignite evolve init did not produce genesis.json. Aborting." - exit 1 -fi - -echo "๐Ÿ”‘ Setting up keys..." -# Add validator key (same key will be used for attester) -echo "$MNEMONIC" | "$BINARY" keys add "$KEY_NAME" --keyring-backend "$KEYRING_BACKEND" --home "$GM_HOME" --recover --hd-path "m/44'/118'/0'/0/0" -VALIDATOR_ADDRESS=$("$BINARY" keys show "$KEY_NAME" -a --keyring-backend "$KEYRING_BACKEND" --home "$GM_HOME") -ATTESTER_ADDRESS="$VALIDATOR_ADDRESS" - -# Add relayer key (different mnemonic) -echo "$RELAYER_MNEMONIC" | "$BINARY" keys add "relayer" --keyring-backend "$KEYRING_BACKEND" --home "$GM_HOME" --recover --hd-path "m/44'/118'/0'/0/0" -RELAYER_ADDRESS=$("$BINARY" keys show "relayer" -a --keyring-backend "$KEYRING_BACKEND" --home "$GM_HOME") - -# Ensure client.toml has the correct RPC node (127.0.0.1:26757 instead of localhost:26657) -mkdir -p "$GM_HOME/config" -if [ -f "$GM_HOME/config/client.toml" ]; then - sed -i 's|^node *=.*|node = "tcp://127.0.0.1:26757"|' "$GM_HOME/config/client.toml" -else - cat > "$GM_HOME/config/client.toml" </dev/null || chown -R gm:gm /shared 2>/dev/null || true -mkdir -p /shared/config /shared/data 2>/dev/null || true -if [[ -d "/shared" && -w "/shared" ]]; then - cp -r "$GM_HOME/config"/* /shared/config/ 2>/dev/null || true - cp -r "$GM_HOME/data"/* /shared/data/ 2>/dev/null || true - # Copy other important files to root of shared volume - cp "$GM_HOME"/keyring-test-* /shared/ 2>/dev/null || true - echo " Config files available for attester" -else - echo " โš ๏ธ Cannot write to /shared - attester may not have access to keys" -fi - -# Build start command -START_CMD=("$BINARY" start --rollkit.node.aggregator \ - --rollkit.da.address "http://local-da:7980" \ - --home "$GM_HOME" \ - --rpc.laddr tcp://0.0.0.0:26757 \ - --grpc.address 0.0.0.0:9190 \ - --api.enable \ - --api.address tcp://0.0.0.0:1417 \ - --minimum-gas-prices 0.001stake) - -# Add attester-specific flag if in attester mode -if [[ "$ATTESTER_MODE" == "true" ]]; then - START_CMD+=(--evnode.attester-mode=true) - echo "๐Ÿš€ Starting GM chain in ATTESTER MODE..." -else - echo "๐Ÿš€ Starting GM chain in NORMAL MODE..." -fi - -echo " RPC: http://0.0.0.0:26757" -echo " gRPC: 0.0.0.0:9190" -echo " API: http://0.0.0.0:1417" - -# Copy configuration files to shared volume before starting (in case of restart) -echo "๐Ÿ“‹ Ensuring config files are available in shared volume..." -# Ensure permissions are correct and directory exists -sudo chown -R gm:gm /shared 2>/dev/null || chown -R gm:gm /shared 2>/dev/null || true -mkdir -p /shared/config /shared/data 2>/dev/null || true -if [[ -d "/shared" && -w "/shared" ]]; then - cp -r "$GM_HOME/config"/* /shared/config/ 2>/dev/null || true - cp -r "$GM_HOME/data"/* /shared/data/ 2>/dev/null || true - # Copy other important files to root of shared volume - cp "$GM_HOME"/keyring-test-* /shared/ 2>/dev/null || true - echo " Config files synced for attester" -else - echo " โš ๏ธ Cannot write to /shared - attester may not have access to keys" -fi - -# Execute the start command -exec "${START_CMD[@]}" diff --git a/.github/integration-tests/scripts/prepare-deps.sh b/.github/integration-tests/scripts/prepare-deps.sh deleted file mode 100755 index 9e344927..00000000 --- a/.github/integration-tests/scripts/prepare-deps.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# Script to prepare local dependencies for Docker build - -set -e - -echo "Preparing local dependencies for Docker build..." - -# Check if we're in the right directory -if [ ! -f "go.mod" ]; then - echo "Error: go.mod not found. Run this script from the gm/ directory." - exit 1 -fi - -# Create deps directory -mkdir -p deps - -# Copy local dependencies -if [ -d "../ev-abci" ]; then - echo "Copying ev-abci..." - cp -r ../ev-abci deps/ -else - echo "Warning: ../ev-abci not found" -fi - -if [ -d "../ev-node" ]; then - echo "Copying ev-node..." - cp -r ../ev-node deps/ -else - echo "Warning: ../ev-node not found" -fi - -if [ -d "../tastora" ]; then - echo "Copying tastora..." - cp -r ../tastora deps/ -else - echo "Warning: ../tastora not found" -fi - -echo "Dependencies prepared in deps/ directory" \ No newline at end of file diff --git a/.github/integration-tests/scripts/run-attester.sh b/.github/integration-tests/scripts/run-attester.sh deleted file mode 100755 index b0742d61..00000000 --- a/.github/integration-tests/scripts/run-attester.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Configuration -CHAIN_ID="${CHAIN_ID:-gm}" -GM_HOME="${GM_HOME:-/tmp/.gm}" -GM_NODE="${GM_NODE:-http://gm-chain:26757}" -GM_API="${GM_API:-http://gm-chain:1417}" -MNEMONIC="${MNEMONIC:-abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about}" -VERBOSE="${VERBOSE:-true}" - -# Bech32 prefix configuration -BECH32_ACCOUNT_PREFIX="${BECH32_ACCOUNT_PREFIX:-gm}" -BECH32_ACCOUNT_PUBKEY="${BECH32_ACCOUNT_PUBKEY:-gmpub}" -BECH32_VALIDATOR_PREFIX="${BECH32_VALIDATOR_PREFIX:-gmvaloper}" -BECH32_VALIDATOR_PUBKEY="${BECH32_VALIDATOR_PUBKEY:-gmvaloperpub}" - -echo "๐Ÿค– Starting attester service..." -echo " Chain ID: $CHAIN_ID" -echo " Node: $GM_NODE" -echo " API: $GM_API" -echo " Home: $GM_HOME" -echo " Bech32 Prefixes:" -echo " Account: $BECH32_ACCOUNT_PREFIX / $BECH32_ACCOUNT_PUBKEY" -echo " Validator: $BECH32_VALIDATOR_PREFIX / $BECH32_VALIDATOR_PUBKEY" - -# Wait for GM chain to be ready -echo "โณ Waiting for GM chain to be ready..." -./wait-for-chain.sh "$GM_NODE" "$GM_API" - -echo "๐Ÿ” Checking for required validator files..." -echo " Looking for files in $GM_HOME..." -echo " Directory contents:" -find "$GM_HOME" -type f 2>/dev/null || echo " Directory doesn't exist or is empty" - -# The gm-chain copies files to /shared which is mounted as $GM_HOME -# Files should be at $GM_HOME/config/ and $GM_HOME/data/ -PRIV_KEY_FILE="$GM_HOME/config/priv_validator_key.json" -PRIV_STATE_FILE="$GM_HOME/data/priv_validator_state.json" - -if [[ ! -f "$PRIV_KEY_FILE" ]]; then - echo "โŒ ERROR: priv_validator_key.json not found at $PRIV_KEY_FILE" - echo " Available files in config:" - ls -la "$GM_HOME/config/" 2>/dev/null || echo " config/ directory doesn't exist" - exit 1 -fi - -if [[ ! -f "$PRIV_STATE_FILE" ]]; then - echo "โŒ ERROR: priv_validator_state.json not found at $PRIV_STATE_FILE" - echo " Available files in data:" - ls -la "$GM_HOME/data/" 2>/dev/null || echo " data/ directory doesn't exist" - exit 1 -fi - -echo "โœ… Validator files found at:" -echo " Key: $PRIV_KEY_FILE" -echo " State: $PRIV_STATE_FILE" -echo "๐Ÿš€ Attester is ready, starting attestation..." - -# Build attester command -ATTESTER_CMD=(attester - --chain-id="$CHAIN_ID" - --home="$GM_HOME" - --mnemonic="$MNEMONIC" - --api-addr="$GM_API" - --node="$GM_NODE" - --bech32-account-prefix="$BECH32_ACCOUNT_PREFIX" - --bech32-account-pubkey="$BECH32_ACCOUNT_PUBKEY" - --bech32-validator-prefix="$BECH32_VALIDATOR_PREFIX" - --bech32-validator-pubkey="$BECH32_VALIDATOR_PUBKEY" -) - -if [[ "$VERBOSE" == "true" ]]; then - ATTESTER_CMD+=(--verbose) -fi - -echo " Command: ${ATTESTER_CMD[*]}" - -# Execute attester -exec "${ATTESTER_CMD[@]}" \ No newline at end of file diff --git a/.github/integration-tests/scripts/run-integration-test.sh b/.github/integration-tests/scripts/run-integration-test.sh deleted file mode 100755 index c75776c2..00000000 --- a/.github/integration-tests/scripts/run-integration-test.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash -set -euo pipefail - -echo "๐Ÿงช Starting IBC Integration Tests" -echo "================================" -echo "" - -# Configuration -GM_RPC="${GM_RPC:-http://gm-chain:26757}" -GM_GRPC="${GM_GRPC:-http://gm-chain:9190}" -GM_API="${GM_API:-http://gm-chain:1417}" -GAIA_RPC="${GAIA_RPC:-http://gaia-chain:26657}" -GAIA_GRPC="${GAIA_GRPC:-http://gaia-chain:9090}" -GAIA_API="${GAIA_API:-http://gaia-chain:1317}" -HERMES_HOME="${HERMES_HOME:-/home/tester/.hermes}" - -# Test parameters -MAX_WAIT_TIME="${MAX_WAIT_TIME:-300}" # 5 minutes max wait - -echo "๐Ÿ“‹ Test Configuration:" -echo " GM Chain RPC: $GM_RPC" -echo " GM Chain API: $GM_API" -echo " Gaia Chain RPC: $GAIA_RPC" -echo " Gaia Chain API: $GAIA_API" -echo " Max Wait Time: ${MAX_WAIT_TIME}s" -echo "" - -# Step 1: Wait for chains to be ready -echo "๐Ÿ”„ Step 1: Waiting for chains to be ready..." -echo "" - -echo " Waiting for Gaia chain..." -./wait-for-chain.sh "$GAIA_RPC" "$GAIA_API" - -echo "" -echo " Waiting for GM chain..." -./wait-for-chain.sh "$GM_RPC" "$GM_API" - -echo "" -echo "โœ… Both chains are ready!" -echo "" - -# Step 2: Wait for attester to be running -echo "๐Ÿ”„ Step 2: Waiting for attester to start..." -echo "" -./wait-for-attester.sh - -echo "" -echo "โœ… Attester is running!" -echo "" - -# Step 3: Final validation -echo "๐Ÿ”„ Step 3: Final validation..." -echo "" - -# Check that both chains are still healthy -echo " Checking chain health..." -if ! curl -f -s "$GM_RPC/status" >/dev/null; then - echo "โŒ GM chain is not healthy" - exit 1 -fi - -if ! curl -f -s "$GAIA_RPC/status" >/dev/null; then - echo "โŒ Gaia chain is not healthy" - exit 1 -fi - -echo "โœ… All chains are healthy" -echo "" - -echo "๐ŸŽ‰ Basic Setup Validation Passed!" -echo "=================================" -echo "" -echo "โœ… All validation steps completed successfully:" -echo " โœ… Chains initialized and running" -echo " โœ… Attester service operational" -echo " โœ… System ready for IBC setup" -echo "" - -# Step 4: Run IBC transfer tests -echo "๐Ÿ”„ Step 4: Running IBC transfer tests..." -echo "" -./test-transfers.sh - -echo "" -echo "๐ŸŽ‰ Integration Tests Completed Successfully!" -echo "==========================================" -echo "" -echo "โœ… All test steps completed successfully:" -echo " โœ… Chains initialized and running" -echo " โœ… Attester service operational" -echo " โœ… IBC transfers tested" -echo "" -echo "๐Ÿš€ Your IBC integration system is fully operational!" \ No newline at end of file diff --git a/.github/integration-tests/scripts/setup-ibc.sh b/.github/integration-tests/scripts/setup-ibc.sh deleted file mode 100755 index ca3c380f..00000000 --- a/.github/integration-tests/scripts/setup-ibc.sh +++ /dev/null @@ -1,498 +0,0 @@ -#!/bin/bash -set -e # Exit on any error - -# Configuration for chains - adapted for Docker containers -GM_CHAIN_ID="gm" -GAIA_CHAIN_ID="gaia-local" -GM_RPC="http://gm-chain:26757" -GAIA_RPC="http://gaia-chain:26657" -GM_GRPC="http://gm-chain:9190" -GAIA_GRPC="http://gaia-chain:9090" - -HERMES_CONFIG_DIR="$HOME/.hermes" -HERMES_CONFIG="$HERMES_CONFIG_DIR/config.toml" - -# Mnemonic for relayer accounts (separate from validators) -RELAYER_MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" - -echo "๐Ÿ”— Setting up IBC connection between GM and Gaia chains..." - -# Check if hermes is installed -if ! command -v hermes &> /dev/null; then - echo "โŒ Error: hermes is not installed or not in PATH" - echo "Install it with: cargo install ibc-relayer-cli --bin hermes" - exit 1 -fi - -# Create hermes config directory -echo "๐Ÿ“ Creating hermes config directory..." -mkdir -p "$HERMES_CONFIG_DIR" - -# Create hermes configuration -echo "โš™๏ธ Creating hermes configuration..." -cat > "$HERMES_CONFIG" << 'EOF' -[global] -log_level = 'debug' - -[mode] - -[mode.clients] -enabled = true -refresh = true -misbehaviour = false - -[mode.connections] -enabled = false - -[mode.channels] -enabled = false - -[mode.packets] -enabled = true -clear_interval = 100 -clear_on_start = true -tx_confirmation = false - -[rest] -enabled = false -host = '127.0.0.1' -port = 3000 - -[telemetry] -enabled = false -host = '127.0.0.1' -port = 3001 - -[[chains]] -id = 'gm' -type = 'CosmosSdk' -rpc_addr = 'http://gm-chain:26757' -grpc_addr = 'http://gm-chain:9190' -rpc_timeout = '10s' -trusted_node = false -account_prefix = 'gm' -key_name = 'gm-relayer' -key_store_type = 'Test' -store_prefix = 'ibc' -default_gas = 200000 -max_gas = 2000000 -gas_multiplier = 1.5 -max_msg_num = 30 -max_tx_size = 2097152 -max_grpc_decoding_size = 33554432 -clock_drift = '5s' -max_block_time = '30s' -ccv_consumer_chain = false -memo_prefix = '' -sequential_batch_tx = false - -[chains.event_source] -mode = 'pull' -interval = '1s' - -[chains.trust_threshold] -numerator = '1' -denominator = '3' - -[chains.gas_price] -price = 10.0 -denom = 'stake' - -[chains.packet_filter] -policy = 'allow' -list = [ - ['transfer', 'channel-*'], -] - -[chains.address_type] -derivation = 'cosmos' - -[[chains]] -id = 'gaia-local' -type = 'CosmosSdk' -rpc_addr = 'http://gaia-chain:26657' -grpc_addr = 'http://gaia-chain:9090' -rpc_timeout = '10s' -trusted_node = false -account_prefix = 'cosmos' -key_name = 'gaia-relayer' -key_store_type = 'Test' -store_prefix = 'ibc' -default_gas = 200000 -max_gas = 2000000 -gas_multiplier = 1.5 -max_msg_num = 30 -max_tx_size = 2097152 -max_grpc_decoding_size = 33554432 -clock_drift = '5s' -max_block_time = '30s' -ccv_consumer_chain = false -memo_prefix = '' -sequential_batch_tx = false - -[chains.event_source] -mode = 'pull' -interval = '1s' - -[chains.trust_threshold] -numerator = '1' -denominator = '3' - -[chains.gas_price] -price = 10.0 -denom = 'stake' - -[chains.packet_filter] -policy = 'allow' -list = [ - ['transfer', 'channel-*'], -] - -[chains.address_type] -derivation = 'cosmos' -EOF - -echo "โœ… Hermes configuration created at $HERMES_CONFIG" -echo "๐Ÿ“‹ Validating Hermes configuration..." -hermes config validate || { - echo "โŒ Hermes configuration validation failed!" - echo "๐Ÿ“„ Configuration file content:" - cat "$HERMES_CONFIG" - exit 1 -} -echo "โœ… Hermes configuration is valid" - -# Add relayer keys to hermes -echo "๐Ÿ”‘ Adding relayer keys to hermes..." - -# Add GM relayer key -echo "Adding GM relayer key..." -echo "$RELAYER_MNEMONIC" | hermes keys add --chain "$GM_CHAIN_ID" --mnemonic-file /dev/stdin --key-name "gm-relayer" --hd-path "m/44'/118'/0'/0/0" || echo "โš ๏ธ GM key already exists" - -# Add Gaia relayer key -echo "Adding Gaia relayer key..." -echo "$RELAYER_MNEMONIC" | hermes keys add --chain "$GAIA_CHAIN_ID" --mnemonic-file /dev/stdin --key-name "gaia-relayer" --hd-path "m/44'/118'/0'/0/0" || echo "โš ๏ธ Gaia key already exists" - -# Wait for chains to be running -echo "โณ Waiting for chains to be ready..." -sleep 5 - -# Check chain connectivity -echo "๐Ÿ” Checking chain connectivity..." -echo "๐Ÿ” Testing individual chain connections..." - -echo "๐Ÿ” Testing GM chain ($GM_CHAIN_ID) at $GM_RPC..." -if command -v curl >/dev/null 2>&1; then - if curl -s --connect-timeout 5 "$GM_RPC/status" | grep -q "result"; then - echo "โœ… GM chain is accessible via RPC" - GM_BLOCK_HEIGHT=$(curl -s "$GM_RPC/status" | grep -o '"latest_block_height":"[0-9]*"' | grep -o '[0-9]*') - echo " Latest block height: $GM_BLOCK_HEIGHT" - else - echo "โš ๏ธ GM RPC check failed (curl). Continuing..." - fi -else - echo "โ„น๏ธ curl not available; skipping GM RPC check" -fi - -# Test Gaia chain connection -echo "๐Ÿ” Testing Gaia chain ($GAIA_CHAIN_ID) at $GAIA_RPC..." -if command -v curl >/dev/null 2>&1; then - if curl -s --connect-timeout 5 "$GAIA_RPC/status" | grep -q "result"; then - echo "โœ… Gaia chain is accessible via RPC" - GAIA_BLOCK_HEIGHT=$(curl -s "$GAIA_RPC/status" | grep -o '"latest_block_height":"[0-9]*"' | grep -o '[0-9]*') - echo " Latest block height: $GAIA_BLOCK_HEIGHT" - else - echo "โš ๏ธ Gaia RPC check failed (curl). Continuing..." - fi -else - echo "โ„น๏ธ curl not available; skipping Gaia RPC check" -fi - -echo "๐Ÿ” Running Hermes health check..." -hermes health-check || { - echo "โš ๏ธ Health check had warnings, continuing anyway..." - echo " - GM chain: $GM_RPC" - echo " - Gaia chain: $GAIA_RPC" - echo " - Check the logs above for specific connectivity issues" -} - -# Wait until chains report catching_up=false (especially GM in attester mode) -echo "โณ Waiting for chains to finish catching up..." - -wait_for_not_catching_up() { - local name="$1"; local url="$2"; local max_wait="${CATCHUP_MAX_WAIT:-180}"; local waited=0 - # If curl is not available (as in Hermes official image), skip this wait. - if ! command -v curl >/dev/null 2>&1; then - echo "โ„น๏ธ curl not available; skipping catch-up wait for $name" - return 0 - fi - while true; do - local status_json - status_json=$(curl -s "$url/status" || echo "") - if echo "$status_json" | grep -q '"catching_up":false'; then - echo "โœ… $name not catching up" - return 0 - fi - if [ "$waited" -ge "$max_wait" ]; then - echo "โš ๏ธ $name still catching_up after ${max_wait}s; proceeding anyway" - return 0 - fi - sleep 3 - waited=$((waited+3)) - echo " $name catching_up=true... (${waited}/${max_wait}s)" - done -} - -wait_for_not_catching_up "GM chain" "$GM_RPC" -wait_for_not_catching_up "Gaia chain" "$GAIA_RPC" - -# Create IBC client for GM on Gaia -echo "๐Ÿ”— Creating IBC client for GM on Gaia..." -echo "๐Ÿ“‹ Pre-flight checks for client creation..." - -# Check if GM chain is producing blocks -echo " Checking if GM chain is producing blocks..." -if command -v curl >/dev/null 2>&1; then - GM_HEIGHT_1=$(curl -s "$GM_RPC/status" | grep -o '"latest_block_height":"[0-9]*"' | grep -o '[0-9]*' || echo "0") - sleep 3 - GM_HEIGHT_2=$(curl -s "$GM_RPC/status" | grep -o '"latest_block_height":"[0-9]*"' | grep -o '[0-9]*' || echo "0") - if [[ "$GM_HEIGHT_2" -gt "$GM_HEIGHT_1" ]]; then - echo "โœ… GM chain is producing blocks ($GM_HEIGHT_1 -> $GM_HEIGHT_2)" - else - echo "โš ๏ธ GM chain may not be producing blocks (height: $GM_HEIGHT_1)" - fi -else - echo "โ„น๏ธ curl not available; skipping GM block production check" -fi - -# Check chain consensus info -echo " Getting GM chain consensus info..." -if command -v curl >/dev/null 2>&1; then - GM_CONSENSUS=$(curl -s "$GM_RPC/consensus_state" 2>/dev/null || echo "failed") - if [[ "$GM_CONSENSUS" != "failed" ]]; then - echo "โœ… GM chain consensus state accessible" - else - echo "โš ๏ธ Could not get GM chain consensus state" - fi -fi - -echo "๐Ÿš€ Attempting to create IBC client for GM on Gaia..." -echo " Command: RUST_LOG=debug hermes create client --host-chain $GAIA_CHAIN_ID --reference-chain $GM_CHAIN_ID --trust-threshold 1/3" -echo "๐Ÿ“ Running with verbose logging..." - -set +e # Temporarily disable exit on error - -# Create a temporary file to capture all output -TEMP_LOG_1=$(mktemp) -echo "๐Ÿ” Capturing output to temporary file: $TEMP_LOG_1" - -# Run hermes with verbose logging and capture everything -RUST_LOG=debug hermes create client --host-chain "$GAIA_CHAIN_ID" --reference-chain "$GM_CHAIN_ID" --trust-threshold 1/3 > "$TEMP_LOG_1" 2>&1 -CREATE_CLIENT_EXIT_CODE=$? - -# Read the output -CLIENT_OUTPUT_1=$(cat "$TEMP_LOG_1") -CLIENT_GM_ON_GAIA=$(echo "$CLIENT_OUTPUT_1" | grep -o '07-tendermint-[0-9]*' | tail -1) - -# Clean up temp file -rm -f "$TEMP_LOG_1" -set -e # Re-enable exit on error - -echo "๐Ÿ“„ Full client creation output:" -echo "$CLIENT_OUTPUT_1" -echo "๐Ÿ“Š Exit code: $CREATE_CLIENT_EXIT_CODE" - -if [[ $CREATE_CLIENT_EXIT_CODE -eq 0 && -n "$CLIENT_GM_ON_GAIA" ]]; then - echo "โœ… Successfully created client for GM on Gaia: $CLIENT_GM_ON_GAIA" -else - echo "โŒ Failed to create client for GM on Gaia" - echo "๐Ÿ” Troubleshooting information:" - echo " - Host chain: $GAIA_CHAIN_ID (should be running and accessible)" - echo " - Reference chain: $GM_CHAIN_ID (should be producing blocks)" - echo " - GM chain RPC: $GM_RPC" - echo " - Gaia chain RPC: $GAIA_RPC" - echo " - Check if both chains have recent blocks and are synced" -fi - -# Create IBC client for Gaia on GM -echo "๐Ÿ”— Creating IBC client for Gaia on GM..." -echo "๐Ÿ“‹ Pre-flight checks for client creation..." - -# Check if Gaia chain is producing blocks -echo " Checking if Gaia chain is producing blocks..." -if command -v curl >/dev/null 2>&1; then - GAIA_HEIGHT_1=$(curl -s "$GAIA_RPC/status" | grep -o '"latest_block_height":"[0-9]*"' | grep -o '[0-9]*' || echo "0") - sleep 3 - GAIA_HEIGHT_2=$(curl -s "$GAIA_RPC/status" | grep -o '"latest_block_height":"[0-9]*"' | grep -o '[0-9]*' || echo "0") - if [[ "$GAIA_HEIGHT_2" -gt "$GAIA_HEIGHT_1" ]]; then - echo "โœ… Gaia chain is producing blocks ($GAIA_HEIGHT_1 -> $GAIA_HEIGHT_2)" - else - echo "โš ๏ธ Gaia chain may not be producing blocks (height: $GAIA_HEIGHT_1)" - fi -else - echo "โ„น๏ธ curl not available; skipping Gaia block production check" -fi - -# Check chain consensus info -echo " Getting Gaia chain consensus info..." -if command -v curl >/dev/null 2>&1; then - GAIA_CONSENSUS=$(curl -s "$GAIA_RPC/consensus_state" 2>/dev/null || echo "failed") - if [[ "$GAIA_CONSENSUS" != "failed" ]]; then - echo "โœ… Gaia chain consensus state accessible" - else - echo "โš ๏ธ Could not get Gaia chain consensus state" - fi -fi - -echo "๐Ÿš€ Attempting to create IBC client for Gaia on GM..." -echo " Command: RUST_LOG=debug hermes create client --host-chain $GM_CHAIN_ID --reference-chain $GAIA_CHAIN_ID --trust-threshold 1/3" -echo "๐Ÿ“ Running with verbose logging..." - -set +e - -# Create a temporary file to capture all output -TEMP_LOG_2=$(mktemp) -echo "๐Ÿ” Capturing output to temporary file: $TEMP_LOG_2" - -# Run hermes with verbose logging and capture everything -RUST_LOG=debug hermes create client --host-chain "$GM_CHAIN_ID" --reference-chain "$GAIA_CHAIN_ID" --trust-threshold 1/3 > "$TEMP_LOG_2" 2>&1 -CREATE_CLIENT_EXIT_CODE_2=$? - -# Read the output -CLIENT_OUTPUT_2=$(cat "$TEMP_LOG_2") -CLIENT_GAIA_ON_GM=$(echo "$CLIENT_OUTPUT_2" | grep -o '07-tendermint-[0-9]*' | tail -1) - -# Clean up temp file -rm -f "$TEMP_LOG_2" -set -e - -echo "๐Ÿ“„ Full client creation output:" -echo "$CLIENT_OUTPUT_2" -echo "๐Ÿ“Š Exit code: $CREATE_CLIENT_EXIT_CODE_2" - -if [[ $CREATE_CLIENT_EXIT_CODE_2 -eq 0 && -n "$CLIENT_GAIA_ON_GM" ]]; then - echo "โœ… Successfully created client for Gaia on GM: $CLIENT_GAIA_ON_GM" -else - echo "โŒ Failed to create client for Gaia on GM" - echo "๐Ÿ” Troubleshooting information:" - echo " - Host chain: $GM_CHAIN_ID (should be running and accessible)" - echo " - Reference chain: $GAIA_CHAIN_ID (should be producing blocks)" - echo " - GM chain RPC: $GM_RPC" - echo " - Gaia chain RPC: $GAIA_RPC" - echo " - Check if both chains have recent blocks and are synced" -fi - -# Verify we have both clients -echo "๐Ÿ” Verifying client creation results..." -if [[ -z "$CLIENT_GM_ON_GAIA" ]]; then - echo "โŒ Missing client ID for GM on Gaia chain" - echo "๐Ÿ” Raw output from first client creation:" - echo "$CLIENT_OUTPUT_1" -fi - -if [[ -z "$CLIENT_GAIA_ON_GM" ]]; then - echo "โŒ Missing client ID for Gaia on GM chain" - echo "๐Ÿ” Raw output from second client creation:" - echo "$CLIENT_OUTPUT_2" -fi - -if [[ -z "$CLIENT_GM_ON_GAIA" || -z "$CLIENT_GAIA_ON_GM" ]]; then - echo "โŒ Failed to create IBC clients. Cannot proceed with connection setup." - echo "๐Ÿ› ๏ธ Possible issues:" - echo " 1. Chains are not running or not accessible" - echo " 2. Chains are not producing blocks" - echo " 3. Hermes configuration is incorrect" - echo " 4. Network connectivity issues between chains" - echo " 5. Trust threshold or other IBC parameters are invalid" - echo "๐Ÿ“ Check the debug logs above for specific error messages" - exit 1 -fi - -echo "โœ… Both IBC clients created successfully:" -echo " - GM on Gaia: $CLIENT_GM_ON_GAIA" -echo " - Gaia on GM: $CLIENT_GAIA_ON_GM" - -# Create connection -echo "๐Ÿ”— Creating IBC connection..." -echo " Using clients: GM->$CLIENT_GAIA_ON_GM, Gaia->$CLIENT_GM_ON_GAIA" -echo " Command: RUST_LOG=debug hermes create connection --a-chain $GM_CHAIN_ID --a-client $CLIENT_GAIA_ON_GM --b-client $CLIENT_GM_ON_GAIA" - -set +e -# Create temporary file for connection output -TEMP_LOG_3=$(mktemp) -RUST_LOG=debug hermes create connection --a-chain "$GM_CHAIN_ID" --a-client "$CLIENT_GAIA_ON_GM" --b-client "$CLIENT_GM_ON_GAIA" > "$TEMP_LOG_3" 2>&1 -CONNECTION_EXIT_CODE=$? -CONNECTION_OUTPUT=$(cat "$TEMP_LOG_3") -CONNECTION_ID=$(echo "$CONNECTION_OUTPUT" | grep -o 'connection-[0-9]*' | tail -1) -rm -f "$TEMP_LOG_3" -set -e - -echo "๐Ÿ“„ Full connection creation output:" -echo "$CONNECTION_OUTPUT" -echo "๐Ÿ“Š Exit code: $CONNECTION_EXIT_CODE" - -if [[ $CONNECTION_EXIT_CODE -eq 0 && -n "$CONNECTION_ID" ]]; then - echo "โœ… Successfully created connection: $CONNECTION_ID" -else - echo "โŒ Failed to create connection" - echo "๐Ÿ” Connection troubleshooting:" - echo " - Verify both clients exist and are active" - echo " - Check that both chains are still running" - echo " - Ensure clients haven't expired" -fi - -if [[ -z "$CONNECTION_ID" ]]; then - echo "โŒ Failed to create IBC connection. Cannot proceed with channel setup." - echo "๐Ÿ“ Raw connection output analysis:" - echo "$CONNECTION_OUTPUT" - exit 1 -fi - -# Create transfer channel -echo "๐Ÿ”— Creating transfer channel..." -echo " Using connection: $CONNECTION_ID" -echo " Command: RUST_LOG=debug hermes create channel --a-chain $GM_CHAIN_ID --a-connection $CONNECTION_ID --a-port transfer --b-port transfer" - -set +e -# Create temporary file for channel output -TEMP_LOG_4=$(mktemp) -RUST_LOG=debug hermes create channel --a-chain "$GM_CHAIN_ID" --a-connection "$CONNECTION_ID" --a-port "transfer" --b-port "transfer" > "$TEMP_LOG_4" 2>&1 -CHANNEL_EXIT_CODE=$? -CHANNEL_OUTPUT=$(cat "$TEMP_LOG_4") -CHANNEL_GM=$(echo "$CHANNEL_OUTPUT" | grep -o 'channel-[0-9]*' | head -1) -CHANNEL_GAIA=$(echo "$CHANNEL_OUTPUT" | grep -o 'channel-[0-9]*' | tail -1) -rm -f "$TEMP_LOG_4" -set -e - -echo "๐Ÿ“„ Full channel creation output:" -echo "$CHANNEL_OUTPUT" -echo "๐Ÿ“Š Exit code: $CHANNEL_EXIT_CODE" - -if [[ $CHANNEL_EXIT_CODE -eq 0 && -n "$CHANNEL_GM" && -n "$CHANNEL_GAIA" ]]; then - echo "โœ… Successfully created transfer channel: GM=$CHANNEL_GM, Gaia=$CHANNEL_GAIA" -else - echo "โŒ Failed to create transfer channel" - echo "๐Ÿ” Channel troubleshooting:" - echo " - Verify connection $CONNECTION_ID exists and is active" - echo " - Check that transfer modules are enabled on both chains" - echo " - Ensure both chains support ICS-20 token transfers" -fi - -# Save connection details for test script -cat > /tmp/ibc-connection-info << EOF -CLIENT_GM_ON_GAIA=$CLIENT_GM_ON_GAIA -CLIENT_GAIA_ON_GM=$CLIENT_GAIA_ON_GM -CONNECTION_ID=$CONNECTION_ID -CHANNEL_GM=$CHANNEL_GM -CHANNEL_GAIA=$CHANNEL_GAIA -EOF - -echo "๐ŸŽ‰ IBC setup completed successfully!" -echo "" -echo "๐Ÿ“Š Connection Details:" -echo " GM Chain: $GM_CHAIN_ID ($GM_RPC)" -echo " Gaia Chain: $GAIA_CHAIN_ID ($GAIA_RPC)" -echo " Connection: $CONNECTION_ID" -echo " GM Channel: $CHANNEL_GM" -echo " Gaia Channel: $CHANNEL_GAIA" -echo "" diff --git a/.github/integration-tests/scripts/test-transfers.sh b/.github/integration-tests/scripts/test-transfers.sh deleted file mode 100755 index 3f342a36..00000000 --- a/.github/integration-tests/scripts/test-transfers.sh +++ /dev/null @@ -1,221 +0,0 @@ -#!/bin/bash -set -euo pipefail - -echo "๐Ÿ’ธ Testing IBC transfers..." -echo "" - -# Configuration -GM_CHAIN_ID="gm" -GAIA_CHAIN_ID="gaia-local" -GM_RPC="${GM_RPC:-http://gm-chain:26757}" -GAIA_RPC="${GAIA_RPC:-http://gaia-chain:26657}" -GM_HOME="/tmp/gm-test-home" -GAIA_HOME="/tmp/gaia-test-home" - -# Relayer mnemonic (same as used in setup-ibc.sh) -RELAYER_MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" - -# Load connection info -if [[ ! -f /tmp/ibc-connection-info ]]; then - echo "โŒ IBC connection info not found. Run setup-ibc.sh first." - exit 1 -fi - -source /tmp/ibc-connection-info - -echo "๐Ÿ“‹ Using IBC channels:" -echo " GM Channel: $CHANNEL_GM" -echo " Gaia Channel: $CHANNEL_GAIA" -echo "" - -# Setup test homes and keyrings -echo "๐Ÿ”ง Setting up test environment..." -mkdir -p "$GM_HOME" "$GAIA_HOME" - -# Initialize keyring for GM chain -echo "$RELAYER_MNEMONIC" | gmd keys add relayer --keyring-backend test --recover --home "$GM_HOME" >/dev/null 2>&1 || true - -# Initialize keyring for Gaia chain - using 'validator' key like in your script -echo "$RELAYER_MNEMONIC" | gaiad keys add validator --keyring-backend test --recover --home "$GAIA_HOME" >/dev/null 2>&1 || true - -# Get addresses using binaries -GM_RELAYER_ADDR=$(gmd keys show relayer -a --keyring-backend test --home "$GM_HOME") -GAIA_VALIDATOR_ADDR=$(gaiad keys show validator -a --keyring-backend test --home "$GAIA_HOME") - -echo "๐Ÿ“‹ Test addresses:" -echo " GM Relayer: $GM_RELAYER_ADDR" -echo " Gaia Validator: $GAIA_VALIDATOR_ADDR" -echo "" - -# Function to get all balances -get_all_balances() { - local chain="$1" - local address="$2" - - case "$chain" in - "gm") - gmd query bank balances "$address" --node "$GM_RPC" --home "$GM_HOME" --output json 2>/dev/null | jq -r '.balances[]? | .denom + ": " + .amount' || echo "No balances" - ;; - "gaia") - gaiad query bank balances "$address" --chain-id "$GAIA_CHAIN_ID" --node "$GAIA_RPC" --home "$GAIA_HOME" --output json 2>/dev/null | jq -r '.balances[]? | .denom + ": " + .amount' || echo "No balances" - ;; - esac -} - -# Check initial balances -echo "๐Ÿ” Checking initial balances..." -echo "GM relayer balances:" -get_all_balances "gm" "$GM_RELAYER_ADDR" | sed 's/^/ /' - -echo "" -echo "Gaia validator balances:" -get_all_balances "gaia" "$GAIA_VALIDATOR_ADDR" | sed 's/^/ /' -echo "" - -# Test 1: Transfer from GM to Gaia -echo "๐Ÿ’ธ Test 1: Transferring 1000stake from GM to Gaia..." -echo " Executing real IBC transfer..." - -gmd tx ibc-transfer transfer transfer "$CHANNEL_GM" "$GAIA_VALIDATOR_ADDR" 1000stake \ - --from relayer \ - --chain-id "$GM_CHAIN_ID" \ - --keyring-backend test \ - --home "$GM_HOME" \ - --fees 500stake \ - --node "$GM_RPC" \ - --output json \ - -y - -if [[ $? -eq 0 ]]; then - echo "โœ… GM to Gaia transfer submitted successfully" -else - echo "โŒ GM to Gaia transfer failed" -fi - -# Test 2: Transfer from Gaia to GM -echo "" -echo "๐Ÿ’ธ Test 2: Transferring 1000stake from Gaia to GM..." -echo " Executing real IBC transfer..." - -gaiad tx ibc-transfer transfer transfer "$CHANNEL_GAIA" "$GM_RELAYER_ADDR" 1000stake \ - --from validator \ - --chain-id "$GAIA_CHAIN_ID" \ - --keyring-backend test \ - --home "$GAIA_HOME" \ - --fees 200000stake \ - --node "$GAIA_RPC" \ - --output json \ - -y - -if [[ $? -eq 0 ]]; then - echo "โœ… Gaia to GM transfer submitted successfully" -else - echo "โŒ Gaia to GM transfer failed" -fi - -echo "" -echo "โณ Waiting for transfers to be relayed..." - -# Wait until BOTH chains show IBC tokens or timeout -MAX_RELAY_WAIT="${MAX_RELAY_WAIT:-300}" -WAITED=0 -INTERVAL=5 -while true; do - # Recompute IBC token counts on each chain - GM_IBC_TOKENS=$(gmd query bank balances "$GM_RELAYER_ADDR" --node "$GM_RPC" --home "$GM_HOME" --output json 2>/dev/null | jq -r '.balances[]? | select(.denom | startswith("ibc/")) | .denom + ": " + .amount' | wc -l | tr -d ' ') - GAIA_IBC_TOKENS=$(gaiad query bank balances "$GAIA_VALIDATOR_ADDR" --chain-id "$GAIA_CHAIN_ID" --node "$GAIA_RPC" --home "$GAIA_HOME" --output json 2>/dev/null | jq -r '.balances[]? | select(.denom | startswith("ibc/")) | .denom + ": " + .amount' | wc -l | tr -d ' ') - - if [[ ${GM_IBC_TOKENS:-0} -gt 0 && ${GAIA_IBC_TOKENS:-0} -gt 0 ]]; then - echo "โœ… Both chains show IBC tokens (GM: ${GM_IBC_TOKENS}, Gaia: ${GAIA_IBC_TOKENS})" - break - fi - - if [[ $WAITED -ge $MAX_RELAY_WAIT ]]; then - echo "โš ๏ธ Transfers not fully relayed after ${MAX_RELAY_WAIT}s (GM ibc tokens: ${GM_IBC_TOKENS:-0}, Gaia ibc tokens: ${GAIA_IBC_TOKENS:-0})" - break - fi - - sleep "$INTERVAL" - WAITED=$((WAITED+INTERVAL)) - echo " ...waiting (${WAITED}/${MAX_RELAY_WAIT}s) | GM ibc: ${GM_IBC_TOKENS:-0}, Gaia ibc: ${GAIA_IBC_TOKENS:-0}" -done - -# Check final balances -echo "" -echo "๐Ÿ” Checking final balances after transfer..." -echo "GM relayer balances:" -get_all_balances "gm" "$GM_RELAYER_ADDR" | sed 's/^/ /' - -echo "" -echo "Gaia validator balances:" -get_all_balances "gaia" "$GAIA_VALIDATOR_ADDR" | sed 's/^/ /' - -# Look specifically for IBC tokens (they have ibc/ prefix) -echo "" -echo "๐Ÿ” Checking for IBC tokens..." - -GM_IBC_TOKENS=${GM_IBC_TOKENS:-$(gmd query bank balances "$GM_RELAYER_ADDR" --node "$GM_RPC" --home "$GM_HOME" --output json 2>/dev/null | jq -r '.balances[]? | select(.denom | startswith("ibc/")) | .denom + ": " + .amount' | wc -l | tr -d ' ')} -GAIA_IBC_TOKENS=${GAIA_IBC_TOKENS:-$(gaiad query bank balances "$GAIA_VALIDATOR_ADDR" --chain-id "$GAIA_CHAIN_ID" --node "$GAIA_RPC" --home "$GAIA_HOME" --output json 2>/dev/null | jq -r '.balances[]? | select(.denom | startswith("ibc/")) | .denom + ": " + .amount' | wc -l | tr -d ' ')} - -if [[ ${GM_IBC_TOKENS:-0} -gt 0 ]]; then - echo "โœ… GM chain has IBC tokens:" - gmd query bank balances "$GM_RELAYER_ADDR" --node "$GM_RPC" --home "$GM_HOME" --output json 2>/dev/null | jq -r '.balances[]? | select(.denom | startswith("ibc/")) | " " + .denom + ": " + .amount' -else - echo "โ„น๏ธ GM chain has no IBC tokens yet" -fi - -if [[ ${GAIA_IBC_TOKENS:-0} -gt 0 ]]; then - echo "โœ… Gaia chain has IBC tokens:" - gaiad query bank balances "$GAIA_VALIDATOR_ADDR" --chain-id "$GAIA_CHAIN_ID" --node "$GAIA_RPC" --home "$GAIA_HOME" --output json 2>/dev/null | jq -r '.balances[]? | select(.denom | startswith("ibc/")) | " " + .denom + ": " + .amount' -else - echo "โ„น๏ธ Gaia chain has no IBC tokens yet" -fi - -echo "" - -# Final validation -echo "" -echo "๐Ÿ” Final validation..." - -# Check if chains are still healthy -echo " Checking chain health..." -if ! curl -f -s "$GM_RPC/status" >/dev/null; then - echo "โŒ GM chain is not healthy" - exit 1 -fi - -if ! curl -f -s "$GAIA_RPC/status" >/dev/null; then - echo "โŒ Gaia chain is not healthy" - exit 1 -fi - -echo "โœ… Both chains are healthy" - -# Test if balance queries are working -echo " Testing balance query functionality..." -if get_all_balances "gm" "$GM_RELAYER_ADDR" >/dev/null && get_all_balances "gaia" "$GAIA_VALIDATOR_ADDR" >/dev/null; then - echo "โœ… Balance queries working correctly" -else - echo "โŒ Balance queries failed" - exit 1 -fi - -echo "" - -# Require tokens on BOTH chains to pass -if [[ ${GM_IBC_TOKENS:-0} -eq 0 || ${GAIA_IBC_TOKENS:-0} -eq 0 ]]; then - echo "โŒ IBC transfers incomplete: GM ibc tokens=${GM_IBC_TOKENS:-0}, Gaia ibc tokens=${GAIA_IBC_TOKENS:-0}" - exit 1 -fi - -echo "๐ŸŽ‰ IBC Transfer Tests Completed!" -echo "================================" -echo "" -echo "โœ… Test Summary:" -echo " โœ… Chain connectivity maintained" -echo " โœ… Real IBC transfers executed" -echo " โœ… Balance queries operational" -echo " โœ… IBC channels functional" -echo " โœ… IBC tokens successfully transferred on BOTH chains" -echo "" -echo "๐Ÿš€ Your IBC integration system is fully operational!" diff --git a/.github/integration-tests/scripts/wait-for-attester.sh b/.github/integration-tests/scripts/wait-for-attester.sh deleted file mode 100755 index 55322cf1..00000000 --- a/.github/integration-tests/scripts/wait-for-attester.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash -set -euo pipefail - -GM_RPC="${GM_RPC:-http://gm-chain:26757}" -MAX_ATTEMPTS="${MAX_ATTEMPTS:-60}" -SLEEP_INTERVAL="${SLEEP_INTERVAL:-5}" - -echo "โณ Waiting for attester to be operational..." -echo " GM RPC: $GM_RPC" -echo " Checking for attestation activity..." - -# Function to check if attester is working by looking for attestations -check_attester_activity() { - # Check if there are any attester signatures being submitted - # We'll look for network module queries and attestation activity - - # First, check if the chain has network module endpoints available - if ! curl -f -s "$GM_RPC/status" >/dev/null 2>&1; then - return 1 - fi - - # Get current block height - HEIGHT=$(curl -s "$GM_RPC/status" 2>/dev/null | jq -r '.result.sync_info.latest_block_height // 0' || echo "0") - - if [[ "$HEIGHT" -lt 10 ]]; then - echo " Chain height too low ($HEIGHT), waiting for more blocks..." - return 1 - fi - - # Check if we can query network module (indicates attester setup is ready) - # Try to get epoch information - if this works, the network module is active - local api_url="http://gm-chain:1417" - if curl -f -s "$api_url/evabci/network/v1/params" >/dev/null 2>&1; then - echo " Network module is responsive" - - # Check for any attestation activity in recent blocks - # Look for attestation at a checkpoint height (multiples of 10) - local checkpoint_height=$((HEIGHT - HEIGHT % 10)) - if [[ $checkpoint_height -gt 0 ]]; then - local attestation_result=$(curl -s "$api_url/evabci/network/v1/attestation/$checkpoint_height" 2>/dev/null || echo "") - if [[ -n "$attestation_result" ]] && echo "$attestation_result" | jq -e '.bitmap' >/dev/null 2>&1; then - echo " Found attestation data at height $checkpoint_height" - return 0 - fi - fi - - # If we can query the network module but don't see attestations yet, - # the attester might still be starting up - echo " Network module ready, waiting for attestation activity..." - return 1 - else - echo " Network module not yet available..." - return 1 - fi -} - -for i in $(seq 1 $MAX_ATTEMPTS); do - echo " Attempt $i/$MAX_ATTEMPTS..." - - if check_attester_activity; then - echo "โœ… Attester is operational!" - exit 0 - fi - - if [[ $i -lt $MAX_ATTEMPTS ]]; then - echo " Waiting ${SLEEP_INTERVAL}s before next check..." - sleep $SLEEP_INTERVAL - fi -done - -echo "โŒ Attester did not become operational after $MAX_ATTEMPTS attempts" -echo " This could mean:" -echo " 1. Attester container failed to start" -echo " 2. Attester is not successfully connecting to GM chain" -echo " 3. Attester is not producing valid attestations" -echo " 4. Network module is not properly configured" -echo "" -echo "๐Ÿ” Debug information:" -echo " GM RPC: $GM_RPC" - -# Try to get some debug info -HEIGHT=$(curl -s "$GM_RPC/status" 2>/dev/null | jq -r '.result.sync_info.latest_block_height // "unknown"' || echo "unknown") -echo " Current chain height: $HEIGHT" - -# Check if network module params are available -api_url="http://gm-chain:1417" -if curl -f -s "$api_url/evabci/network/v1/params" >/dev/null 2>&1; then - echo " โœ… Network module is accessible" - - # Try to get epoch info - params=$(curl -s "$api_url/evabci/network/v1/params" 2>/dev/null || echo "{}") - epoch_length=$(echo "$params" | jq -r '.params.epoch_length // "unknown"' 2>/dev/null || echo "unknown") - sign_mode=$(echo "$params" | jq -r '.params.sign_mode // "unknown"' 2>/dev/null || echo "unknown") - - echo " Epoch length: $epoch_length" - echo " Sign mode: $sign_mode" -else - echo " โŒ Network module is not accessible" -fi - -exit 1 \ No newline at end of file diff --git a/.github/integration-tests/scripts/wait-for-chain.sh b/.github/integration-tests/scripts/wait-for-chain.sh deleted file mode 100755 index b02c4581..00000000 --- a/.github/integration-tests/scripts/wait-for-chain.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -set -euo pipefail - -NODE_URL="${1:-http://localhost:26757}" -API_URL="${2:-http://localhost:1417}" -MAX_ATTEMPTS="${MAX_ATTEMPTS:-30}" -SLEEP_INTERVAL="${SLEEP_INTERVAL:-2}" - -echo "โณ Waiting for chain to be ready..." -echo " Node RPC: $NODE_URL" -echo " API: $API_URL" - -for i in $(seq 1 $MAX_ATTEMPTS); do - echo " Attempt $i/$MAX_ATTEMPTS..." - - # Check if RPC is accessible and chain is producing blocks - if curl -f -s "$NODE_URL/status" >/dev/null 2>&1; then - # Get current block height - use /block endpoint for Rollkit/ev-abci compatibility - HEIGHT=$(curl -s "$NODE_URL/block" | jq -r '.result.block.header.height // 0' 2>/dev/null || echo "0") - - if [[ "$HEIGHT" -gt 0 ]]; then - echo " Chain is producing blocks (height: $HEIGHT)" - echo "โœ… Chain is ready!" - echo " Block height: $HEIGHT" - exit 0 - else - echo " Chain accessible but not producing blocks yet..." - fi - else - echo " Chain not yet accessible..." - fi - - if [[ $i -lt $MAX_ATTEMPTS ]]; then - sleep $SLEEP_INTERVAL - fi -done - -echo "โŒ Chain is not ready after $MAX_ATTEMPTS attempts" -echo " RPC URL: $NODE_URL" -echo " API URL: $API_URL" -echo " Consider increasing MAX_ATTEMPTS or checking chain service" -exit 1 \ No newline at end of file diff --git a/.github/integration-tests/scripts/wait-for-da.sh b/.github/integration-tests/scripts/wait-for-da.sh deleted file mode 100755 index 0b0ed8b3..00000000 --- a/.github/integration-tests/scripts/wait-for-da.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -set -euo pipefail - -DA_URL="${DA_URL:-http://local-da:7980}" -MAX_ATTEMPTS="${MAX_ATTEMPTS:-30}" -SLEEP_INTERVAL="${SLEEP_INTERVAL:-2}" - -echo "โณ Waiting for local-da to be available at $DA_URL..." - -for i in $(seq 1 $MAX_ATTEMPTS); do - echo " Attempt $i/$MAX_ATTEMPTS..." - - if nc -z local-da 7980 >/dev/null 2>&1; then - echo "โœ… local-da is ready!" - exit 0 - fi - - if [[ $i -lt $MAX_ATTEMPTS ]]; then - echo " Not ready, waiting ${SLEEP_INTERVAL}s..." - sleep $SLEEP_INTERVAL - fi -done - -echo "โŒ local-da is not available after $MAX_ATTEMPTS attempts" -echo " URL: $DA_URL" -echo " Consider increasing MAX_ATTEMPTS or checking local-da service" -exit 1 \ No newline at end of file diff --git a/.github/workflows/attester-mode-integration-test.yml b/.github/workflows/attester-mode-integration-test.yml index 2b706411..e1bd77b9 100644 --- a/.github/workflows/attester-mode-integration-test.yml +++ b/.github/workflows/attester-mode-integration-test.yml @@ -14,7 +14,7 @@ jobs: timeout-minutes: 30 env: DO_NOT_TRACK: true - EVNODE_VERSION: "v1.0.0-beta.2.0.20250917144924-05372840f308" + EVNODE_VERSION: "v1.0.0-beta.4" EVNODE_DA_VERSION: "v1.0.0-beta.1" IGNITE_VERSION: "v29.3.1" IGNITE_EVOLVE_APP_VERSION: "main" @@ -25,17 +25,18 @@ jobs: with: fetch-depth: 0 - - name: Run integration tests (compose orchestrator) + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Build attester Docker images + run: make build-attester-docker-images + + - name: Run attester integration test + working-directory: tests/integration env: + GOTOOLCHAIN: auto VERBOSE: "true" run: | - set -euo pipefail - bash .github/integration-tests/run-integration-tests.sh --timeout 900 - - - name: Upload integration logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: integration-logs - path: .github/integration-tests/logs/ - if-no-files-found: warn + go test -v -run 'TestDockerIntegrationTestSuite/TestAttesterSystem' -count=1 diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index b028a66f..5f2a2df4 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -16,8 +16,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 env: - EVNODE_VERSION: "v1.0.0-beta.2.0.20250917144924-05372840f308" - IGNITE_VERSION: "v29.3.1" + EVNODE_VERSION: "v1.0.0-beta.4" + IGNITE_VERSION: "v29.4.0" IGNITE_EVOLVE_APP_VERSION: "main" # use tagged when apps has tagged (blocked on things) EVOLVE_IMAGE_REPO: "evolve-gm" EVOLVE_IMAGE_TAG: "latest" @@ -48,7 +48,7 @@ jobs: - name: Run Liveness Test run: | cd tests/integration - go test -v -run TestLivenessWithCelestiaDA -timeout 30m + go test -v -run TestDockerIntegrationTestSuite/TestLivenessWithCelestiaDA -timeout 30m env: EVOLVE_IMAGE_REPO: ${{ env.EVOLVE_IMAGE_REPO }} EVOLVE_IMAGE_TAG: ${{ env.EVOLVE_IMAGE_TAG }} @@ -59,8 +59,8 @@ jobs: timeout-minutes: 30 env: DO_NOT_TRACK: true - EVNODE_VERSION: "v1.0.0-beta.2.0.20250917144924-05372840f308" - IGNITE_VERSION: "v29.3.1" + EVNODE_VERSION: "v1.0.0-beta.4" + IGNITE_VERSION: "v29.4.0" IGNITE_EVOLVE_APP_VERSION: "main" # use tagged when apps has tagged (blocked on things) outputs: carol_mnemonic: ${{ steps.save_mnemonic.outputs.carol_mnemonic }} @@ -266,7 +266,7 @@ jobs: GMD_HOME: ${{ needs.liveness.outputs.gmd_home }} HERMES_VERSION: "v1.13.1" GAIA_VERSION: "v25.1.0" - EVNODE_VERSION: "v1.0.0-beta.2.0.20250917144924-05372840f308" + EVNODE_VERSION: "v1.0.0-beta.4" EVNODE_DA_VERSION: "v1.0.0-beta.1" steps: - name: Set up Go diff --git a/.github/workflows/migration_test.yml b/.github/workflows/migration_test.yml index 1fd0ff22..2181132c 100644 --- a/.github/workflows/migration_test.yml +++ b/.github/workflows/migration_test.yml @@ -13,8 +13,8 @@ jobs: timeout-minutes: 45 env: DO_NOT_TRACK: true - EVNODE_VERSION: "v1.0.0-beta.2.0.20250917144924-05372840f308" - IGNITE_VERSION: "v29.3.1" + EVNODE_VERSION: "v1.0.0-beta.4" + IGNITE_VERSION: "v29.4.0" IGNITE_EVOLVE_APP_VERSION: "main" # use tagged when apps has tagged (blocked on things) steps: - uses: actions/checkout@v5 diff --git a/Dockerfile b/Dockerfile index 2d26ffcb..0775edf9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN apk add --no-cache \ bash # Set environment variables -ENV EVNODE_VERSION=v1.0.0-beta.2.0.20250917144924-05372840f308 +ENV EVNODE_VERSION=v1.0.0-beta.4 ENV IGNITE_VERSION=v29.3.1 ENV IGNITE_EVOLVE_APP_VERSION=main diff --git a/Makefile b/Makefile index 568d54fe..e6530d8e 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,10 @@ pkgs := $(shell go list ./...) run := . count := 1 +IGNITE_VERSION ?= v29.3.1 +IGNITE_EVOLVE_APP_VERSION ?= main +EVNODE_VERSION ?= v1.0.0-beta.4 + ## help: Show this help message help: Makefile @echo " Choose a command run in "$(PROJECTNAME)":" @@ -77,3 +81,22 @@ proto-gen: @rm -r modules/github.com .PHONY: proto-gen + + +## build-attester-docker-images: Build Docker images for the GM chain and attester integration tests +build-attester-docker-images: + @echo "--> Building GM integration Docker image" + @docker build \ + -f tests/integration/docker/Dockerfile.gm \ + --build-arg IGNITE_VERSION=$(IGNITE_VERSION) \ + --build-arg IGNITE_EVOLVE_APP_VERSION=$(IGNITE_EVOLVE_APP_VERSION) \ + --build-arg EVNODE_VERSION=$(EVNODE_VERSION) \ + -t evabci/gm:local \ + . + @echo "--> Building attester integration Docker image" + @docker build \ + -f tests/integration/docker/Dockerfile.attester \ + -t evabci/attester:local \ + . + +.PHONY: build-attester-docker-images diff --git a/attester/go.mod b/attester/go.mod index 8b9c23e7..a8e1660e 100644 --- a/attester/go.mod +++ b/attester/go.mod @@ -6,7 +6,6 @@ toolchain go1.24.6 replace ( github.com/evstack/ev-abci => ../../../ev-abci - // use local ev-node github.com/evstack/ev-node => ../../../ev-node ) diff --git a/attester/main.go b/attester/main.go index 5caf51c6..b7f26999 100644 --- a/attester/main.go +++ b/attester/main.go @@ -26,13 +26,17 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/std" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module/testutil" "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/gogoproto/proto" "github.com/spf13/cobra" @@ -47,6 +51,7 @@ const ( flagHome = "home" flagVerbose = "verbose" flagMnemonic = "mnemonic" + flagPrivKeyArmor = "priv-key-armor" flagBech32AccountPrefix = "bech32-account-prefix" flagBech32AccountPubkey = "bech32-account-pubkey" flagBech32ValidatorPrefix = "bech32-validator-prefix" @@ -61,6 +66,7 @@ type Config struct { Home string Verbose bool Mnemonic string + PrivKeyArmor string Bech32AccountPrefix string Bech32AccountPubkey string Bech32ValidatorPrefix string @@ -84,13 +90,14 @@ func main() { rootCmd.Flags().String(flagHome, "", "Directory for config and data") rootCmd.Flags().Bool(flagVerbose, false, "Enable verbose output") rootCmd.Flags().String(flagMnemonic, "", "Mnemonic for the private key") + rootCmd.Flags().String(flagPrivKeyArmor, "", "ASCII armored private key (alternative to mnemonic)") rootCmd.Flags().String(flagBech32AccountPrefix, "gm", "Bech32 prefix for account addresses") rootCmd.Flags().String(flagBech32AccountPubkey, "gmpub", "Bech32 prefix for account public keys") rootCmd.Flags().String(flagBech32ValidatorPrefix, "gmvaloper", "Bech32 prefix for validator addresses") rootCmd.Flags().String(flagBech32ValidatorPubkey, "gmvaloperpub", "Bech32 prefix for validator public keys") _ = rootCmd.MarkFlagRequired(flagChainID) - _ = rootCmd.MarkFlagRequired(flagMnemonic) + // Note: Either mnemonic or priv-key-armor is required, checked at runtime // Execute if err := rootCmd.Execute(); err != nil { @@ -131,6 +138,11 @@ func ParseFlags(cmd *cobra.Command) (*Config, error) { return nil, err } + privKeyArmor, err := cmd.Flags().GetString(flagPrivKeyArmor) + if err != nil { + return nil, err + } + bech32AccountPrefix, err := cmd.Flags().GetString(flagBech32AccountPrefix) if err != nil { return nil, err @@ -158,6 +170,7 @@ func ParseFlags(cmd *cobra.Command) (*Config, error) { Home: home, Verbose: verbose, Mnemonic: mnemonic, + PrivKeyArmor: privKeyArmor, Bech32AccountPrefix: bech32AccountPrefix, Bech32AccountPubkey: bech32AccountPubkey, Bech32ValidatorPrefix: bech32ValidatorPrefix, @@ -187,9 +200,20 @@ func runAttester(cmd *cobra.Command, _ []string) error { fmt.Printf(" Validator pubkey: %s\n", config.Bech32ValidatorPubkey) } - operatorPrivKey, err := privateKeyFromMnemonic(config.Mnemonic) - if err != nil { - return fmt.Errorf("failed to create private key from mnemonic: %w", err) + // Get private key from either mnemonic or armored key + var operatorPrivKey *secp256k1.PrivKey + if config.PrivKeyArmor != "" { + operatorPrivKey, err = privateKeyFromArmor(config.PrivKeyArmor) + if err != nil { + return fmt.Errorf("failed to create private key from armored key: %w", err) + } + } else if config.Mnemonic != "" { + operatorPrivKey, err = privateKeyFromMnemonic(config.Mnemonic) + if err != nil { + return fmt.Errorf("failed to create private key from mnemonic: %w", err) + } + } else { + return fmt.Errorf("either --mnemonic or --priv-key-armor must be provided") } privKeyPath := filepath.Join(config.Home, "config", "priv_validator_key.json") @@ -768,6 +792,44 @@ func privateKeyFromMnemonic(mnemonic string) (*secp256k1.PrivKey, error) { return &secp256k1.PrivKey{Key: derivedPriv}, nil } +// privateKeyFromArmor imports a private key from ASCII armored format +func privateKeyFromArmor(armoredKey string) (*secp256k1.PrivKey, error) { + // Create a test encoding config with the necessary codec + testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}) + kr := keyring.NewInMemory(testEncCfg.Codec) + + // Import the armored key into the temporary keyring + err := kr.ImportPrivKey("temp", armoredKey, "") + if err != nil { + return nil, fmt.Errorf("failed to import armored private key: %w", err) + } + + // Get the key record + keyRecord, err := kr.Key("temp") + if err != nil { + return nil, fmt.Errorf("failed to get imported key: %w", err) + } + + // Get the local record from the keyring record + localRecord := keyRecord.GetLocal() + if localRecord == nil { + return nil, fmt.Errorf("failed to get local record: record is nil") + } + + // Get the private key from the local record + if localRecord.PrivKey == nil { + return nil, fmt.Errorf("failed to get private key: key is nil") + } + + // Get the cached private key + privKey, ok := localRecord.PrivKey.GetCachedValue().(*secp256k1.PrivKey) + if !ok { + return nil, fmt.Errorf("failed to cast private key to secp256k1.PrivKey") + } + + return privKey, nil +} + // submitAttestation creates and submits an attestation for a block using PayloadProvider func submitAttestation( ctx context.Context, diff --git a/go.mod b/go.mod index 91a0dded..0f5caae0 100644 --- a/go.mod +++ b/go.mod @@ -19,17 +19,17 @@ require ( cosmossdk.io/log v1.6.1 cosmossdk.io/math v1.5.3 cosmossdk.io/store v1.1.2 - github.com/celestiaorg/go-header v0.7.1 + github.com/celestiaorg/go-header v0.7.2 github.com/cometbft/cometbft v0.38.17 github.com/cometbft/cometbft-db v0.14.1 github.com/cosmos/cosmos-db v1.1.3 github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.50.14 github.com/cosmos/gogoproto v1.7.0 - github.com/evstack/ev-node v1.0.0-beta.2.0.20250917144924-05372840f308 - github.com/evstack/ev-node/core v1.0.0-beta.1.0.20250917144924-05372840f308 - github.com/evstack/ev-node/da v0.0.0-20250917144924-05372840f308 - github.com/evstack/ev-node/sequencers/single v0.0.0-20250917144924-05372840f308 + github.com/evstack/ev-node v1.0.0-beta.4 + github.com/evstack/ev-node/core v1.0.0-beta.3 + github.com/evstack/ev-node/da v1.0.0-beta.3 + github.com/evstack/ev-node/sequencers/single v1.0.0-beta.2 github.com/go-kit/kit v0.13.0 github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 @@ -86,6 +86,7 @@ require ( github.com/bytedance/sonic v1.14.0 // indirect github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/celestiaorg/go-libp2p-messenger v0.2.2 // indirect + github.com/celestiaorg/go-square/v2 v2.3.3 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.5 // indirect diff --git a/go.sum b/go.sum index 6741bea8..e7e805a8 100644 --- a/go.sum +++ b/go.sum @@ -139,10 +139,12 @@ github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFos github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/celestiaorg/go-datastore v0.0.0-20250801131506-48a63ae531e4 h1:udw77BU45zmvTV7798FhR1wHFmsFpu4GnA5mubtMcR0= github.com/celestiaorg/go-datastore v0.0.0-20250801131506-48a63ae531e4/go.mod h1:W+pI1NsUsz3tcsAACMtfC+IZdnQTnC/7VfPoJBQuts0= -github.com/celestiaorg/go-header v0.7.1 h1:XG0fQykSjKsCtWl9sY5jZXG12D4Xe59bjklWZ2sWip0= -github.com/celestiaorg/go-header v0.7.1/go.mod h1:eX9iTSPthVEAlEDLux40ZT/olXPGhpxHd+mEzJeDhd0= +github.com/celestiaorg/go-header v0.7.2 h1:Jw01iBKnodfsILzynDCU3C11xurpoBt5SI9lgyKHJc0= +github.com/celestiaorg/go-header v0.7.2/go.mod h1:eX9iTSPthVEAlEDLux40ZT/olXPGhpxHd+mEzJeDhd0= github.com/celestiaorg/go-libp2p-messenger v0.2.2 h1:osoUfqjss7vWTIZrrDSy953RjQz+ps/vBFE7bychLEc= github.com/celestiaorg/go-libp2p-messenger v0.2.2/go.mod h1:oTCRV5TfdO7V/k6nkx7QjQzGrWuJbupv+0o1cgnY2i4= +github.com/celestiaorg/go-square/v2 v2.3.3 h1:vhu6Lt39km19Q/Jk4nS3r2cuWJq6jFg+/1+iG8YGftY= +github.com/celestiaorg/go-square/v2 v2.3.3/go.mod h1:vY5RRv+qRmEVjPF6dAdr0dyLwKmTTDHHffENPQw8pUA= github.com/celestiaorg/utils v0.1.0 h1:WsP3O8jF7jKRgLNFmlDCwdThwOFMFxg0MnqhkLFVxPo= github.com/celestiaorg/utils v0.1.0/go.mod h1:vQTh7MHnvpIeCQZ2/Ph+w7K1R2UerDheZbgJEJD2hSU= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= @@ -292,14 +294,14 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evstack/ev-node v1.0.0-beta.2.0.20250917144924-05372840f308 h1:eNdun4l/cZ+mF6a7mDDAmrEaEhmtdUM3QB2DywAEJiA= -github.com/evstack/ev-node v1.0.0-beta.2.0.20250917144924-05372840f308/go.mod h1:K/B6ItITtx4zzSh36/dyanr3hior8GZOOOd3CfjSYKg= -github.com/evstack/ev-node/core v1.0.0-beta.1.0.20250917144924-05372840f308 h1:p0Ic2+7dw5gEN/NDkwrdXlxV5KiocGs2/gP6HIkmDS4= -github.com/evstack/ev-node/core v1.0.0-beta.1.0.20250917144924-05372840f308/go.mod h1:n2w/LhYQTPsi48m6lMj16YiIqsaQw6gxwjyJvR+B3sY= -github.com/evstack/ev-node/da v0.0.0-20250917144924-05372840f308 h1:LChUDf4JYXRcvj2KMsjxHB3yWFvthxwHyP+LYp43C24= -github.com/evstack/ev-node/da v0.0.0-20250917144924-05372840f308/go.mod h1:9rah0LnlscekwXVSD0jrB5hU5Q0UHl4xqZ9hTWzgyHw= -github.com/evstack/ev-node/sequencers/single v0.0.0-20250917144924-05372840f308 h1:Zmrwmbzi/7EIiZgz7dFrjLZws8L45rDGU1hUqZcAhaU= -github.com/evstack/ev-node/sequencers/single v0.0.0-20250917144924-05372840f308/go.mod h1:Q8nNm/QtiScFSgHPgohPxu/mUKsb1QK3voAAwoulhAw= +github.com/evstack/ev-node v1.0.0-beta.4 h1:tOW+M7+ZbGnlP+op01OKbFlIuNv1KxrtCQhg+HsLyZc= +github.com/evstack/ev-node v1.0.0-beta.4/go.mod h1:ooOFcaglIwVsmrL+5Y318F4ZCyTogXA8Fh6L3T+jwNM= +github.com/evstack/ev-node/core v1.0.0-beta.3 h1:01K2Ygm3puX4m2OBxvg/HDxu+he54jeNv+KDmpgujFc= +github.com/evstack/ev-node/core v1.0.0-beta.3/go.mod h1:n2w/LhYQTPsi48m6lMj16YiIqsaQw6gxwjyJvR+B3sY= +github.com/evstack/ev-node/da v1.0.0-beta.3 h1:jeJ2MOixjr5TnIiLSCtrim/Ulb/r4QIDSrovFO/MiGU= +github.com/evstack/ev-node/da v1.0.0-beta.3/go.mod h1:O3Lbx4/WFN0DIUOHdTihmyRnGmQwVXdswH19RW/KyG4= +github.com/evstack/ev-node/sequencers/single v1.0.0-beta.2 h1:UlQd3WL2p6bBtGMYYok8PUGxUEQJ74rf2XHlCqJF7Z8= +github.com/evstack/ev-node/sequencers/single v1.0.0-beta.2/go.mod h1:df5iQYNItmXgJlEJnW+nRlfWzsgwOtRwIEsh2c2wwu4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= diff --git a/server/start.go b/server/start.go index ad84b948..90c1a554 100644 --- a/server/start.go +++ b/server/start.go @@ -329,6 +329,10 @@ func setupNodeAndExecutor( return nil, nil, cleanupFn, err } + if err := rollkitcfg.Validate(); err != nil { + return nil, nil, cleanupFn, fmt.Errorf("failed to validate ev-node config: %w", err) + } + // only load signer if rollkit.node.aggregator == true var signer signer.Signer if rollkitcfg.Node.Aggregator { diff --git a/tests/integration/attester_test.go b/tests/integration/attester_test.go new file mode 100644 index 00000000..ec62f943 --- /dev/null +++ b/tests/integration/attester_test.go @@ -0,0 +1,122 @@ +package integration_test + +import ( + "context" + "fmt" + + "github.com/celestiaorg/tastora/framework/docker/container" + dockerclient "github.com/moby/moby/client" + "go.uber.org/zap" +) + +const ( + attesterDefaultImage = "evabci/attester" + attesterDefaultVersion = "local" + attesterDefaultUIDGID = "2000:2000" + attesterHomeDir = "/home/attester" +) + +var AttesterNode = AttesterNodeType{} + +type AttesterNodeType struct{} + +func (attesterNodeType AttesterNodeType) String() string { + return "attester" +} + +type Attester struct { + *container.Node +} + +func NewAttester(ctx context.Context, dockerClient *dockerclient.Client, testName, networkID string, index int, logger *zap.Logger) (*Attester, error) { + image := container.Image{ + Repository: attesterDefaultImage, + Version: attesterDefaultVersion, + UIDGID: attesterDefaultUIDGID, + } + + if logger == nil { + logger = zap.NewNop() + } + + node := container.NewNode( + networkID, + dockerClient, + testName, + image, + attesterHomeDir, + index, + AttesterNode, + logger, + ) + + attester := &Attester{ + Node: node, + } + + lifecycle := container.NewLifecycle(logger, dockerClient, attester.Name()) + attester.SetContainerLifecycle(lifecycle) + + err := attester.CreateAndSetupVolume(ctx, attester.Name()) + if err != nil { + return nil, err + } + + return attester, nil +} + +// Name returns the hostname of the docker container. +func (h *Attester) Name() string { + return fmt.Sprintf("%s-%d-attester", SanitizeContainerName(h.TestName), h.Index) +} + +// AttesterConfig holds configuration for the attester +type AttesterConfig struct { + ChainID string + GMNodeURL string + GMAPIUrl string + PrivKeyArmor string + ValidatorKeyPath string + ValidatorStatePath string +} + +// DefaultAttesterConfig returns a default configuration +func DefaultAttesterConfig() AttesterConfig { + return AttesterConfig{ + ChainID: "gm", + } +} + +func (h *Attester) Start(ctx context.Context, config AttesterConfig) error { + cmd := []string{ + "attester", + "--chain-id", config.ChainID, + "--home", attesterHomeDir, + } + + // Use armored key + cmd = append(cmd, "--priv-key-armor", config.PrivKeyArmor) + + cmd = append(cmd, + "--api-addr", config.GMAPIUrl, + "--node", config.GMNodeURL, + "--bech32-account-prefix", "celestia", + "--bech32-account-pubkey", "celestiapub", + "--bech32-validator-prefix", "celestiavaloper", + "--bech32-validator-pubkey", "celestiavaloperpub", + "--verbose", + ) + + err := h.CreateContainer(ctx, h.TestName, h.NetworkID, h.Image, nil, "", h.Bind(), nil, h.Name(), cmd, nil, []string{}) + if err != nil { + return fmt.Errorf("failed to create attester container: %w", err) + } + + if err := h.StartContainer(ctx); err != nil { + return fmt.Errorf("failed to start attester container: %w", err) + } + + return nil +} + +// Attester inherits WriteFileWithOptions from embedded container.Node. diff --git a/.github/integration-tests/docker/Dockerfile.attester b/tests/integration/docker/Dockerfile.attester similarity index 75% rename from .github/integration-tests/docker/Dockerfile.attester rename to tests/integration/docker/Dockerfile.attester index 32b18776..e6fdd0f1 100644 --- a/.github/integration-tests/docker/Dockerfile.attester +++ b/tests/integration/docker/Dockerfile.attester @@ -26,20 +26,13 @@ FROM alpine:3.18 # Install runtime dependencies RUN apk add --no-cache ca-certificates curl jq bash -# Create attester user -RUN adduser -D -s /bin/bash attester +# Create attester user with stable UID/GID expected by integration tests +RUN addgroup -g 2000 attester \ + && adduser -D -G attester -u 2000 -h /home/attester -s /bin/bash attester # Copy attester binary COPY --from=builder /workspace/attester /usr/local/bin/attester -# Copy attester script -COPY --chown=attester:attester .github/integration-tests/scripts/run-attester.sh /home/attester/run-attester.sh -RUN chmod +x /home/attester/run-attester.sh - -# Copy wait helpers -COPY --chown=attester:attester .github/integration-tests/scripts/wait-for-chain.sh /home/attester/wait-for-chain.sh -RUN chmod +x /home/attester/wait-for-chain.sh - # Switch to attester user USER attester WORKDIR /home/attester @@ -54,6 +47,3 @@ ENV MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon ab # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD pgrep -f attester || exit 1 - -# Run attester -CMD ["./run-attester.sh"] diff --git a/.github/integration-tests/docker/Dockerfile.gm b/tests/integration/docker/Dockerfile.gm similarity index 75% rename from .github/integration-tests/docker/Dockerfile.gm rename to tests/integration/docker/Dockerfile.gm index 279d03c0..724d427a 100644 --- a/.github/integration-tests/docker/Dockerfile.gm +++ b/tests/integration/docker/Dockerfile.gm @@ -20,13 +20,13 @@ WORKDIR /workspace COPY . /workspace/ev-abci # Scaffold GM app and apply evolve plugin -RUN ignite scaffold chain gm --no-module --skip-git --address-prefix gm +RUN ignite scaffold chain gm --no-module --skip-git --address-prefix celestia WORKDIR /workspace/gm RUN ignite app install github.com/ignite/apps/evolve@${IGNITE_EVOLVE_APP_VERSION} RUN ignite evolve add # Inject App wiring for ev-abci network module before building -COPY .github/integration-tests/patches/app-wiring/patch-app-wiring.sh /workspace/patch-app-wiring.sh +COPY tests/integration/docker/patches/app-wiring/patch-app-wiring.sh /workspace/patch-app-wiring.sh RUN chmod +x /workspace/patch-app-wiring.sh && \ echo "===== Running network module patch =====" && \ bash /workspace/patch-app-wiring.sh @@ -61,18 +61,7 @@ RUN useradd -m -s /bin/bash gm && echo "gm ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoe COPY --from=builder /workspace/bin/gmd /usr/local/bin/gmd RUN chmod +x /usr/local/bin/gmd -# Copy Ignite CLI and plugin cache from builder -COPY --from=builder /usr/local/bin/ignite /usr/local/bin/ignite -COPY --from=builder /root/.ignite /home/gm/.ignite -RUN chown -R gm:gm /home/gm/.ignite && chmod +x /usr/local/bin/ignite - -# Copy gm source (for ignite/evolve operations) -COPY --from=builder --chown=gm:gm /workspace/gm /home/gm/gm - -# Copy scripts -COPY --chown=gm:gm .github/integration-tests/scripts/init-gm.sh /home/gm/init-gm.sh -COPY --chown=gm:gm .github/integration-tests/scripts/wait-for-da.sh /home/gm/wait-for-da.sh -RUN chmod +x /home/gm/init-gm.sh /home/gm/wait-for-da.sh +# COPY --from=builder --chown=gm:gm /workspace/gm /home/gm/gm # Switch to gm user USER gm @@ -92,4 +81,4 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD curl -f http://localhost:26757/status || exit 1 # Default command -CMD ["./init-gm.sh"] +CMD ["/usr/local/bin/gmd", "start"] diff --git a/.github/integration-tests/patches/app-wiring/patch-app-wiring.sh b/tests/integration/docker/patches/app-wiring/patch-app-wiring.sh similarity index 100% rename from .github/integration-tests/patches/app-wiring/patch-app-wiring.sh rename to tests/integration/docker/patches/app-wiring/patch-app-wiring.sh diff --git a/tests/integration/gm_gaia_health_test.go b/tests/integration/gm_gaia_health_test.go new file mode 100644 index 00000000..ac20531d --- /dev/null +++ b/tests/integration/gm_gaia_health_test.go @@ -0,0 +1,596 @@ +package integration_test + +import ( + "context" + "encoding/json" + "fmt" + "testing" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/BurntSushi/toml" + "github.com/celestiaorg/tastora/framework/docker/container" + "github.com/celestiaorg/tastora/framework/docker/cosmos" + "github.com/celestiaorg/tastora/framework/docker/ibc" + "github.com/celestiaorg/tastora/framework/docker/ibc/relayer" + "github.com/celestiaorg/tastora/framework/testutil/config" + "github.com/celestiaorg/tastora/framework/testutil/query" + "github.com/celestiaorg/tastora/framework/testutil/sdkacc" + "github.com/celestiaorg/tastora/framework/testutil/wait" + "github.com/celestiaorg/tastora/framework/types" + cometcfg "github.com/cometbft/cometbft/config" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/ibc-go/v8/modules/apps/transfer" + ibctransfer "github.com/cosmos/ibc-go/v8/modules/apps/transfer" + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + "github.com/stretchr/testify/require" +) + +// TestAttesterSystem is an empty test case using the DockerIntegrationTestSuite +func (s *DockerIntegrationTestSuite) TestAttesterSystem() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gmChain := s.getGmChain(ctx) + + // Start GM chain in a goroutine + go func() { + s.T().Log("Starting GM chain...") + err := gmChain.Start(ctx) + if err != nil { + s.T().Errorf("Failed to start GM chain: %v", err) + } + }() + + // Wait for GM chain RPC to be ready + s.T().Log("Waiting for GM chain RPC to be ready...") + var rpcReady bool + for i := 0; i < 30; i++ { // 30 second timeout + node := gmChain.GetNodes()[0] + rpcClient, _ := node.GetRPCClient() + if rpcClient != nil { + // Test if RPC client is actually working by making a simple call + _, err := rpcClient.Status(ctx) + if err == nil { + rpcReady = true + s.T().Log("GM chain RPC is ready") + break + } + } + time.Sleep(1 * time.Second) + } + require.True(s.T(), rpcReady, "GM chain RPC failed to become ready within 30 seconds") + + kr, err := gmChain.GetNodes()[0].GetKeyring() + require.NoError(s.T(), err) + + // List available keys + keys, err := kr.List() + require.NoError(s.T(), err) + s.T().Logf("Available keys in keyring: %d", len(keys)) + + // Log all available keys and find validator key + var validatorKey *keyring.Record + for i, key := range keys { + keyAddr, _ := key.GetAddress() + s.T().Logf("Key %d: Name=%s, Address=%s", i, key.Name, keyAddr.String()) + + if key.Name == "validator" { + validatorKey = key + } + } + + // Extract validator key if found + var validatorArmoredKey string + if validatorKey != nil { + s.T().Logf("Extracting validator key...") + + // Export private key in armor format (no passphrase for test keyring) + armoredPrivKey, err := kr.ExportPrivKeyArmor("validator", "") + require.NoError(s.T(), err, "failed to export validator private key") + + s.T().Logf("Validator private key exported successfully (armor format)") + previewLen := 100 + if len(armoredPrivKey) < previewLen { + previewLen = len(armoredPrivKey) + } + s.T().Logf("Armored key preview: %s...", armoredPrivKey[:previewLen]) + validatorArmoredKey = armoredPrivKey + } else { + s.T().Log("No validator key found in keyring") + } + + attesterConfig, attesterNode := s.getAttester(ctx, gmChain, validatorArmoredKey) + + s.T().Logf("Starting attester node %s", attesterNode.Name()) + err = attesterNode.Start(ctx, attesterConfig) + require.NoError(s.T(), err) + s.T().Log("Attester node started successfully") + + hermes, err := relayer.NewHermes(ctx, s.dockerClient, s.T().Name(), s.networkID, 0, s.logger) + require.NoError(s.T(), err, "failed to create hermes relayer") + + err = hermes.Init(ctx, s.celestiaChain, gmChain) + require.NoError(s.T(), err, "failed to initialize relayer") + + // Switch hermes to pull mode to avoid WebSocket connection issues + err = s.configureHermesForPullMode(ctx, hermes) + require.NoError(s.T(), err, "failed to configure hermes for pull mode") + + connection, channel := setupIBCConnection(s.T(), ctx, s.celestiaChain, gmChain, hermes) + s.T().Logf("Established IBC connection %s and channel %s between Celestia and GM chain", connection.ConnectionID, channel.ChannelID) + + // Test IBC transfers + s.testIBCTransfers(ctx, s.celestiaChain, gmChain, channel, hermes) +} + +func (s *DockerIntegrationTestSuite) getAttester(ctx context.Context, gmChain *cosmos.Chain, validatorArmoredKey string) (AttesterConfig, *Attester) { + // Create attester configuration + attesterConfig := DefaultAttesterConfig() + + // Set armored key (required) + require.NotEmpty(s.T(), validatorArmoredKey, "validator armored key is required") + attesterConfig.PrivKeyArmor = validatorArmoredKey + + // Get the internal network addresses for the GM chain + gmNodes := gmChain.GetNodes() + require.NotEmpty(s.T(), gmNodes, "no GM chain nodes available") + + gmNode := gmNodes[0] + gmNodeInfo, err := gmNode.GetNetworkInfo(ctx) + require.NoError(s.T(), err) + + privValidatorKeyJSON, err := gmNode.ReadFile(ctx, "config/priv_validator_key.json") + require.NoError(s.T(), err, "unable to read priv_validator_key.json from GM node") + + privValidatorStateJSON, err := gmNode.ReadFile(ctx, "data/priv_validator_state.json") + require.NoError(s.T(), err, "unable to read priv_validator_state.json from GM node") + + // Derive attester account address from armored key + attesterAccAddr, err := deriveAttesterAccountFromArmor(attesterConfig.PrivKeyArmor) + require.NoError(s.T(), err, "failed to derive attester account address from armored key") + + fromAddr, err := sdkacc.AddressFromWallet(gmChain.GetFaucetWallet()) + require.NoError(s.T(), err, "failed to retrieve faucet address") + coins := sdk.NewCoins(sdk.NewCoin(gmChain.Config.Denom, sdkmath.NewInt(5_000_000_000))) + fundingMsg := banktypes.NewMsgSend(fromAddr, attesterAccAddr, coins) + resp, err := gmChain.BroadcastMessages(ctx, gmChain.GetFaucetWallet(), fundingMsg) + require.NoError(s.T(), err, "failed to fund attester account") + require.Zero(s.T(), resp.Code, "funding tx failed: %s", resp.RawLog) + s.T().Logf("funded attester account %s with %s", attesterAccAddr.String(), coins) + + // Use internal addresses for communication within docker network + attesterConfig.GMNodeURL = fmt.Sprintf("http://%s:26657", gmNodeInfo.Internal.Hostname) + attesterConfig.GMAPIUrl = fmt.Sprintf("http://%s:1417", gmNodeInfo.Internal.Hostname) + + // Create and start the attester + attesterNode, err := NewAttester(ctx, s.dockerClient, s.T().Name(), s.networkID, 0, s.logger) + require.NoError(s.T(), err) + require.NoError(s.T(), attesterNode.WriteFile( + ctx, + "config/priv_validator_key.json", + privValidatorKeyJSON, + )) + require.NoError(s.T(), attesterNode.WriteFile( + ctx, + "data/priv_validator_state.json", + privValidatorStateJSON, + )) + + // Verify validator key can be imported (demonstration) + s.T().Log("Setting up attester keyring with validator key...") + + // Create an in-memory keyring for the attester + // Include transfer module so MsgTransfer is registered in the interface registry + testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, ibctransfer.AppModuleBasic{}) + attesterKeyring := keyring.NewInMemory(testEncCfg.Codec) + + // Import the validator key into the attester keyring + err = attesterKeyring.ImportPrivKey("validator", validatorArmoredKey, "") + require.NoError(s.T(), err, "failed to import validator key into attester keyring") + + s.T().Log("Validator key imported successfully into attester keyring") + + // List keys in attester keyring to verify + attesterKeys, err := attesterKeyring.List() + require.NoError(s.T(), err) + s.T().Logf("Attester keyring now has %d keys", len(attesterKeys)) + + for i, key := range attesterKeys { + keyAddr, _ := key.GetAddress() + s.T().Logf("Attester Key %d: Name=%s, Address=%s", i, key.Name, keyAddr.String()) + } + + return attesterConfig, attesterNode +} + +func deriveAttesterAccountFromArmor(armoredKey string) (sdk.AccAddress, error) { + // Create a temporary in-memory keyring for importing + testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}) + kr := keyring.NewInMemory(testEncCfg.Codec) + + // Import the armored key into the temporary keyring + err := kr.ImportPrivKey("temp", armoredKey, "") + if err != nil { + return nil, fmt.Errorf("failed to import armored private key: %w", err) + } + + // Get the key record + keyRecord, err := kr.Key("temp") + if err != nil { + return nil, fmt.Errorf("failed to get imported key: %w", err) + } + + // Get the address from the key record + keyAddr, err := keyRecord.GetAddress() + if err != nil { + return nil, fmt.Errorf("failed to get address from key: %w", err) + } + + return keyAddr, nil +} + +func (s *DockerIntegrationTestSuite) configureHermesForPullMode(ctx context.Context, hermes *relayer.Hermes) error { + s.T().Log("Configuring hermes to use pull mode and increased clock drift...") + + // Read the current config + configBz, err := hermes.ReadFile(ctx, ".hermes/config.toml") + if err != nil { + return fmt.Errorf("failed to read hermes config: %w", err) + } + + // Unmarshal into map + var c map[string]interface{} + if err := toml.Unmarshal(configBz, &c); err != nil { + return fmt.Errorf("failed to unmarshal hermes config: %w", err) + } + + // Update chains to use pull mode and increase clock drift + chains, ok := c["chains"].([]map[string]interface{}) + if !ok { + return fmt.Errorf("chains not found in config or not in expected format") + } + + for i := range chains { + // Update event_source to pull mode with tighter interval + chains[i]["event_source"] = map[string]interface{}{ + "mode": "pull", + "interval": "200ms", + } + + // Update clock_drift to handle timing differences between chains + chains[i]["clock_drift"] = "60s" + } + + // Remarshal into bytes + updatedConfigBz, err := toml.Marshal(c) + if err != nil { + return fmt.Errorf("failed to marshal updated hermes config: %w", err) + } + + // Write the updated config + err = hermes.WriteFile(ctx, ".hermes/config.toml", updatedConfigBz) + if err != nil { + return fmt.Errorf("failed to write updated hermes config: %w", err) + } + + s.T().Log("Successfully configured hermes to use pull mode with 60s clock drift tolerance") + return nil +} + +func (s *DockerIntegrationTestSuite) getGmChain(ctx context.Context) *cosmos.Chain { + daAddress, authToken, daStartHeight, err := s.getDANetworkParams(ctx) + require.NoError(s.T(), err) + + s.T().Log("Creating GM chain connected to DA network...") + sdk.GetConfig().SetBech32PrefixForAccount("celestia", "celestiapub") + gmImg := container.NewImage("evabci/gm", "local", "1000:1000") + testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, transfer.AppModuleBasic{}) + gmChain, err := cosmos.NewChainBuilder(s.T()). + WithEncodingConfig(&testEncCfg). + WithDockerClient(s.dockerClient). + WithDockerNetworkID(s.networkID). + WithImage(gmImg). + WithDenom("stake"). + WithBech32Prefix("celestia"). + WithChainID("gm"). + WithBinaryName("gmd"). + WithGasPrices(fmt.Sprintf("0.001%s", "stake")). + WithAdditionalStartArgs( + "--evnode.node.aggregator", + "--evnode.signer.passphrase", "12345678", + "--evnode.da.address", daAddress, + "--evnode.da.gas_price", "0.000001", + "--evnode.da.auth_token", authToken, + "--evnode.rpc.address", "0.0.0.0:7331", + "--evnode.da.namespace", "ev-header", + "--evnode.da.data_namespace", "ev-data", + "--evnode.da.start_height", daStartHeight, + "--evnode.p2p.listen_address", "/ip4/0.0.0.0/tcp/36656", + "--rpc.laddr", "tcp://0.0.0.0:26657", + "--evnode.attester-mode", "true", + "--grpc.address", "0.0.0.0:9090", + "--api.enable", + "--minimum-gas-prices", "0.001stake", + "--log_level", "*:info", + ). + WithPostInit(func(ctx context.Context, node *cosmos.ChainNode) error { + // 1) Ensure ABCI responses and tx events are retained and indexed for Hermes + if err := config.Modify(ctx, node, "config/config.toml", func(cfg *cometcfg.Config) { + cfg.Storage.DiscardABCIResponses = false + // Enable key-value tx indexer so Hermes can query IBC packet events + cfg.TxIndex.Indexer = "kv" + // Increase RPC BroadcastTxCommit timeout to accommodate CI slowness + if cfg.RPC != nil { + cfg.RPC.TimeoutBroadcastTxCommit = 120000000000 // 120s in nanoseconds + } + }); err != nil { + return err + } + // 2) Ensure app-level index-events include IBC packet events + appToml, err := node.ReadFile(ctx, "config/app.toml") + if err != nil { + return err + } + var appCfg map[string]interface{} + if err := toml.Unmarshal(appToml, &appCfg); err != nil { + return err + } + appCfg["index-events"] = []string{ + "message.action", + "send_packet", + "recv_packet", + "write_acknowledgement", + "acknowledge_packet", + "timeout_packet", + } + updated, err := toml.Marshal(appCfg) + if err != nil { + return err + } + return node.WriteFile(ctx, "config/app.toml", updated) + }). + WithNode(cosmos.NewChainNodeConfigBuilder(). + WithPostInit(AddSingleSequencer). + Build()). + Build(ctx) + require.NoError(s.T(), err) + + return gmChain +} + +// AddSingleSequencer modifies the genesis file to add a single sequencer with specified power and public key. +// Reads the genesis file from the node, updates the validators with the sequencer info, and writes the updated file back. +func AddSingleSequencer(ctx context.Context, node *cosmos.ChainNode) error { + genesisBz, err := node.ReadFile(ctx, "config/genesis.json") + if err != nil { + return fmt.Errorf("failed to read genesis.json: %w", err) + } + + pubKey, err := getPubKey(ctx, node) + if err != nil { + return fmt.Errorf("failed to get pubkey: %w", err) + } + + var genDoc map[string]interface{} + if err := json.Unmarshal(genesisBz, &genDoc); err != nil { + return fmt.Errorf("failed to parse genesis.json: %w", err) + } + + consensus, ok := genDoc["consensus"].(map[string]interface{}) + if !ok { + return fmt.Errorf("genesis.json does not contain a valid 'consensus' object") + } + consensus["validators"] = []map[string]interface{}{ + { + "name": "Ev Node Sequencer", + "address": pubKey.Address(), + "pub_key": map[string]interface{}{ + "type": "tendermint/PubKeyEd25519", + "value": pubKey.Bytes(), + }, + "power": "5", // NOTE: because of default validator wallet amount in tastora the power will be computed as 5. + }, + } + + updatedGenesis, err := json.MarshalIndent(genDoc, "", " ") + if err != nil { + return fmt.Errorf("failed to marshal genesis: %w", err) + } + return node.WriteFile(ctx, "config/genesis.json", updatedGenesis) +} + +// setupIBCConnection establishes a complete IBC connection and channel +func setupIBCConnection(t *testing.T, ctx context.Context, chainA, chainB types.Chain, hermes *relayer.Hermes) (ibc.Connection, ibc.Channel) { + // create clients + err := hermes.CreateClients(ctx, chainA, chainB) + require.NoError(t, err) + + // create connections + connection, err := hermes.CreateConnections(ctx, chainA, chainB) + require.NoError(t, err) + require.NotEmpty(t, connection.ConnectionID, "Connection ID should not be empty") + + // give chains a moment to persist connection state and client updates + _ = wait.ForBlocks(ctx, 2, chainA, chainB) + + // Create an ICS20 channel for token transfers + channelOpts := ibc.CreateChannelOptions{ + SourcePortName: "transfer", + DestPortName: "transfer", + Order: ibc.OrderUnordered, + Version: "ics20-1", + } + + channel, err := hermes.CreateChannel(ctx, chainA, connection, channelOpts) + require.NoError(t, err) + require.NotNil(t, channel) + require.NotEmpty(t, channel.ChannelID, "Channel ID should not be empty") + + t.Logf("Created IBC connection: %s <-> %s", connection.ConnectionID, connection.CounterpartyID) + t.Logf("Created IBC channel: %s <-> %s", channel.ChannelID, channel.CounterpartyID) + + return connection, channel +} + +// testIBCTransfers performs bidirectional IBC transfers and validates they succeed +func (s *DockerIntegrationTestSuite) testIBCTransfers(ctx context.Context, celestiaChain, gmChain *cosmos.Chain, channel ibc.Channel, hermes *relayer.Hermes) { + // Transfer amount + transferAmount := sdkmath.NewInt(1_000_000) + + // Get wallets for both chains + celestiaWallet := celestiaChain.GetFaucetWallet() + gmWallet := gmChain.GetFaucetWallet() + + celestiaAddr, err := sdkacc.AddressFromWallet(celestiaWallet) + require.NoError(s.T(), err) + gmAddr, err := sdkacc.AddressFromWallet(gmWallet) + require.NoError(s.T(), err) + + s.T().Logf("Celestia wallet address: %s", celestiaAddr.String()) + s.T().Logf("GM wallet address: %s", gmAddr.String()) + + initialCelestiaNativeBalance := s.getBalance(ctx, celestiaChain, celestiaAddr, "utia") + s.T().Logf("Initial Celestia native balance: %s utia", initialCelestiaNativeBalance.String()) + + // Calculate IBC denom for GM chain receiving Celestia tokens + celestiaToGMIBCDenom := s.calculateIBCDenom(channel.CounterpartyPort, channel.CounterpartyID, "utia") + + // Start Hermes relayer + s.T().Log("Starting Hermes relayer...") + err = hermes.Start(ctx) + require.NoError(s.T(), err) + + // Allow Hermes to sync initial heights before sending packets + _ = wait.ForBlocks(ctx, 2, celestiaChain, gmChain) + + // Test 1: Transfer from Celestia to GM chain + s.T().Log("=== Testing transfer from Celestia to GM chain ===") + + // Get initial balance + initialGMBalance := s.getBalance(ctx, gmChain, gmAddr, celestiaToGMIBCDenom) + s.T().Logf("Initial GM IBC balance: %s %s", initialGMBalance.String(), celestiaToGMIBCDenom) + + // Perform transfer + transferMsg := transfertypes.NewMsgTransfer( + channel.PortID, + channel.ChannelID, + sdk.NewCoin("utia", transferAmount), + celestiaWallet.GetFormattedAddress(), + gmAddr.String(), + clienttypes.ZeroHeight(), + uint64(time.Now().Add(time.Hour).UnixNano()), + "", + ) + + // Use a longer per-tx timeout to avoid 60s default aborts on busy or lagging nodes + ctxTx, cancelTx := context.WithTimeout(ctx, 2*time.Minute) + defer cancelTx() + resp, err := celestiaChain.BroadcastMessages(ctxTx, celestiaWallet, transferMsg) + require.NoError(s.T(), err) + require.Equal(s.T(), uint32(0), resp.Code, "IBC transfer failed: %s", resp.RawLog) + + s.T().Logf("IBC transfer broadcast successful. TX hash: %s", resp.TxHash) + + // Wait until GM balance reflects the transfer (poll with timeout) + s.T().Log("Waiting for GM balance to update...") + require.NoError(s.T(), s.waitForBalanceIncrease(ctx, gmChain, gmAddr, celestiaToGMIBCDenom, initialGMBalance, transferAmount, 2*time.Minute)) + + // Check final balance + finalGMBalance := s.getBalance(ctx, gmChain, gmAddr, celestiaToGMIBCDenom) + s.T().Logf("Final GM IBC balance: %s %s", finalGMBalance.String(), celestiaToGMIBCDenom) + + // Verify transfer succeeded + expectedBalance := initialGMBalance.Add(transferAmount) + require.True(s.T(), finalGMBalance.Equal(expectedBalance), + "GM balance mismatch: expected %s, got %s", expectedBalance.String(), finalGMBalance.String()) + + postInboundCelestiaNativeBalance := s.getBalance(ctx, celestiaChain, celestiaAddr, "utia") + s.T().Logf("Celestia native balance after outbound transfer: %s utia", postInboundCelestiaNativeBalance.String()) + + // Test 2: Return Celestia-originated tokens back to Celestia + s.T().Log("=== Returning Celestia-originated tokens to Celestia ===") + + returnTransferMsg := transfertypes.NewMsgTransfer( + channel.CounterpartyPort, + channel.CounterpartyID, + sdk.NewCoin(celestiaToGMIBCDenom, transferAmount), + gmWallet.GetFormattedAddress(), + celestiaAddr.String(), + clienttypes.ZeroHeight(), + uint64(time.Now().Add(time.Hour).UnixNano()), + "", + ) + + ctxTxReturn, cancelTxReturn := context.WithTimeout(ctx, 2*time.Minute) + defer cancelTxReturn() + resp, err = gmChain.BroadcastMessages(ctxTxReturn, gmWallet, returnTransferMsg) + require.NoError(s.T(), err) + require.Equal(s.T(), uint32(0), resp.Code, "Return IBC transfer failed: %s", resp.RawLog) + + s.T().Logf("Return IBC transfer broadcast successful. TX hash: %s", resp.TxHash) + + s.T().Log("Waiting for Celestia native balance to restore...") + require.NoError(s.T(), s.waitForBalanceIncrease(ctx, celestiaChain, celestiaAddr, "utia", postInboundCelestiaNativeBalance, transferAmount, 2*time.Minute)) + + restoredGMBalance := s.getBalance(ctx, gmChain, gmAddr, celestiaToGMIBCDenom) + s.T().Logf("GM IBC balance after returning tokens: %s %s", restoredGMBalance.String(), celestiaToGMIBCDenom) + require.True(s.T(), restoredGMBalance.Equal(initialGMBalance), + "GM balance mismatch after returning tokens: expected %s, got %s", initialGMBalance.String(), restoredGMBalance.String()) + + finalCelestiaNativeBalance := s.getBalance(ctx, celestiaChain, celestiaAddr, "utia") + s.T().Logf("Final Celestia native balance: %s utia", finalCelestiaNativeBalance.String()) + expectedReturnBalance := postInboundCelestiaNativeBalance.Add(transferAmount) + require.True(s.T(), finalCelestiaNativeBalance.Equal(expectedReturnBalance), + "Celestia native balance mismatch after return: expected %s, got %s", + expectedReturnBalance.String(), finalCelestiaNativeBalance.String()) + + s.T().Log("=== IBC Transfer Tests Completed Successfully ===") +} + +// waitForBalanceIncrease polls the balance until it increases by expectedIncrease or timeout expires. +func (s *DockerIntegrationTestSuite) waitForBalanceIncrease(ctx context.Context, chain *cosmos.Chain, address sdk.AccAddress, denom string, initial sdkmath.Int, expectedIncrease sdkmath.Int, timeout time.Duration) error { + deadline := time.Now().Add(timeout) + target := initial.Add(expectedIncrease) + for { + current := s.getBalance(ctx, chain, address, denom) + if current.GTE(target) { + return nil + } + if time.Now().After(deadline) { + return fmt.Errorf("balance did not reach target within %s: got %s, want %s (%s)", timeout, current.String(), target.String(), denom) + } + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(1 * time.Second): + } + } +} + +// getBalance queries the balance of an address for a specific denom +func (s *DockerIntegrationTestSuite) getBalance(ctx context.Context, chain *cosmos.Chain, address sdk.AccAddress, denom string) sdkmath.Int { + node := chain.GetNode() + amount, err := query.Balance(ctx, node.GrpcConn, address.String(), denom) + if err != nil { + s.T().Logf("Failed to query balance for %s denom %s: %v", address.String(), denom, err) + return sdkmath.ZeroInt() + } + return amount +} + +// calculateIBCDenom calculates the IBC denomination for a token transferred over IBC +func (s *DockerIntegrationTestSuite) calculateIBCDenom(portID, channelID, baseDenom string) string { + prefixedDenom := transfertypes.GetPrefixedDenom( + portID, + channelID, + baseDenom, + ) + return transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom() +} diff --git a/tests/integration/go.mod b/tests/integration/go.mod index 0482f659..55b77b96 100644 --- a/tests/integration/go.mod +++ b/tests/integration/go.mod @@ -1,67 +1,92 @@ module github.com/evstack/ev-abci/tests/integration -go 1.24.1 +go 1.24.6 require ( - github.com/celestiaorg/go-square/v2 v2.2.0 - github.com/celestiaorg/tastora v0.1.3-0.20250718071213-c9bb942b02b5 + github.com/celestiaorg/tastora v0.3.0 + github.com/cosmos/ibc-go/v8 v8.7.0 github.com/moby/moby v27.5.1+incompatible - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 go.uber.org/zap v1.27.0 ) require ( + github.com/libp2p/go-libp2p v0.43.0 + github.com/multiformats/go-multihash v0.2.3 +) + +require ( + cosmossdk.io/x/upgrade v0.1.4 // indirect + github.com/aws/aws-sdk-go-v2 v1.38.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect + github.com/aws/aws-sdk-go-v2/config v1.31.2 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.18.6 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 // indirect + github.com/aws/smithy-go v1.22.5 // indirect + github.com/celestiaorg/go-square/v2 v2.2.0 // indirect + github.com/celestiaorg/nmt v0.24.1 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cosmos/ibc-go/modules/capability v1.0.1 // indirect github.com/golang/mock v1.6.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect - github.com/grafana/pyroscope-go v1.2.0 // indirect + github.com/grafana/pyroscope-go v1.2.4 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/ipfs/go-cid v0.5.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/lib/pq v1.10.9 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect github.com/minio/highwayhash v1.0.3 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.16.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.9.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 // indirect + go.opentelemetry.io/otel/sdk v1.37.0 // indirect + lukechampine.com/blake3 v1.4.1 // indirect ) require ( cosmossdk.io/api v0.7.6 // indirect cosmossdk.io/collections v0.4.0 // indirect; indirect\ - cosmossdk.io/core v0.11.0 // indirect + cosmossdk.io/core v0.11.1 // indirect cosmossdk.io/depinject v1.1.0 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.4.0 cosmossdk.io/store v1.1.1 // indirect cosmossdk.io/x/tx v0.13.7 // indirect - filippo.io/edwards25519 v1.0.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect - github.com/BurntSushi/toml v1.5.0 // indirect + github.com/BurntSushi/toml v1.5.0 github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect - github.com/aws/aws-sdk-go-v2 v1.36.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.8 // indirect - github.com/aws/aws-sdk-go-v2/config v1.29.6 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.59 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.32 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.6.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.13 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.76.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 // indirect - github.com/aws/smithy-go v1.22.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect - github.com/celestiaorg/nmt v0.23.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/errors v1.11.3 // indirect @@ -76,16 +101,16 @@ require ( github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect - github.com/cosmos/cosmos-sdk v0.0.0-00010101000000-000000000000 + github.com/cosmos/cosmos-sdk v0.50.14 github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogoproto v1.7.0 // indirect github.com/cosmos/iavl v1.2.2 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.15.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v4 v4.2.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect @@ -108,15 +133,15 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.4 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/glog v1.2.5 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect @@ -134,7 +159,7 @@ require ( github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.18.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/linxGnu/grocksdb v1.8.14 // indirect @@ -155,12 +180,12 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.5 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/client_golang v1.23.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.65.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/cors v1.11.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -177,32 +202,27 @@ require ( github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect github.com/zondax/hid v0.9.2 // indirect - github.com/zondax/ledger-go v0.14.3 // indirect + github.com/zondax/ledger-go v1.0.0 // indirect go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/otel v1.37.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.38.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.40.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.23.0 // indirect - google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect - google.golang.org/grpc v1.72.2 - google.golang.org/protobuf v1.36.6 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect + google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect + google.golang.org/grpc v1.75.0 + google.golang.org/protobuf v1.36.9 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect @@ -213,10 +233,12 @@ require ( replace ( cosmossdk.io/x/upgrade => github.com/celestiaorg/cosmos-sdk/x/upgrade v0.1.0 + //github.com/celestiaorg/tastora => ../../../tastora + github.com/cometbft/cometbft => github.com/celestiaorg/celestia-core v1.56.1-tm-v0.38.17 github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v1.29.4-sdk-v0.50.14 - github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 + // goleveldb: canonical version github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // celestia-core(v0.34.x): used for multiplexing abci v1 requests diff --git a/tests/integration/go.sum b/tests/integration/go.sum index 1e83ed08..e7535e26 100644 --- a/tests/integration/go.sum +++ b/tests/integration/go.sum @@ -1,11 +1,26 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/auth v0.6.0 h1:5x+d6b5zdezZ7gmLWD1m/xNjnaQ2YDhmIz/HH3doy1g= +cloud.google.com/go/auth v0.6.0/go.mod h1:b4acV+jLQDyjwm4OXHYjNvRi4jvGBzHWJRtJcy+2P4g= +cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= +cloud.google.com/go/compute v1.27.1 h1:0WbBLIPNANheCRZ4h8QhgzjN53KMutbiVBOLtPiVzBU= +cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= +cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= +cloud.google.com/go/iam v1.1.9 h1:oSkYLVtVme29uGYrOcKcvJRht7cHJpYD09GM9JaR0TE= +cloud.google.com/go/iam v1.1.9/go.mod h1:Nt1eDWNYH9nGQg3d/mY7U1hvfGmsaG9o/kLGoLoLXjQ= +cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RBx0= +cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.3 h1:+TTuH0DwQYsUq2JFAl3fDZzKq5gQG7nt3dAattkjFDU= +cosmossdk.io/client/v2 v2.0.0-beta.3/go.mod h1:CZcL41HpJPOOayTCO28j8weNBQprG+SRiKX39votypo= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= -cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= +cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= +cosmossdk.io/core v0.11.1/go.mod h1:OJzxcdC+RPrgGF8NJZR2uoQr56tc7gfBKhiKeDO7hH0= cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E= cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,11 +31,17 @@ cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ= cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk= cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y= cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM= +cosmossdk.io/x/circuit v0.1.1 h1:KPJCnLChWrxD4jLwUiuQaf5mFD/1m7Omyo7oooefBVQ= +cosmossdk.io/x/circuit v0.1.1/go.mod h1:B6f/urRuQH8gjt4eLIXfZJucrbreuYrKh5CSjaOxr+Q= +cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= +cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= +cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= +cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= cosmossdk.io/x/tx v0.13.7 h1:8WSk6B/OHJLYjiZeMKhq7DK7lHDMyK0UfDbBMxVmeOI= cosmossdk.io/x/tx v0.13.7/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= -filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= @@ -36,8 +57,8 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -63,55 +84,59 @@ github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIc github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ= +github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/aws/aws-sdk-go-v2 v1.36.1 h1:iTDl5U6oAhkNPba0e1t1hrwAo02ZMqbrGq4k5JBWM5E= -github.com/aws/aws-sdk-go-v2 v1.36.1/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.8 h1:zAxi9p3wsZMIaVCdoiQp2uZ9k1LsZvmAnoTBeZPXom0= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.8/go.mod h1:3XkePX5dSaxveLAYY7nsbsZZrKxCyEuE5pM4ziFxyGg= -github.com/aws/aws-sdk-go-v2/config v1.29.6 h1:fqgqEKK5HaZVWLQoLiC9Q+xDlSp+1LYidp6ybGE2OGg= -github.com/aws/aws-sdk-go-v2/config v1.29.6/go.mod h1:Ft+WLODzDQmCTHDvqAH1JfC2xxbZ0MxpZAcJqmE1LTQ= -github.com/aws/aws-sdk-go-v2/credentials v1.17.59 h1:9btwmrt//Q6JcSdgJOLI98sdr5p7tssS9yAsGe8aKP4= -github.com/aws/aws-sdk-go-v2/credentials v1.17.59/go.mod h1:NM8fM6ovI3zak23UISdWidyZuI1ghNe2xjzUZAyT+08= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 h1:KwsodFKVQTlI5EyhRSugALzsV6mG/SGrdjlMXSZSdso= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28/go.mod h1:EY3APf9MzygVhKuPXAc5H+MkGb8k/DOSQjWS0LgkKqI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 h1:BjUcr3X3K0wZPGFg2bxOWW3VPN8rkE3/61zhP+IHviA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32/go.mod h1:80+OGC/bgzzFFTUmcuwD0lb4YutwQeKLFpmt6hoWapU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 h1:m1GeXHVMJsRsUAqG6HjZWx9dj7F5TR+cF1bjyfYyBd4= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32/go.mod h1:IitoQxGfaKdVLNg0hD8/DXmAqNy0H4K2H2Sf91ti8sI= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.32 h1:OIHj/nAhVzIXGzbAE+4XmZ8FPvro3THr6NlqErJc3wY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.32/go.mod h1:LiBEsDo34OJXqdDlRGsilhlIiXR7DL+6Cx2f4p1EgzI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.6.0 h1:kT2WeWcFySdYpPgyqJMSUE7781Qucjtn6wBvrgm9P+M= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.6.0/go.mod h1:WYH1ABybY7JK9TITPnk6ZlP7gQB8psI4c9qDmMsnLSA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 h1:SYVGSFQHlchIcy6e7x12bsrxClCXSP5et8cqVhL8cuw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13/go.mod h1:kizuDaLX37bG5WZaoxGPQR/LNFXpxp0vsUnqfkWXfNE= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.13 h1:OBsrtam3rk8NfBEq7OLOMm5HtQ9Yyw32X4UQMya/wjw= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.13/go.mod h1:3U4gFA5pmoCOja7aq4nSaIAGbaOHv2Yl2ug018cmC+Q= -github.com/aws/aws-sdk-go-v2/service/s3 v1.76.1 h1:d4ZG8mELlLeUWFBMCqPtRfEP3J6aQgg/KTC9jLSlkMs= -github.com/aws/aws-sdk-go-v2/service/s3 v1.76.1/go.mod h1:uZoEIR6PzGOZEjgAZE4hfYfsqK2zOHhq68JLKEvvXj4= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 h1:/eE3DogBjYlvlbhd2ssWyeuovWunHLxfgw3s/OJa4GQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.15/go.mod h1:2PCJYpi7EKeA5SkStAmZlF6fi0uUABuhtF8ILHjGc3Y= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 h1:M/zwXiL2iXUrHputuXgmO94TVNmcenPHxgLXLutodKE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14/go.mod h1:RVwIw3y/IqxC2YEXSIkAzRDdEU1iRabDPaYjpGCbCGQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 h1:TzeR06UCMUq+KA3bDkujxK1GVGy+G8qQN/QVYzGLkQE= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.14/go.mod h1:dspXf/oYWGWo6DEvj98wpaTeqt5+DMidZD0A9BYTizc= -github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= -github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/aws-sdk-go-v2 v1.38.1 h1:j7sc33amE74Rz0M/PoCpsZQ6OunLqys/m5antM0J+Z8= +github.com/aws/aws-sdk-go-v2 v1.38.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= +github.com/aws/aws-sdk-go-v2/config v1.31.2 h1:NOaSZpVGEH2Np/c1toSeW0jooNl+9ALmsUTZ8YvkJR0= +github.com/aws/aws-sdk-go-v2/config v1.31.2/go.mod h1:17ft42Yb2lF6OigqSYiDAiUcX4RIkEMY6XxEMJsrAes= +github.com/aws/aws-sdk-go-v2/credentials v1.18.6 h1:AmmvNEYrru7sYNJnp3pf57lGbiarX4T9qU/6AZ9SucU= +github.com/aws/aws-sdk-go-v2/credentials v1.18.6/go.mod h1:/jdQkh1iVPa01xndfECInp1v1Wnp70v3K4MvtlLGVEc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4 h1:lpdMwTzmuDLkgW7086jE94HweHCqG+uOJwHf3LZs7T0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4/go.mod h1:9xzb8/SV62W6gHQGC/8rrvgNXU6ZoYM3sAIJCIrXJxY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 h1:IdCLsiiIj5YJ3AFevsewURCPV+YWUlOW8JiPhoAy8vg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4/go.mod h1:l4bdfCD7XyyZA9BolKBo1eLqgaJxl0/x91PL4Yqe0ao= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 h1:j7vjtr1YIssWQOMeOWRbh3z8g2oY/xPjnZH2gLY4sGw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4/go.mod h1:yDmJgqOiH4EA8Hndnv4KwAo8jCGTSnM5ASG1nBI+toA= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4 h1:BE/MNQ86yzTINrfxPPFS86QCBNQeLKY2A0KhDh47+wI= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4/go.mod h1:SPBBhkJxjcrzJBc+qY85e83MQ2q3qdra8fghhkkyrJg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4 h1:Beh9oVgtQnBgR4sKKzkUBRQpf1GnL4wt0l4s8h2VCJ0= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4/go.mod h1:b17At0o8inygF+c6FOD3rNyYZufPw62o9XJbSfQPgbo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 h1:ueB2Te0NacDMnaC+68za9jLwkjzxGWm0KB5HTUHjLTI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4/go.mod h1:nLEfLnVMmLvyIG58/6gsSA03F1voKGaCfHV7+lR8S7s= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4 h1:HVSeukL40rHclNcUqVcBwE1YoZhOkoLeBfhUqR3tjIU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4/go.mod h1:DnbBOv4FlIXHj2/xmrUQYtawRFC9L9ZmQPz+DBc6X5I= +github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1 h1:2n6Pd67eJwAb/5KCX62/8RTU0aFAAW7V5XIGSghiHrw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1/go.mod h1:w5PC+6GHLkvMJKasYGVloB3TduOtROEMqm15HSuIbw4= +github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 h1:ve9dYBB8CfJGTFqcQ3ZLAAb/KXWgYlgu/2R2TZL2Ko0= +github.com/aws/aws-sdk-go-v2/service/sso v1.28.2/go.mod h1:n9bTZFZcBa9hGGqVz3i/a6+NG0zmZgtkB9qVVFDqPA8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2 h1:pd9G9HQaM6UZAZh19pYOkpKSQkyQQ9ftnl/LttQOcGI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2/go.mod h1:eknndR9rU8UpE/OmFpqU78V1EcXPKFTTm5l/buZYgvM= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 h1:iV1Ko4Em/lkJIsoKyGfc0nQySi+v0Udxr6Igq+y9JZc= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.0/go.mod h1:bEPcjW7IbolPfK67G1nilqWyoxYMSPrDiIQ3RdIdKgo= +github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= +github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 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/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= github.com/bits-and-blooms/bitset v1.8.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/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= +github.com/btcsuite/btcd/btcec/v2 v2.3.5/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= @@ -121,23 +146,34 @@ github.com/celestiaorg/celestia-core v1.56.1-tm-v0.38.17 h1:bbsnn4eyE0UG9benmUId github.com/celestiaorg/celestia-core v1.56.1-tm-v0.38.17/go.mod h1:jDJU+alpN4/MzC5Lz6+IsAYmvy8SrkD+jplk+C3W0Yo= github.com/celestiaorg/cosmos-sdk v1.29.4-sdk-v0.50.14 h1:MBVJBZuJqZLyRgYkF4ONvtv6Ncn0LOB3XVKWqj3VDhQ= github.com/celestiaorg/cosmos-sdk v1.29.4-sdk-v0.50.14/go.mod h1:clLEg7hWK0iJfiO1Vp71tcQ0vGbFzVsEcLxxnRobIZM= +github.com/celestiaorg/cosmos-sdk/x/upgrade v0.1.0 h1:+i3G5mP/kPgFEn83EEXGly29QDin2Gvdt0kgpmw/vTg= +github.com/celestiaorg/cosmos-sdk/x/upgrade v0.1.0/go.mod h1:T4K9O18zQNKNpt4YvTL3lcUt4aKOEU05ZIFWVdQi3Ak= github.com/celestiaorg/go-square/v2 v2.2.0 h1:zJnUxCYc65S8FgUfVpyG/osDcsnjzo/JSXw/Uwn8zp4= github.com/celestiaorg/go-square/v2 v2.2.0/go.mod h1:j8kQUqJLYtcvCQMQV6QjEhUdaF7rBTXF74g8LbkR0Co= -github.com/celestiaorg/nmt v0.23.0 h1:cfYy//hL1HeDSH0ub3CPlJuox5U5xzgg4JGZrw23I/I= -github.com/celestiaorg/nmt v0.23.0/go.mod h1:kYfIjRq5rmA2mJnv41GLWkxn5KyLNPlma3v5Q68rHdI= -github.com/celestiaorg/tastora v0.1.3-0.20250718071213-c9bb942b02b5 h1:AFRtyM6up5dHmIs9jQYFvhYVF2UpxDIwHmIEPljhbSM= -github.com/celestiaorg/tastora v0.1.3-0.20250718071213-c9bb942b02b5/go.mod h1:A/DWauemWmg353BvhWYPCd8XbED12UCUiQsL+1sz9BU= +github.com/celestiaorg/nmt v0.24.1 h1:MhGKqp257eq2EQQKcva1H/BSYFqIt0Trk8/t3IWfWSw= +github.com/celestiaorg/nmt v0.24.1/go.mod h1:IhLnJDgCdP70crZFpgihFmU6G+PGeXN37tnMRm+/4iU= +github.com/celestiaorg/tastora v0.3.0 h1:ZfwlRXjddTCRzj2+5pNbdr75nwPeEpsLx93Fpo8GxEM= +github.com/celestiaorg/tastora v0.3.0/go.mod h1:28BiTBJ4Yz6K5iT57NwS1NVLJFN/hmZHx9j0CVz4QXM= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= 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/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= @@ -194,10 +230,14 @@ github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fr github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/cosmos/iavl v1.2.2 h1:qHhKW3I70w+04g5KdsdVSHRbFLgt3yY3qTMd4Xa4rC8= github.com/cosmos/iavl v1.2.2/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= +github.com/cosmos/ibc-go/modules/capability v1.0.1 h1:ibwhrpJ3SftEEZRxCRkH0fQZ9svjthrX2+oXdZvzgGI= +github.com/cosmos/ibc-go/modules/capability v1.0.1/go.mod h1:rquyOV262nGJplkumH+/LeYs04P3eV8oB7ZM4Ygqk4E= +github.com/cosmos/ibc-go/v8 v8.7.0 h1:HqhVOkO8bDpClXE81DFQgFjroQcTvtpm0tCS7SQVKVY= +github.com/cosmos/ibc-go/v8 v8.7.0/go.mod h1:G2z+Q6ZQSMcyHI2+BVcJdvfOupb09M2h/tgpXOEdY6k= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= -github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= -github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= +github.com/cosmos/ledger-cosmos-go v0.15.0 h1:xmizkkEX19tyFLVL6PPMQNg21Jc9W9/bpbwxMDdtxXg= +github.com/cosmos/ledger-cosmos-go v0.15.0/go.mod h1:KJqW5U4/MMl8ICPO4WPjIAyC4TfYRnr28d9N9bBUKWc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -208,10 +248,10 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= @@ -254,7 +294,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= @@ -327,13 +366,13 @@ github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6x github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= -github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= @@ -383,26 +422,32 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= -github.com/grafana/pyroscope-go v1.2.0 h1:aILLKjTj8CS8f/24OPMGPewQSYlhmdQMBmol1d3KGj8= -github.com/grafana/pyroscope-go v1.2.0/go.mod h1:2GHr28Nr05bg2pElS+dDsc98f3JTUh2f6Fz1hWXrqwk= +github.com/grafana/pyroscope-go v1.2.4 h1:B22GMXz+O0nWLatxLuaP7o7L9dvP0clLvIpmeEQQM0Q= +github.com/grafana/pyroscope-go v1.2.4/go.mod h1:zzT9QXQAp2Iz2ZdS216UiV8y9uXJYQiGE1q8v1FyhqU= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -413,8 +458,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= @@ -422,6 +467,10 @@ github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0= +github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -435,12 +484,17 @@ github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -472,9 +526,13 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= +github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -493,8 +551,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -512,6 +572,10 @@ github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-libp2p v0.43.0 h1:b2bg2cRNmY4HpLK8VHYQXLX2d3iND95OjodLFymvqXU= +github.com/libp2p/go-libp2p v0.43.0/go.mod h1:IiSqAXDyP2sWH+J2gs43pNmB/y4FOi2XQPbsb+8qvzc= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ= @@ -539,8 +603,12 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= @@ -569,8 +637,24 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.16.0 h1:oGWEVKioVQcdIOBlYM8BH1rZDWOGJSqr9/BKl6zQ4qc= +github.com/multiformats/go-multiaddr v0.16.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.9.1 h1:x/Fuxr7ZuR4jJV4Os5g444F7xC4XmyUaT/FWtE+9Zjo= +github.com/multiformats/go-multicodec v0.9.1/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= 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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -598,8 +682,9 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -652,32 +737,32 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= +github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -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/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -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/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -685,8 +770,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= @@ -717,6 +802,8 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= 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/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 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.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= @@ -750,8 +837,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -771,8 +858,10 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -781,8 +870,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= -github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zondax/ledger-go v1.0.0 h1:BvNoksIyRqyQTW78rIZP9A44WwAminKiomQa7jXp9EI= +github.com/zondax/ledger-go v1.0.0/go.mod h1:HpgkgFh3Jkwi9iYLDATdyRxc8CxqxcywsFj6QerWzvo= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 h1:qxen9oVGzDdIRP6ejyAJc760RwW4SnVDiTYTzwnXuxo= go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5/go.mod h1:eW0HG9/oHQhvRCvb1/pIXW4cOvtDqeQK+XSi3TnwaXY= @@ -794,6 +883,8 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= @@ -801,18 +892,18 @@ go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4= go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= @@ -845,13 +936,13 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4= +golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -866,8 +957,6 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -895,11 +984,13 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -908,8 +999,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -954,6 +1045,7 @@ golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -962,24 +1054,24 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -998,13 +1090,15 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.186.0 h1:n2OPp+PPXX0Axh4GuSsL5QL8xQCTb2oDwyzPnQvqUug= +google.golang.org/api v0.186.0/go.mod h1:hvRbBmgoje49RV3xqVXrmP6w93n6ehGgIVPYrGtBFFc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1019,12 +1113,12 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 h1:6whtk83KtD3FkGrVb2hFXuQ+ZMbCNdakARIn/aHMmG8= +google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094/go.mod h1:Zs4wYw8z1zr6RNF4cwYb31mvN/EGaKAdQjNCF3DW6K4= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 h1:MAKi5q709QWfnkkpNQ0M12hYJ1+e8qYVDyowc4U1XZM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1043,8 +1137,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= -google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1059,8 +1153,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1098,6 +1192,8 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= +lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= diff --git a/tests/integration/liveness_test.go b/tests/integration/liveness_test.go index 5d16c98e..d5f7d6c7 100644 --- a/tests/integration/liveness_test.go +++ b/tests/integration/liveness_test.go @@ -2,225 +2,29 @@ package integration_test import ( "context" - "encoding/hex" - "encoding/json" "fmt" + "github.com/celestiaorg/tastora/framework/docker/container" "os" "testing" - "github.com/celestiaorg/tastora/framework/testutil/sdkacc" - "github.com/celestiaorg/tastora/framework/testutil/wallet" - "github.com/cometbft/cometbft/crypto" - cmtjson "github.com/cometbft/cometbft/libs/json" - cmprivval "github.com/cometbft/cometbft/privval" - "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/bank" - "go.uber.org/zap/zaptest" - "cosmossdk.io/math" + "github.com/celestiaorg/tastora/framework/docker/cosmos" + "github.com/celestiaorg/tastora/framework/testutil/wait" + "github.com/celestiaorg/tastora/framework/testutil/wallet" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - - "github.com/celestiaorg/go-square/v2/share" - "github.com/celestiaorg/tastora/framework/docker" - "github.com/celestiaorg/tastora/framework/docker/container" - "github.com/celestiaorg/tastora/framework/testutil/wait" - "github.com/celestiaorg/tastora/framework/types" - "github.com/moby/moby/client" - "github.com/stretchr/testify/require" ) const ( - denom = "stake" - celestiaAppTag = "v4.0.10" - celestiaNodeTag = "v0.23.5" - celestiaNodeRepo = "ghcr.io/celestiaorg/celestia-node" - celestiaAppRepo = "ghcr.io/celestiaorg/celestia-app" + denom = "stake" ) -// CreateCelestiaChain sets up a Celestia app chain for DA -func CreateCelestiaChain(ctx context.Context, t *testing.T, dockerClient *client.Client, networkID string) (*docker.Chain, error) { - testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}) - celestia, err := docker.NewChainBuilder(t). - WithEncodingConfig(&testEncCfg). - WithDockerClient(dockerClient). - WithDockerNetworkID(networkID). - WithImage(container.NewImage(celestiaAppRepo, celestiaAppTag, "10001:10001")). - WithAdditionalStartArgs( - "--force-no-bbr", - "--grpc.enable", - "--grpc.address", "0.0.0.0:9090", - "--rpc.grpc_laddr=tcp://0.0.0.0:9098", - "--timeout-commit", "1s", - "--minimum-gas-prices", "0.000001utia", - ). - WithNode(docker.NewChainNodeConfigBuilder().Build()). - Build(ctx) - - if err != nil { - return nil, fmt.Errorf("failed to build celestia chain: %w", err) - } - - err = celestia.Start(ctx) - if err != nil { - return nil, fmt.Errorf("failed to start celestia chain: %w", err) - } - - return celestia, nil -} - -// CreateDANetwork sets up the DA network with bridge and full nodes -func CreateDANetwork(ctx context.Context, t *testing.T, dockerClient *client.Client, networkID string, celestiaChain *docker.Chain) (types.DataAvailabilityNetwork, types.DANode, error) { - config := &docker.Config{ - Logger: zaptest.NewLogger(t), - DockerClient: dockerClient, - DockerNetworkID: networkID, - DataAvailabilityNetworkConfig: &docker.DataAvailabilityNetworkConfig{ - Image: container.NewImage(celestiaNodeRepo, celestiaNodeTag, "10001:10001"), - BridgeNodeCount: 1, - }, - } - - provider := docker.NewProvider(*config, t) - daNetwork, err := provider.GetDataAvailabilityNetwork(ctx) - if err != nil { - return nil, nil, fmt.Errorf("failed to get DA network: %w", err) - } - - genesisHash, err := getGenesisHash(ctx, celestiaChain) - if err != nil { - return nil, nil, fmt.Errorf("failed to get genesis hash: %w", err) - } - - bridgeNodes := daNetwork.GetBridgeNodes() - if len(bridgeNodes) == 0 { - return nil, nil, fmt.Errorf("no bridge nodes available") - } - - bridgeNode := bridgeNodes[0] - - chainID := celestiaChain.GetChainID() - celestiaNodeHostname, err := celestiaChain.GetNodes()[0].GetInternalHostName(ctx) - if err != nil { - return nil, nil, fmt.Errorf("failed to get celestia node hostname: %w", err) - } - - err = bridgeNode.Start(ctx, - types.WithChainID(chainID), - // my-key is the name of the keyring generated by the bridge node, we can fund this key so that we can submit blobs. - types.WithAdditionalStartArguments("--p2p.network", chainID, "--core.ip", celestiaNodeHostname, "--rpc.addr", "0.0.0.0", "--keyring.keyname", "my-key"), - types.WithEnvironmentVariables(map[string]string{ - "CELESTIA_CUSTOM": types.BuildCelestiaCustomEnvVar(chainID, genesisHash, ""), - "P2P_NETWORK": chainID, - }), - ) - if err != nil { - return nil, nil, fmt.Errorf("failed to start bridge node: %w", err) - } - - // hack to get around global, need to set the address prefix before use. - sdk.GetConfig().SetBech32PrefixForAccount("celestia", "celestiapub") - - // Fund the bridge node DA wallet to enable blob submission - t.Log("Funding bridge node DA wallet...") - fundingWallet := celestiaChain.GetFaucetWallet() - - // Get the bridge node's wallet - bridgeWallet, err := bridgeNode.GetWallet() - require.NoError(t, err, "failed to get bridge node wallet") - - // fund the bridge node wallet - daFundingAmount := sdk.NewCoins(sdk.NewCoin("utia", math.NewInt(10_000_000))) - err = sendFunds(ctx, celestiaChain, fundingWallet, bridgeWallet, daFundingAmount) - require.NoError(t, err, "failed to fund bridge node DA wallet") - - return daNetwork, bridgeNode, nil -} - -// CreateEvolveChain sets up the evolve chain connected to the DA network -func CreateEvolveChain(ctx context.Context, t *testing.T, dockerClient *client.Client, networkID string, bridgeNode types.DANode) (*docker.Chain, error) { - // Get DA connection details - authToken, err := bridgeNode.GetAuthToken() - if err != nil { - return nil, fmt.Errorf("failed to get auth token: %w", err) - } - - bridgeRPCAddress, err := bridgeNode.GetInternalRPCAddress() - if err != nil { - return nil, fmt.Errorf("failed to get bridge RPC address: %w", err) - } - - daAddress := fmt.Sprintf("http://%s", bridgeRPCAddress) - namespace := generateValidNamespace() - - // bank and auth modules required to deal with bank send tx's - testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}) - rollkitChain, err := docker.NewChainBuilder(t). - WithEncodingConfig(&testEncCfg). - WithImage(getEvolveAppContainer()). - WithDenom(denom). - WithDockerClient(dockerClient). - WithName("rollkit"). - WithDockerNetworkID(networkID). - WithChainID("rollkit-test"). - WithBech32Prefix("gm"). - WithBinaryName("gmd"). - // explicitly set 0 gas so that we can make exact assertions when sending balances. - WithGasPrices(fmt.Sprintf("0.00%s", denom)). - WithNode(docker.NewChainNodeConfigBuilder(). - // Create aggregator node with evolve-specific start arguments - WithAdditionalStartArgs( - "--rollkit.node.aggregator", - "--rollkit.signer.passphrase", "12345678", - "--rollkit.da.address", daAddress, - "--rollkit.da.gas_price", "0.000001", - "--rollkit.da.auth_token", authToken, - "--rollkit.rpc.address", "0.0.0.0:7331", // bind to 0.0.0.0 so rpc is reachable from test host. - "--rollkit.da.namespace", namespace, - ). - WithPostInit(AddSingleSequencer). - Build()). - Build(ctx) - - if err != nil { - return nil, fmt.Errorf("failed to build evolve chain: %w", err) - } - - err = rollkitChain.Start(ctx) - if err != nil { - return nil, fmt.Errorf("failed to start evolve chain: %w", err) - } - - return rollkitChain, nil -} - -// getGenesisHash retrieves the genesis hash from the celestia chain -func getGenesisHash(ctx context.Context, celestiaChain types.Chain) (string, error) { - node := celestiaChain.GetNodes()[0] - c, err := node.GetRPCClient() - if err != nil { - return "", fmt.Errorf("failed to get node client: %w", err) - } - - first := int64(1) - block, err := c.Block(ctx, &first) - if err != nil { - return "", fmt.Errorf("failed to get block: %w", err) - } - - genesisHash := block.Block.Header.Hash().String() - if genesisHash == "" { - return "", fmt.Errorf("genesis hash is empty") - } - - return genesisHash, nil -} - -func generateValidNamespace() string { - return hex.EncodeToString(share.RandomBlobNamespace().Bytes()) +func TestDockerIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(DockerIntegrationTestSuite)) } // queryBankBalance queries the balance of an address using RPC calls. @@ -246,33 +50,22 @@ func queryBankBalance(ctx context.Context, grpcAddress string, walletAddress str return resp.Balance, nil } -// sendFunds sends funds from one wallet to another using bank transfer -func sendFunds(ctx context.Context, chain *docker.Chain, fromWallet, toWallet types.Wallet, amount sdk.Coins) error { - fromAddress, err := sdkacc.AddressFromWallet(fromWallet) - if err != nil { - return fmt.Errorf("failed to get sender address: %w", err) - } - - toAddress, err := sdkacc.AddressFromWallet(toWallet) - if err != nil { - return fmt.Errorf("failed to get destination address: %w", err) - } - - msg := banktypes.NewMsgSend(fromAddress, toAddress, amount) - resp, err := chain.BroadcastMessages(ctx, fromWallet, msg) - if err != nil { - return fmt.Errorf("failed to broadcast transaction: %w", err) - } +// TestLivenessWithCelestiaDA tests the liveness of rollkit with Celestia DA +func (s *DockerIntegrationTestSuite) TestLivenessWithCelestiaDA() { + ctx := context.Background() + // Test block production - wait for rollkit chain to produce blocks + s.T().Log("Testing block production...") + s.Require().NoError(wait.ForBlocks(ctx, 5, s.evolveChain)) - if resp.Code != 0 { - return fmt.Errorf("transaction failed with code %d: %s", resp.Code, resp.RawLog) - } + // Test transaction submission and query + s.T().Log("Testing transaction submission and query...") + s.testTransactionSubmissionAndQuery(s.T(), ctx, s.evolveChain) - return nil + s.T().Log("Test completed successfully") } // testTransactionSubmissionAndQuery tests sending transactions and querying results using tastora API -func testTransactionSubmissionAndQuery(t *testing.T, ctx context.Context, rollkitChain *docker.Chain) { +func (s *DockerIntegrationTestSuite) testTransactionSubmissionAndQuery(t *testing.T, ctx context.Context, rollkitChain *cosmos.Chain) { // hack to get around global, need to set the address prefix before use. sdk.GetConfig().SetBech32PrefixForAccount("gm", "gmpub") @@ -283,76 +76,28 @@ func testTransactionSubmissionAndQuery(t *testing.T, ctx context.Context, rollki require.NoError(t, err, "failed to create carol wallet") t.Log("Querying Bob's initial balance...") - initialBalance, err := queryBankBalance(ctx, rollkitChain.GetGRPCAddress(), bobsWallet.GetFormattedAddress(), denom) + networkInfo, err := rollkitChain.GetNodes()[0].GetNetworkInfo(ctx) + require.NoError(t, err, "failed to get network info") + initialBalance, err := queryBankBalance(ctx, networkInfo.External.GRPCAddress(), bobsWallet.GetFormattedAddress(), denom) require.NoError(t, err, "failed to query bob's initial balance") require.True(t, initialBalance.Amount.Equal(math.NewInt(1000)), "bob should have 1000 tokens") t.Logf("Sending 100%s from Bob to Carol...", denom) transferAmount := sdk.NewCoins(sdk.NewCoin(denom, math.NewInt(100))) - err = sendFunds(ctx, rollkitChain, bobsWallet, carolsWallet, transferAmount) + // send funds broadcasting to a node that is not the aggregator. + err = s.sendFunds(ctx, rollkitChain, bobsWallet, carolsWallet, transferAmount, 1) require.NoError(t, err, "failed to send funds from Bob to Carol") - finalBalance, err := queryBankBalance(ctx, rollkitChain.GetGRPCAddress(), bobsWallet.GetFormattedAddress(), denom) + finalBalance, err := queryBankBalance(ctx, networkInfo.External.GRPCAddress(), bobsWallet.GetFormattedAddress(), denom) require.NoError(t, err, "failed to query bob's final balance") expectedBalance := initialBalance.Amount.Sub(math.NewInt(100)) require.True(t, finalBalance.Amount.Equal(expectedBalance), "final balance should be exactly initial minus 100") - carolBalance, err := queryBankBalance(ctx, rollkitChain.GetGRPCAddress(), carolsWallet.GetFormattedAddress(), denom) + carolBalance, err := queryBankBalance(ctx, networkInfo.External.GRPCAddress(), carolsWallet.GetFormattedAddress(), denom) require.NoError(t, err, "failed to query carol's balance") - require.True(t, carolBalance.Amount.Equal(math.NewInt(100)), "carol should have received 100 tokens") -} - -func TestLivenessWithCelestiaDA(t *testing.T) { - ctx := context.Background() - dockerClient, networkID := docker.DockerSetup(t) - - celestiaChain, err := CreateCelestiaChain(ctx, t, dockerClient, networkID) - require.NoError(t, err) - t.Cleanup(func() { - if err := celestiaChain.Stop(ctx); err != nil { - t.Logf("failed to stop celestia chain: %v", err) - } - }) - - t.Log("Celestia app chain started") - - _, bridgeNode, err := CreateDANetwork(ctx, t, dockerClient, networkID, celestiaChain) - require.NoError(t, err) - - t.Log("Bridge node started") - - rollkitChain, err := CreateEvolveChain(ctx, t, dockerClient, networkID, bridgeNode) - require.NoError(t, err) - t.Cleanup(func() { - if err := rollkitChain.Stop(ctx); err != nil { - t.Logf("failed to stop evolve chain: %v", err) - } - }) - - t.Log("Evolve chain started") - - // Test block production - wait for evolve chain to produce blocks - t.Log("Testing block production...") - require.NoError(t, wait.ForBlocks(ctx, 5, rollkitChain)) - - // Test transaction submission and query - t.Log("Testing transaction submission and query...") - testTransactionSubmissionAndQuery(t, ctx, rollkitChain) -} - -// getPubKey returns the validator public key. -func getPubKey(ctx context.Context, chainNode *docker.ChainNode) (crypto.PubKey, error) { - keyJSONBytes, err := chainNode.ReadFile(ctx, "config/priv_validator_key.json") - if err != nil { - return nil, err - } - var pvKey cmprivval.FilePVKey - if err = cmtjson.Unmarshal(keyJSONBytes, &pvKey); err != nil { - return nil, fmt.Errorf("failed to unmarshal priv_validator_key.json: %w", err) - } - return pvKey.PubKey, nil + require.True(t, carolBalance.Amount.Equal(math.NewInt(100)), "carol shouldaddFollowerNode have received 100 tokens") } // getEvolveAppContainer returns the evolve app container image. @@ -361,7 +106,7 @@ func getEvolveAppContainer() container.Image { // get image repo and tag from environment variables imageRepo := os.Getenv("EVOLVE_IMAGE_REPO") if imageRepo == "" { - imageRepo = "evolve-gm" // fallback default + imageRepo = "ev-node" // fallback default } imageTag := os.Getenv("EVOLVE_IMAGE_TAG") @@ -370,44 +115,3 @@ func getEvolveAppContainer() container.Image { } return container.NewImage(imageRepo, imageTag, "10001:10001") } - -// AddSingleSequencer modifies the genesis file to add a single sequencer with specified power and public key. -// Reads the genesis file from the node, updates the validators with the sequencer info, and writes the updated file back. -func AddSingleSequencer(ctx context.Context, node *docker.ChainNode) error { - genesisBz, err := node.ReadFile(ctx, "config/genesis.json") - if err != nil { - return fmt.Errorf("failed to read genesis.json: %w", err) - } - - pubKey, err := getPubKey(ctx, node) - if err != nil { - return fmt.Errorf("failed to get pubkey: %w", err) - } - - var genDoc map[string]interface{} - if err := json.Unmarshal(genesisBz, &genDoc); err != nil { - return fmt.Errorf("failed to parse genesis.json: %w", err) - } - - consensus, ok := genDoc["consensus"].(map[string]interface{}) - if !ok { - return fmt.Errorf("genesis.json does not contain a valid 'consensus' object") - } - consensus["validators"] = []map[string]interface{}{ - { - "name": "Ev Node Sequencer", - "address": pubKey.Address(), - "pub_key": map[string]interface{}{ - "type": "tendermint/PubKeyEd25519", - "value": pubKey.Bytes(), - }, - "power": "5", // NOTE: because of default validator wallet amount in tastora the power will be computed as 5. - }, - } - - updatedGenesis, err := json.MarshalIndent(genDoc, "", " ") - if err != nil { - return fmt.Errorf("failed to marshal genesis: %w", err) - } - return node.WriteFile(ctx, "config/genesis.json", updatedGenesis) -} diff --git a/tests/integration/testsuite_test.go b/tests/integration/testsuite_test.go new file mode 100644 index 00000000..41afe1cf --- /dev/null +++ b/tests/integration/testsuite_test.go @@ -0,0 +1,473 @@ +package integration_test + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/celestiaorg/tastora/framework/testutil/config" + cometcfg "github.com/cometbft/cometbft/config" + "github.com/cosmos/ibc-go/v8/modules/apps/transfer" + "github.com/multiformats/go-multihash" + + //multihash "github.com/multiformats/go-multihash/core" + "github.com/pelletier/go-toml/v2" + "regexp" + "time" + + "cosmossdk.io/math" + "github.com/celestiaorg/tastora/framework/docker" + "github.com/celestiaorg/tastora/framework/docker/container" + "github.com/celestiaorg/tastora/framework/docker/cosmos" + "github.com/celestiaorg/tastora/framework/docker/dataavailability" + "github.com/celestiaorg/tastora/framework/testutil/sdkacc" + "github.com/celestiaorg/tastora/framework/types" + "github.com/cometbft/cometbft/crypto" + cmtjson "github.com/cometbft/cometbft/libs/json" + cmprivval "github.com/cometbft/cometbft/privval" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/moby/moby/client" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + "go.uber.org/zap/zaptest" +) + +const ( + celestiaAppTag = "v4.0.10" + celestiaNodeTag = "v0.23.5" + celestiaAppRepo = "ghcr.io/celestiaorg/celestia-app" + celestiaNodeRepo = "ghcr.io/celestiaorg/celestia-node" +) + +// DockerIntegrationTestSuite provides common functionality for integration tests using Docker +type DockerIntegrationTestSuite struct { + suite.Suite + + dockerClient *client.Client + networkID string + celestiaChain *cosmos.Chain + daNetwork *dataavailability.Network + evolveChain *cosmos.Chain + bridgeNode *dataavailability.Node + logger *zap.Logger +} + +// SetupTest initializes the Docker environment for each test +// celestia is deployed, a single bridge node and the rollkit chain. +func (s *DockerIntegrationTestSuite) SetupTest() { + ctx := context.Background() + s.logger = zaptest.NewLogger(s.T()) + s.T().Cleanup(func() { + _ = s.logger.Sync() + }) + s.dockerClient, s.networkID = docker.DockerSetup(s.T()) + + s.celestiaChain = s.CreateCelestiaChain(ctx) + s.T().Log("Celestia app chain started") + + s.bridgeNode = s.CreateDANetwork(ctx) + s.T().Log("Bridge node started") + + /* s.evolveChain = s.CreateEvolveChain(ctx) + s.T().Log("Evolve chain started")*/ +} + +// CreateCelestiaChain sets up a Celestia app chain for DA and stores it in the suite +func (s *DockerIntegrationTestSuite) CreateCelestiaChain(ctx context.Context) *cosmos.Chain { + testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, transfer.AppModuleBasic{}) + celestia, err := cosmos.NewChainBuilder(s.T()). + WithEncodingConfig(&testEncCfg). + WithDockerClient(s.dockerClient). + WithDockerNetworkID(s.networkID). + WithImage(container.NewImage(celestiaAppRepo, celestiaAppTag, "10001:10001")). + WithAdditionalStartArgs( + "--force-no-bbr", + "--grpc.enable", + "--grpc.address", "0.0.0.0:9090", + "--rpc.grpc_laddr=tcp://0.0.0.0:9098", + "--timeout-commit", "1s", + "--minimum-gas-prices", "0.000001utia", + ). + WithPostInit(func(ctx context.Context, node *cosmos.ChainNode) error { + // 1) Ensure ABCI responses and tx events are retained and indexed for Hermes + if err := config.Modify(ctx, node, "config/config.toml", func(cfg *cometcfg.Config) { + cfg.Storage.DiscardABCIResponses = false + // Enable key-value tx indexer so Hermes can query IBC packet events + cfg.TxIndex.Indexer = "kv" + // Increase RPC BroadcastTxCommit timeout to accommodate CI slowness + if cfg.RPC != nil { + cfg.RPC.TimeoutBroadcastTxCommit = 120000000000 // 120s in nanoseconds for toml marshal + } + }); err != nil { + return err + } + // 2) Ensure app-level index-events include IBC packet events + appToml, err := node.ReadFile(ctx, "config/app.toml") + if err != nil { + return err + } + var appCfg map[string]interface{} + if err := toml.Unmarshal(appToml, &appCfg); err != nil { + return err + } + appCfg["index-events"] = []string{ + "message.action", + "send_packet", + "recv_packet", + "write_acknowledgement", + "acknowledge_packet", + "timeout_packet", + } + updated, err := toml.Marshal(appCfg) + if err != nil { + return err + } + return node.WriteFile(ctx, "config/app.toml", updated) + }). + WithNode(cosmos.NewChainNodeConfigBuilder().Build()). + Build(ctx) + + s.Require().NoError(err) + + err = celestia.Start(ctx) + s.Require().NoError(err) + return celestia +} + +// CreateDANetwork sets up the DA network with bridge and full nodes and stores it in the suite +func (s *DockerIntegrationTestSuite) CreateDANetwork(ctx context.Context) *dataavailability.Node { + // Build DA network with bridge node + daNetwork, err := dataavailability.NewNetworkBuilder(s.T()). + WithDockerClient(s.dockerClient). + WithDockerNetworkID(s.networkID). + WithImage(container.NewImage(celestiaNodeRepo, celestiaNodeTag, "10001:10001")). + WithNode(dataavailability.NewNodeBuilder(). + WithNodeType(types.BridgeNode). + Build()). + Build(ctx) + s.Require().NoError(err) + + s.daNetwork = daNetwork + + genesisHash, err := getGenesisHash(ctx, s.celestiaChain) + s.Require().NoError(err) + + bridgeNodes := daNetwork.GetNodesByType(types.BridgeNode) + s.Require().NotEmpty(bridgeNodes, "no bridge nodes available") + + bridgeNode := bridgeNodes[0] + + chainID := s.celestiaChain.GetChainID() + networkInfo, err := s.celestiaChain.GetNodes()[0].GetNetworkInfo(ctx) + s.Require().NoError(err) + celestiaNodeHostname := networkInfo.Internal.Hostname + + err = bridgeNode.Start(ctx, + dataavailability.WithChainID(chainID), + // my-key is the name of the keyring generated by the bridge node, we can fund this key so that we can submit blobs. + dataavailability.WithAdditionalStartArguments("--p2p.network", chainID, "--core.ip", celestiaNodeHostname, "--rpc.addr", "0.0.0.0", "--keyring.keyname", "my-key"), + dataavailability.WithEnvironmentVariables(map[string]string{ + "CELESTIA_CUSTOM": types.BuildCelestiaCustomEnvVar(chainID, genesisHash, ""), + "P2P_NETWORK": chainID, + }), + ) + s.Require().NoError(err) + + // Fund the bridge node DA wallet to enable blob submission + s.fundBridgeNodeWallet(ctx, bridgeNode) + + return bridgeNode +} + +// CreateEvolveChain sets up the rollkit chain connected to the DA network and returns it +func (s *DockerIntegrationTestSuite) CreateEvolveChain(ctx context.Context) *cosmos.Chain { + // Get DA connection details + authToken, err := s.bridgeNode.GetAuthToken() + s.Require().NoError(err) + + bridgeNetworkInfo, err := s.bridgeNode.GetNetworkInfo(ctx) + s.Require().NoError(err) + bridgeRPCAddress := bridgeNetworkInfo.Internal.RPCAddress() + + daAddress := fmt.Sprintf("http://%s", bridgeRPCAddress) + + celestiaHeight, err := s.celestiaChain.Height(ctx) + s.Require().NoError(err) + daStartHeight := fmt.Sprintf("%d", celestiaHeight) + + // bank and auth modules required to deal with bank send tx's + testEncCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}) + // Create chain with only the aggregator node initially + evolveChain, err := cosmos.NewChainBuilder(s.T()). + WithEncodingConfig(&testEncCfg). + WithImage(getEvolveAppContainer()). + WithDenom("stake"). + WithDockerClient(s.dockerClient). + WithName("evolve"). + WithDockerNetworkID(s.networkID). + WithChainID("evolve-test"). + WithBech32Prefix("gm"). + WithBinaryName("gmd"). + // explicitly set 0 gas so that we can make exact assertions when sending balances. + WithGasPrices(fmt.Sprintf("0.00%s", "stake")). + WithNodes( + cosmos.NewChainNodeConfigBuilder(). + // Create aggregator node with rollkit-specific start arguments + WithAdditionalStartArgs( + "--evnode.node.aggregator", + "--evnode.signer.passphrase", "12345678", + "--evnode.da.address", daAddress, + "--evnode.da.gas_price", "0.000001", + "--evnode.da.auth_token", authToken, + "--evnode.rpc.address", "0.0.0.0:7331", + "--evnode.da.namespace", "ev-header", + "--evnode.da.data_namespace", "ev-data", + "--evnode.da.start_height", daStartHeight, + "--evnode.p2p.listen_address", "/ip4/0.0.0.0/tcp/36656", + "--log_level", "*:info", + ). + WithPostInit(addSingleSequencer). + Build(), + ). + Build(ctx) + + s.Require().NoError(err) + + // Start the aggregator node first so that we can query the p2p + err = evolveChain.Start(ctx) + s.Require().NoError(err) + + aggregatorPeer := s.GetNodeMultiAddr(ctx, evolveChain.GetNode()) + s.T().Logf("Aggregator peer: %s", aggregatorPeer) + + s.T().Logf("Adding first follower node...") + s.addFollowerNode(ctx, evolveChain, daAddress, authToken, daStartHeight, aggregatorPeer) + s.T().Logf("Adding second follower node...") + s.addFollowerNode(ctx, evolveChain, daAddress, authToken, daStartHeight, aggregatorPeer) + + return evolveChain +} + +// GetNodeMultiAddr extracts the multiaddr from a rollkit chain node +// Returns the multiaddr in the format: /ip4/{IP}/tcp/36656/p2p/{PEER_ID} +func (s *DockerIntegrationTestSuite) GetNodeMultiAddr(ctx context.Context, node types.ChainNode) string { + // Cast to concrete cosmos.ChainNode to access NodeID method + cosmosNode, ok := node.(*cosmos.ChainNode) + s.Require().True(ok, "node is not a cosmos.ChainNode") + + // Get the node ID + nodeID, err := cosmosNode.NodeID(ctx) + s.Require().NoError(err) + s.Require().NotEmpty(nodeID, "node ID is empty") + + // Get the node's internal IP address + nodeNetworkInfo, err := node.GetNetworkInfo(ctx) + s.Require().NoError(err) + nodeIP := nodeNetworkInfo.Internal.IP + + // Convert hex node ID to libp2p peer ID + nodeIDBytes, err := hex.DecodeString(nodeID) + s.Require().NoError(err) + + // Create a multihash from the node ID bytes (using identity hash since it's already hashed) + mh, err := multihash.Sum(nodeIDBytes, multihash.IDENTITY, -1) + s.Require().NoError(err) + + // Create peer ID from multihash + peerID, err := peer.IDFromBytes(mh) + s.Require().NoError(err) + + // Construct the multiaddr with default rollkit P2P port + multiAddr := fmt.Sprintf("/ip4/%s/tcp/36656/p2p/%s", nodeIP, peerID.String()) + + return multiAddr +} + +// addFollowerNode adds a follower node to the evolve chain. +func (s *DockerIntegrationTestSuite) addFollowerNode(ctx context.Context, evolveChain *cosmos.Chain, daAddress, authToken, daStartHeight, aggregatorPeer string) { + err := evolveChain.AddNode(ctx, cosmos.NewChainNodeConfigBuilder(). + WithAdditionalStartArgs( + "--evnode.da.address", daAddress, + "--evnode.da.gas_price", "0.000001", + "--evnode.da.auth_token", authToken, + "--evnode.rpc.address", "0.0.0.0:7331", + "--evnode.da.namespace", "ev-header", + "--evnode.da.data_namespace", "ev-data", + "--evnode.da.start_height", daStartHeight, + "--evnode.p2p.listen_address", "/ip4/0.0.0.0/tcp/36656", + //"--evnode.p2p.peers", aggregatorPeer, // TODO uncomment to enable P2P, seems broken right now + "--log_level", "*:debug", + ). + Build()) + s.Require().NoError(err) +} + +// getGenesisHash retrieves the genesis hash from the celestia chain +func getGenesisHash(ctx context.Context, chain types.Chain) (string, error) { + node := chain.GetNodes()[0] + c, err := node.GetRPCClient() + if err != nil { + return "", fmt.Errorf("failed to get node client: %w", err) + } + + first := int64(1) + block, err := c.Block(ctx, &first) + if err != nil { + return "", fmt.Errorf("failed to get block: %w", err) + } + + genesisHash := block.Block.Header.Hash().String() + if genesisHash == "" { + return "", fmt.Errorf("genesis hash is empty") + } + + return genesisHash, nil +} + +// sendFunds sends funds from one wallet to another using bank transfer +func (s *DockerIntegrationTestSuite) sendFunds(ctx context.Context, chain *cosmos.Chain, fromWallet, toWallet *types.Wallet, amount sdk.Coins, nodeIdx int) error { + fromAddress, err := sdkacc.AddressFromWallet(fromWallet) + if err != nil { + return fmt.Errorf("failed to get sender address: %w", err) + } + + toAddress, err := sdkacc.AddressFromWallet(toWallet) + if err != nil { + return fmt.Errorf("failed to get destination address: %w", err) + } + + chainNode := chain.GetNodes()[nodeIdx] + cosmosChainNode, ok := chainNode.(*cosmos.ChainNode) + if !ok { + return fmt.Errorf("chainNode is not a cosmos.ChainNode") + } + broadcaster := cosmos.NewBroadcasterForNode(chain, cosmosChainNode) + + time.Sleep(30 * time.Second) + + msg := banktypes.NewMsgSend(fromAddress, toAddress, amount) + resp, err := broadcaster.BroadcastMessages(ctx, fromWallet, msg) + if err != nil { + return fmt.Errorf("failed to broadcast transaction: %w", err) + } + + if resp.Code != 0 { + return fmt.Errorf("transaction failed with code %d: %s", resp.Code, resp.RawLog) + } + + return nil +} + +// addSingleSequencer modifies the genesis file to ensure single sequencer setup +func addSingleSequencer(ctx context.Context, node *cosmos.ChainNode) error { + genesisBz, err := node.ReadFile(ctx, "config/genesis.json") + if err != nil { + return fmt.Errorf("failed to read genesis.json: %w", err) + } + + pubKey, err := getPubKey(ctx, node) + if err != nil { + return fmt.Errorf("failed to get pubkey: %w", err) + } + + var genDoc map[string]interface{} + if err := json.Unmarshal(genesisBz, &genDoc); err != nil { + return fmt.Errorf("failed to parse genesis.json: %w", err) + } + + // set consensus validators to only include the first validator + consensus, ok := genDoc["consensus"].(map[string]interface{}) + if !ok { + return fmt.Errorf("genesis.json does not contain a valid 'consensus' object") + } + consensus["validators"] = []map[string]interface{}{ + { + "name": "Rollkit Sequencer", + "address": pubKey.Address(), + "pub_key": map[string]interface{}{ + "type": "tendermint/PubKeyEd25519", + "value": pubKey.Bytes(), + }, + "power": "5", + }, + } + + updatedGenesis, err := json.MarshalIndent(genDoc, "", " ") + if err != nil { + return fmt.Errorf("failed to marshal genesis: %w", err) + } + + err = node.WriteFile(ctx, "config/genesis.json", updatedGenesis) + if err != nil { + return fmt.Errorf("failed to write genesis.json: %w", err) + } + + return nil +} + +// getPubKey returns the validator public key +func getPubKey(ctx context.Context, chainNode *cosmos.ChainNode) (crypto.PubKey, error) { + keyJSONBytes, err := chainNode.ReadFile(ctx, "config/priv_validator_key.json") + if err != nil { + return nil, err + } + var pvKey cmprivval.FilePVKey + if err = cmtjson.Unmarshal(keyJSONBytes, &pvKey); err != nil { + return nil, fmt.Errorf("failed to unmarshal priv_validator_key.json: %w", err) + } + return pvKey.PubKey, nil +} + +// fundBridgeNodeWallet funds the bridge node's DA wallet for blob submission +func (s *DockerIntegrationTestSuite) fundBridgeNodeWallet(ctx context.Context, bridgeNode *dataavailability.Node) { + // hack to get around global, need to set the address prefix before use. + sdk.GetConfig().SetBech32PrefixForAccount("celestia", "celestiapub") + + s.T().Log("Funding bridge node DA wallet...") + fundingWallet := s.celestiaChain.GetFaucetWallet() + + // Get the bridge node's wallet + bridgeWallet, err := bridgeNode.GetWallet() + s.Require().NoError(err) + + // fund the bridge node wallet + daFundingAmount := sdk.NewCoins(sdk.NewCoin("utia", math.NewInt(10_000_000))) + err = s.sendFunds(ctx, s.celestiaChain, fundingWallet, bridgeWallet, daFundingAmount, 0) + s.Require().NoError(err) +} + +// getDANetworkParams returns the DA network parameters useful for creating an evolve chain +func (s *DockerIntegrationTestSuite) getDANetworkParams(ctx context.Context) (daAddress, authToken, daStartHeight string, err error) { + authToken, err = s.bridgeNode.GetAuthToken() + if err != nil { + return + } + + bridgeNetworkInfo, err := s.bridgeNode.GetNetworkInfo(ctx) + if err != nil { + return + } + daAddress = fmt.Sprintf("http://%s", bridgeNetworkInfo.Internal.RPCAddress()) + + celestiaHeight, err := s.celestiaChain.Height(ctx) + if err != nil { + return + } + daStartHeight = fmt.Sprintf("%d", celestiaHeight) + return +} + +var validContainerCharsRE = regexp.MustCompile(`[^a-zA-Z0-9_.-]`) + +// SanitizeContainerName returns name with any +// invalid characters replaced with underscores. +// Subtests will include slashes, and there may be other +// invalid characters too. +func SanitizeContainerName(name string) string { + return validContainerCharsRE.ReplaceAllLiteralString(name, "_") +}