This file is a merged representation of the entire codebase, combined into a single document by Repomix. The content has been processed where content has been compressed (code blocks are separated by ⋮---- delimiter). # File Summary ## Purpose This file contains a packed representation of the entire repository's contents. It is designed to be easily consumable by AI systems for analysis, code review, or other automated processes. ## File Format The content is organized as follows: 1. This summary section 2. Repository information 3. Directory structure 4. Repository files (if enabled) 5. Multiple file entries, each consisting of: a. A header with the file path (## File: path/to/file) b. The full contents of the file in a code block ## Usage Guidelines - This file should be treated as read-only. Any changes should be made to the original repository files, not this packed version. - When processing this file, use the file path to distinguish between different files in the repository. - Be aware that this file may contain sensitive information. Handle it with the same level of security as you would the original repository. ## Notes - Some files may have been excluded based on .gitignore rules and Repomix's configuration - Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files - Files matching patterns in .gitignore are excluded - Files matching default ignore patterns are excluded - Content has been compressed - code blocks are separated by ⋮---- delimiter - Files are sorted by Git change count (files with more changes are at the bottom) # Directory Structure ``` .github/ workflows/ build.yaml nightly.yaml release.yaml tests.yaml dependabot.yml api/ client/ examples/ main.go README.md v1/ client.go types.go LICENSE proto/ v1/ api.proto cmd/ relay/ root/ app.go config.go root.go main.go utils/ cmd-helpers/ helpers.go keys/ add.go cmd.go print.go remove.go update.go network/ cmd.go genesis.go info.go printers.go operator/ cmd.go info.go invalidate_old_signatures.go register_key.go register_operator.go register_with_signature.go unregister_operator.go unregister_with_signature.go root/ root.go main.go docs/ api/ v1/ api.swagger.json doc.md index.html cli/ relay/ relay_sidecar.md utils/ utils_keys_add.md utils_keys_list.md utils_keys_remove.md utils_keys_update.md utils_keys.md utils_network_generate-genesis.md utils_network_info.md utils_network.md utils_operator_info.md utils_operator_invalidate-old-signatures.md utils_operator_register-key.md utils_operator_register-operator-with-signature.md utils_operator_register-operator.md utils_operator_register-signature.md utils_operator_unregister-operator-with-signature.md utils_operator_unregister-operator.md utils_operator_unregister-signature.md utils_operator.md utils_version.md utils.md e2e/ scripts/ deploy.sh generate_network.sh genesis-generator.sh sidecar-start.sh tests/ api_test.go epoch_test.go genesis_test.go http_gateway_test.go metadata_test.go setup_test.go sidecar.yaml sign_test.go sync_test.go types_test.go README.md setup.sh hack/ codegen/ generate-client-types.go docgen/ generate-cli-docs.go internal/ client/ p2p/ proto/ v1/ message_grpc.pb.go message.pb.go message.proto broadcast_signature_aggregated_message.go broadcast_signature_generated_message.go discovery_integration_test.go discovery_test.go discovery.go p2p_broadcast_test.go p2p_grpc_handler.go p2p_grpc_send_want_aggregation_proofs_request_test.go p2p_grpc_send_want_aggregation_proofs_request.go p2p_grpc_send_want_signatures_request_test.go p2p_grpc_send_want_signatures_request.go p2p_grpc_test.go p2p_handle_message_test.go p2p_handle_message_unit_test.go p2p_handle_message.go p2p_test.go p2p.go repository/ badger/ proto/ v1/ badger.pb.go badger.proto badger_repository_add_proof.go badger_repository_add_signature.go badger_repository_aggregation_proof_pending_test.go badger_repository_aggregation_proof_test.go badger_repository_aggregation_proof.go badger_repository_network_config_test.go badger_repository_network_config.go badger_repository_proof_commits_test.go badger_repository_proof_commits.go badger_repository_proto_test.go badger_repository_signature_map_test.go badger_repository_signature_map.go badger_repository_signature_request_test.go badger_repository_signature_request.go badger_repository_signature_test.go badger_repository_signature.go badger_repository_test.go badger_repository_transaction_test.go badger_repository_transaction.go badger_repository_validator_set_test.go badger_repository_validator_set.go badger_repository.go cached_repository_test.go cached_repository.go cache/ generic_cache.go entity/ entity_aggregation_proof_sync_test.go entity_error.go entity_signature_map_test.go entity_signature_map.go entity_signature_request.go entity_signature_sync.go p2p_entity.go gen/ api/ v1/ api_grpc.pb.go api.pb.go api.pb.gw.go usecase/ aggregation-policy/ low-cost/ low_cost_policy.go low-latency/ low_latency_policy.go types/ types.go aggregation_policies.go aggregator-app/ mocks/ aggregator_app.go aggregator_app_test.go aggregator_app.go api-server/ mocks/ app_mock.go app.go get_aggregation_proof_v1_test.go get_aggregation_proof_v1.go get_aggregation_proofs_by_epoch_v1_test.go get_aggregation_proofs_by_epoch_v1.go get_aggregation_status_v1_test.go get_aggregation_status_v1.go get_current_epoch_v1_test.go get_current_epoch_v1.go get_last_all_committed_v1_test.go get_last_all_committed_v1.go get_last_committed_v1_test.go get_last_committed_v1.go get_local_validator_v1_test.go get_local_validator_v1.go get_signature_request_ids_by_epoch_v1_test.go get_signature_request_ids_by_epoch_v1.go get_signature_request_v1_test.go get_signature_request_v1.go get_signature_requests_by_epoch_v1_test.go get_signature_requests_by_epoch_v1.go get_signature_v1.go get_signatures_by_epoch_v1_test.go get_signatures_by_epoch_v1.go get_signatures_v1_test.go get_validator_by_address_v1_test.go get_validator_by_address_v1.go get_validator_by_key_v1_test.go get_validator_by_key_v1.go get_validator_set_header_v1_test.go get_validator_set_header_v1.go get_validator_set_v1_test.go get_validator_set_v1.go get_validatorset_metadata_v1_test.go get_validatorset_metadata_v1.go helpers_test.go http_test.go http.go interceptors_test.go interceptors.go listen_proofs_v1_test.go listen_proofs_v1.go listen_signature_v1.go listen_signatures_v1_test.go listen_validator_set_v1_test.go listen_validator_set_v1.go sign_message_v1_test.go sign_message_v1.go broadcaster/ doc.go hub_test.go hub.go entity-processor/ mocks/ entity_processor.go entity_processor_test.go entity_processor.go key-provider/ cache_key_provider.go env_provider.go key_provider.go key_store_provider_test.go key_store_provider.go simple_key_provider.go metrics/ metrics_app.go metrics_grpc.go metrics.go signature-listener/ mocks/ signature_listener_uc.go signature_listener_uc_test.go signature_listener_uc.go signer-app/ mocks/ signer_app.go signer_app_handle_signature_aggregated_message.go signer_app_test.go signer_app.go sync-provider/ sync_provider_build_want_aggregation_proofs_request.go sync_provider_build_want_signatures_map.go sync_provider_handle_want_aggregation_proofs_request.go sync_provider_handle_want_signatures.go sync_provider_process_received_aggregation_proofs.go sync_provider_process_received_signatures.go sync_provider_test.go sync_provider.go sync-runner/ sync_runner.go valset-listener/ valset_generator_handle_agg_proof.go valset_listener_uc.go valset-status-tracker/ status_tracker.go pkg/ log/ context_handler.go log_test.go log.go prettylog.go proof/ circuit.go helpers_test.go helpers.go proof_test.go proof.go server/ interceptors.go metrics_server.go signals/ signal_test.go signal.go symbiotic/ client/ evm/ abi/ IKeyRegistry.abi.json ISettlement.abi.json IValSetDriver.abi.json IVotingPowerProvider.abi.json gen/ keyRegistry.go multicall3.go operatorRegistry.go settlement.go valsetDriver.go votingPowerProvider.go mocks/ eth.go eth_commit_valset_test.go eth_commit_valset.go eth_operator_test.go eth_operator.go eth_set_genesis_test.go eth_set_genesis.go eth_test.go eth_verify_quorum_sig_test.go eth_verify_quorum_sig.go eth.go multicall_test.go multicall.go entity/ entity_test.go entity.go evm_entity.go key_tag_entity_test.go key_tag_entity.go key.go usecase/ aggregator/ aggregator-types/ aggregator.go blsBn254Simple/ aggregator_test.go aggregator.go blsBn254ZK/ aggregator_test.go aggregator.go helpers/ helpers_test.go helpers.go aggregators_test.go aggregators.go crypto/ bls12381Bn254/ key_test.go key.go blsBn254/ key_test.go key.go ecdsaSecp256k1/ key_test.go key.go keys.go ssz/ ssz.go types.go valset-deriver/ mocks/ deriver.go valset_deriver_test.go valset_deriver.go symbiotic.go .dockerignore .env.example .gitignore .gitmodules .golangci.yml buf.badger.gen.yaml buf.gen.yaml buf.lock buf.p2p.gen.yaml buf.yaml CONTRIBUTING.md DEVELOPMENT.md Dockerfile example.config.yaml go.mod Makefile README.md ``` # Files ## File: .github/workflows/build.yaml ````yaml --- name: Build on: workflow_call: inputs: version: type: string description: The version to build, if not provided go version srting is used required: false default: "" jobs: build: name: Build runs-on: group: relay timeout-minutes: 15 steps: - name: Checkout source code uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # pin@v4.3.0 with: fetch-depth: 0 - name: Setup Private Git Repo Access run: | git config --global url.https://x-oauth-basic:${{ secrets.GITHUB_TOKEN }}@github.com/.insteadOf https://github.com/ echo "GOPRIVATE=github.com/symbioticfi/relay" >> $GITHUB_ENV - name: Setup Go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # pin@v5.5.0 with: go-version: 1.25.3 - name: Get version id: get_version run: | if [ -n "${{ inputs.version }}" ]; then VERSION_INFO=${{ inputs.version }} echo "Version Info: $VERSION_INFO" echo "TAG=$VERSION_INFO" >> $GITHUB_ENV else echo "No version input provided, will auto calculate" fi - name: Build relay utils linux amd64 run: make build-relay-utils OS=linux ARCH=amd64 - name: Upload artifact relay_utils_linux_amd64 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # pin@v4.6.2 with: name: relay_utils_linux_amd64 path: relay_utils_linux_amd64 - name: Build relay utils linux arm64 run: make build-relay-utils OS=linux ARCH=arm64 - name: Upload artifact relay_utils_linux_arm64 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # pin@v4.6.2 with: name: relay_utils_linux_arm64 path: relay_utils_linux_arm64 - name: Build relay utils darwin arm64 run: make build-relay-utils OS=darwin ARCH=arm64 - name: Upload artifact relay_utils_darwin_arm64 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # pin@v4.6.2 with: name: relay_utils_darwin_arm64 path: relay_utils_darwin_arm64 - name: Build relay sidecar linux amd64 run: make build-relay-sidecar OS=linux ARCH=amd64 - name: Upload artifact relay_sidecar_linux_amd64 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # pin@v4.6.2 with: name: relay_sidecar_linux_amd64 path: relay_sidecar_linux_amd64 - name: Build relay sidecar linux arm64 run: make build-relay-sidecar OS=linux ARCH=arm64 - name: Upload artifact relay_sidecar_linux_arm64 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # pin@v4.6.2 with: name: relay_sidecar_linux_arm64 path: relay_sidecar_linux_arm64 - name: Build relay sidecar darwin arm64 run: make build-relay-sidecar OS=darwin ARCH=arm64 - name: Upload artifact relay_sidecar_darwin_arm64 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # pin@v4.6.2 with: name: relay_sidecar_darwin_arm64 path: relay_sidecar_darwin_arm64 - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 with: driver-opts: network=host - name: Login to Docker Hub uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Cache Docker layers uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx- - name: Build & Push Images run: make image id: push-image timeout-minutes: 30 env: PUSH_IMAGE: true IMAGE_REPO: symbioticfi/relay PUSH_LATEST: true # push latest for all builds nuightly or stable release - name: Echo image built run: echo "Image built - [${{ steps.push-image.outputs.image }}]" ```` ## File: .github/workflows/nightly.yaml ````yaml --- name: Nightly Build on: schedule: # Run at 03:00 UTC every day (avoiding peak 00:00 congestion) - cron: "0 3 * * *" workflow_dispatch: permissions: contents: write jobs: tests: name: Tests uses: ./.github/workflows/tests.yaml secrets: inherit build: needs: - tests name: Build uses: ./.github/workflows/build.yaml secrets: inherit nightly-release: name: Nightly Release needs: - tests - build runs-on: ubuntu-24.04 timeout-minutes: 5 steps: - name: Checkout source code uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # pin@v4.3.0 with: fetch-depth: 0 - name: Generate nightly tag id: nightly_tag run: | DATE=$(date +%Y%m%d) echo "tag=nightly-$DATE" >> "$GITHUB_OUTPUT" echo "Generated nightly tag: nightly-$DATE" - name: Generate changelog id: changelog run: | # Get the last nightly tag or use a fallback LAST_TAG=$(git tag --list "nightly-*" --sort=-version:refname | head -1) if [ -z "$LAST_TAG" ]; then echo "No previous nightly tag found, using last 10 commits" git log -10 --pretty=format:"- %s (%an)" > CHANGELOG.md else echo "Generating changelog between $LAST_TAG and current commit" git log $LAST_TAG..HEAD --pretty=format:"- %s (%an)" > CHANGELOG.md fi cat CHANGELOG.md - name: Download relay utils artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # pin@v5.0.0 with: pattern: relay_utils_* merge-multiple: true - name: Download relay sidecar artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # pin@v5.0.0 with: pattern: relay_sidecar_* merge-multiple: true - name: Create nightly release uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # pin@v2.2.2 with: tag_name: ${{ steps.nightly_tag.outputs.tag }} draft: false prerelease: true body_path: CHANGELOG.md files: | relay_utils_linux_amd64 relay_utils_linux_arm64 relay_utils_darwin_arm64 relay_sidecar_linux_amd64 relay_sidecar_linux_arm64 relay_sidecar_darwin_arm64 ```` ## File: .github/workflows/release.yaml ````yaml --- name: Release on: push: tags: - "v*.*.*" permissions: contents: write jobs: tests: name: Tests uses: ./.github/workflows/tests.yaml secrets: inherit build: needs: - tests name: Build uses: ./.github/workflows/build.yaml with: version: ${{ github.ref_name }} secrets: inherit release: name: Release needs: - tests - build runs-on: ubuntu-24.04 timeout-minutes: 5 steps: - name: Checkout source code uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # pin@v4.3.0 with: fetch-depth: 0 - name: Get previous tag id: get_previous_tag run: | echo "tag=$(git describe --tags --abbrev=0 HEAD^)" >> "$GITHUB_OUTPUT" - name: Generate changelog id: changelog run: | echo "Generating changelog between ${{ steps.get_previous_tag.outputs.tag }} and ${{ github.ref_name }}" git log ${{ steps.get_previous_tag.outputs.tag }}..${{ github.ref_name }} --pretty=format:"- %s (%an)" > CHANGELOG.md cat CHANGELOG.md - name: Download relay utils artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # pin@v5.0.0 with: pattern: relay_utils_* merge-multiple: true - name: Download relay sidecar artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # pin@v5.0.0 with: pattern: relay_sidecar_* merge-multiple: true - name: Release uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # pin@v2.2.2 with: draft: true body_path: CHANGELOG.md files: | relay_utils_linux_amd64 relay_utils_linux_arm64 relay_utils_darwin_arm64 relay_sidecar_linux_amd64 relay_sidecar_linux_arm64 relay_sidecar_darwin_arm64 ```` ## File: .github/workflows/tests.yaml ````yaml --- name: "CI Pipeline" on: pull_request: types: [opened, synchronize, reopened] branches: [dev, main] workflow_call: env: GO_VERSION: "1.25.3" NODE_VERSION: "22" FOUNDRY_VERSION: "v1.3.1" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: code-quality: name: "Code Quality & Linting" runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: "Checkout Repository" uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 0 - name: "Configure Private Repository Access" run: | git config --global url.https://x-oauth-basic:${{ secrets.GITHUB_TOKEN }}@github.com/.insteadOf https://github.com/ echo "GOPRIVATE=github.com/symbioticfi/relay" >> $GITHUB_ENV - name: "Setup Go Environment" uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version: ${{ env.GO_VERSION }} cache: true cache-dependency-path: "go.sum" - name: "Generate Code" run: make generate - name: "Run Code Linting" run: make lint - name: "Verify Code Generation" id: verify-codegen run: | if ! git diff --exit-code; then echo "❌ Code generation produced changes. Please run 'make generate' and commit the changes." echo "changes=true" >> $GITHUB_OUTPUT git diff exit 1 else echo "✅ Code generation verification passed." echo "changes=false" >> $GITHUB_OUTPUT fi unit-tests: name: "Unit Tests" runs-on: ubuntu-24.04 timeout-minutes: 15 needs: [code-quality] steps: - name: "Checkout Repository" uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 0 - name: "Configure Private Repository Access" run: | git config --global url.https://x-oauth-basic:${{ secrets.GITHUB_TOKEN }}@github.com/.insteadOf https://github.com/ echo "GOPRIVATE=github.com/symbioticfi/relay" >> $GITHUB_ENV - name: "Setup Go Environment" uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version: ${{ env.GO_VERSION }} cache: true cache-dependency-path: "go.sum" - name: "Execute Unit Tests" run: make unit-test - name: "Extract Test Coverage" id: coverage run: | if [[ -f coverage.txt ]]; then TOTAL_LINE=$(grep '^total:' coverage.txt | tail -1) COVERAGE=$(echo "$TOTAL_LINE" | grep -Eo '[0-9]+\.[0-9]+%') COVERAGE_VALUE="${COVERAGE:-Not available}" echo "coverage=${COVERAGE_VALUE}" >> $GITHUB_OUTPUT echo "COVERAGE=${COVERAGE_VALUE}" >> $GITHUB_ENV echo "Test Coverage: ${COVERAGE_VALUE}" else echo "coverage=Not available" >> $GITHUB_OUTPUT echo "COVERAGE=Not available" >> $GITHUB_ENV echo "⚠️ Coverage file not found" fi - name: "Post Coverage Report to PR" if: github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2.8.2 with: message: | ## 🧪 Test Coverage Report **Coverage:** `${{ steps.coverage.outputs.coverage }}` e2e-tests: name: "E2E Tests - ${{ matrix.config.name }}" runs-on: ${{ matrix.config.verification_type == 0 && 'relay-16' || 'ubuntu-24.04' }} timeout-minutes: 30 needs: [unit-tests] strategy: matrix: config: - name: "Simple Setup" operators: 4 commiters: 1 aggregators: 1 verification_type: 1 - name: "Multi Committer and Aggregator" operators: 10 commiters: 2 aggregators: 3 verification_type: 1 - name: "ZK Aggregator Test" operators: 10 commiters: 3 aggregators: 3 verification_type: 0 epoch_time: 120 env: # E2E Test Configuration OPERATORS: ${{ matrix.config.operators }} COMMITERS: ${{ matrix.config.commiters }} AGGREGATORS: ${{ matrix.config.aggregators }} VERIFICATION_TYPE: ${{ matrix.config.verification_type }} EPOCH_TIME: ${{ matrix.config.epoch_time || 60 }} BLOCK_TIME: 1 FINALITY_BLOCKS: 2 GENERATE_SIDECARS: false steps: - name: "Checkout Repository" uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 0 - name: "Configure Private Repository Access" run: | git config --global url.https://x-oauth-basic:${{ secrets.GITHUB_TOKEN }}@github.com/.insteadOf https://github.com/ echo "GOPRIVATE=github.com/symbioticfi/relay" >> $GITHUB_ENV - name: "Setup Go Environment" uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version: ${{ env.GO_VERSION }} cache: true cache-dependency-path: "go.sum" - name: "Setup Node.js Environment" uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ env.NODE_VERSION }} - name: "Setup Foundry Toolchain" uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0 with: version: ${{ env.FOUNDRY_VERSION }} - name: "Setup Docker Buildx" uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: "Install Go Dependencies" run: go mod download - name: "Initialize E2E Test Environment" run: | echo "Configuring E2E test environment..." echo " - Operators: ${{ env.OPERATORS }}" echo " - Commiters: ${{ env.COMMITERS }}" echo " - Aggregators: ${{ env.AGGREGATORS }}" echo " - Verification Type: ${{ env.VERIFICATION_TYPE }}" echo " - Epoch Time: ${{ env.EPOCH_TIME }}s" echo " - Block Time: ${{ env.BLOCK_TIME }}s" echo " - Finality Blocks: ${{ env.FINALITY_BLOCKS }}" cd e2e chmod +x setup.sh ./setup.sh cd ../ chmod -R 777 e2e/ - name: "Start Test Network" run: | cd e2e/temp-network echo "Starting Docker Compose network..." docker compose up -d echo "Waiting for services to initialize..." sleep 30 echo "✅ Network startup completed" - name: "Execute E2E Tests" run: | echo "Running End-to-End tests..." make e2e-test - name: "Collect Diagnostic Information" if: failure() run: | cd e2e echo "❌ Test failure detected - collecting diagnostic information..." # Create organized logs directory structure mkdir -p logs/{containers,system,summary} echo "Gathering container information..." # Get active containers (excluding anvil containers which are noisy) CONTAINER_IDS=$(docker ps -a --format "table {{.ID}}\t{{.Names}}" | grep -v -E "(anvil|buildx_buildkit|CONTAINER)" | awk '{print $1}' | tr '\n' ' ') if [ -n "$CONTAINER_IDS" ]; then echo "Found active containers: $(echo $CONTAINER_IDS | wc -w)" # Container status overview { echo "=== Container Status Overview ===" echo "Generated at: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" echo "Workflow: ${{ github.workflow }}" echo "Run ID: ${{ github.run_id }}" echo "" docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -v -E "(anvil|buildx_buildkit)" } > logs/containers/status-overview.log # Individual container logs for container_id in $CONTAINER_IDS; do if [ -n "$container_id" ]; then CONTAINER_NAME=$(docker inspect --format='{{.Name}}' $container_id 2>/dev/null | sed 's/^\/*//' || echo "container-$container_id") echo "Collecting logs for: $CONTAINER_NAME" { echo "=== Container: $CONTAINER_NAME ($container_id) ===" echo "Generated at: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" echo "Last 500 lines of logs:" echo "" docker logs --tail=500 $container_id 2>&1 } > logs/containers/$CONTAINER_NAME.log fi done else echo "⚠️ No active containers found (excluding anvil)" > logs/containers/status-overview.log fi echo "Gathering system information..." { echo "=== System Diagnostics ===" echo "Generated at: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" echo "" echo "=== Disk Usage ===" df -h echo "" echo "=== Memory Usage ===" free -h echo "" echo "=== All Docker Containers ===" docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" echo "" echo "=== Docker Images ===" docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" } > logs/system/diagnostics.log echo "Creating test summary..." { echo "=== E2E Test Failure Summary ===" echo "Timestamp: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" echo "Workflow: ${{ github.workflow }}" echo "Run ID: ${{ github.run_id }}" echo "Run Number: ${{ github.run_number }}" echo "Repository: ${{ github.repository }}" echo "Branch: ${{ github.ref_name }}" echo "" echo "=== Test Configuration ===" echo " - Operators: ${{ env.OPERATORS }}" echo " - Commiters: ${{ env.COMMITERS }}" echo " - Aggregators: ${{ env.AGGREGATORS }}" echo " - Verification Type: ${{ env.VERIFICATION_TYPE }}" echo " - Epoch Time: ${{ env.EPOCH_TIME }}s" echo " - Block Time: ${{ env.BLOCK_TIME }}s" echo " - Finality Blocks: ${{ env.FINALITY_BLOCKS }}" echo "" echo "=== Available Log Files ===" echo "containers/status-overview.log - Container status summary" echo "containers/[name].log - Individual container logs (last 500 lines)" echo "system/diagnostics.log - System resource usage and Docker info" echo "summary/failure-report.log - This summary file" echo "" echo "=== Next Steps ===" echo "1. Review container logs for error messages" echo "2. Check system diagnostics for resource constraints" echo "3. Verify test configuration parameters" echo "4. Consider adjusting timeout values if needed" } > logs/summary/failure-report.log echo "✅ Diagnostic collection completed" echo "Log file summary:" find logs -type f -name "*.log" -exec echo " - {}" \; | sort - name: "Upload Diagnostic Artifacts" if: failure() uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: "e2e-diagnostics-${{ matrix.config.name }}-${{ github.run_number }}-${{ github.run_attempt }}" path: e2e/logs/ retention-days: 7 if-no-files-found: warn ```` ## File: .github/dependabot.yml ````yaml version: 2 updates: # Enable version updates for docker - package-ecosystem: "docker" directory: "/" schedule: interval: "weekly" open-pull-requests-limit: 10 target-branch: "dev" # Enable version updates for go - package-ecosystem: "gomod" directory: "/" schedule: interval: "weekly" open-pull-requests-limit: 10 target-branch: "dev" # Enable version updates for github-actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" open-pull-requests-limit: 5 target-branch: "dev" ```` ## File: api/client/examples/main.go ````go // Basic usage example for the Symbiotic Relay Go client. // // This example demonstrates how to: // 1. Connect to a Symbiotic Relay server // 2. Get the current epoch // 3. Sign a message // 4. Retrieve aggregation proofs // 5. Get validator set information // 6. Get individual signatures // 7. Get signature request IDs by epoch // 8. Get signature requests by epoch // 9. Get a signature request by request ID // 10. Stream signatures in real-time // 11. Stream aggregation proofs in real-time // 12. Stream validator set changes in real-time ⋮---- package main ⋮---- import ( "context" "fmt" "log" "os" "time" "github.com/go-errors/errors" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" client "github.com/symbioticfi/relay/api/client/v1" ) ⋮---- "context" "fmt" "log" "os" "time" ⋮---- "github.com/go-errors/errors" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ⋮---- client "github.com/symbioticfi/relay/api/client/v1" ⋮---- // RelayClient wraps the Symbiotic client with helpful methods type RelayClient struct { client *client.SymbioticClient conn *grpc.ClientConn } ⋮---- // NewRelayClient creates a new client connected to the specified server URL func NewRelayClient(serverURL string) (*RelayClient, error) ⋮---- // Create gRPC connection ⋮---- // Create the symbiotic client ⋮---- // Close closes the gRPC connection func (rc *RelayClient) Close() error ⋮---- // GetCurrentEpoch gets the current epoch information func (rc *RelayClient) GetCurrentEpoch(ctx context.Context) (*client.GetCurrentEpochResponse, error) ⋮---- // GetLastAllCommitted gets the last all committed epochs for all chains func (rc *RelayClient) GetLastAllCommitted(ctx context.Context) (*client.GetLastAllCommittedResponse, error) ⋮---- // SignMessage signs a message using the specified key tag func (rc *RelayClient) SignMessage(ctx context.Context, keyTag uint32, message []byte, requiredEpoch *uint64) (*client.SignMessageResponse, error) ⋮---- // GetAggregationProof gets aggregation proof for a specific request func (rc *RelayClient) GetAggregationProof(ctx context.Context, requestID string) (*client.GetAggregationProofResponse, error) ⋮---- // GetSignatures gets individual signatures for a request func (rc *RelayClient) GetSignatures(ctx context.Context, requestID string) (*client.GetSignaturesResponse, error) ⋮---- // GetSignatureRequestIDsByEpoch gets all signature request IDs for a given epoch func (rc *RelayClient) GetSignatureRequestIDsByEpoch(ctx context.Context, epoch uint64) (*client.GetSignatureRequestIDsByEpochResponse, error) ⋮---- // GetSignatureRequestsByEpoch gets all signature requests for a given epoch func (rc *RelayClient) GetSignatureRequestsByEpoch(ctx context.Context, epoch uint64) (*client.GetSignatureRequestsByEpochResponse, error) ⋮---- // GetSignatureRequest gets a signature request by its request ID func (rc *RelayClient) GetSignatureRequest(ctx context.Context, requestID string) (*client.GetSignatureRequestResponse, error) ⋮---- // GetValidatorSet gets validator set information func (rc *RelayClient) GetValidatorSet(ctx context.Context, epoch *uint64) (*client.GetValidatorSetResponse, error) ⋮---- // ListenSignatures streams signatures in real-time func (rc *RelayClient) ListenSignatures(ctx context.Context, startEpoch *uint64) (grpc.ServerStreamingClient[client.ListenSignaturesResponse], error) ⋮---- // ListenProofs streams aggregation proofs in real-time func (rc *RelayClient) ListenProofs(ctx context.Context, startEpoch *uint64) (grpc.ServerStreamingClient[client.ListenProofsResponse], error) ⋮---- // ListenValidatorSet streams validator set changes in real-time func (rc *RelayClient) ListenValidatorSet(ctx context.Context, startEpoch *uint64) (grpc.ServerStreamingClient[client.ListenValidatorSetResponse], error) ⋮---- func main() ⋮---- // Initialize client ⋮---- // Create context with timeout ⋮---- // Example 1: Get current epoch ⋮---- // Example 2: Get suggested epoch ⋮---- // Example 3: Get validator set ⋮---- // Display some validator details ⋮---- // Example 4: Sign a message ⋮---- // Example 5: Get aggregation proof (this might fail if signing is not complete) ⋮---- // Example 6: Get individual signatures ⋮---- // Example 7: Get signature request IDs by epoch ⋮---- // Display first few request IDs ⋮---- // Example 8: Get signature requests by epoch ⋮---- // Display first few signature requests ⋮---- // Example 9: Get a signature request by request ID ⋮---- // Example 10: Listen to signatures stream ⋮---- // Create a new context with a shorter timeout for streaming example ⋮---- // Start listening from a specific epoch (optional) var startEpoch *uint64 ⋮---- epoch := epochResponse.GetEpoch() - 1 // Start from previous epoch to get some historical data ⋮---- // Example 11: Listen to aggregation proofs stream ⋮---- // Example 12: Listen to validator set changes stream ```` ## File: api/client/examples/README.md ````markdown # Symbiotic Relay Client Examples This directory contains example code demonstrating how to use the [Symbiotic Relay Go client library](../v1/) to interact with a Symbiotic Relay server. ## Basic Usage Example The example shows how to: 1. Connect to a Symbiotic Relay server 2. Get current epoch information 3. Sign messages 4. Retrieve aggregation proofs and signatures 5. Get validator set information 6. Use streaming responses for real-time updates ## Prerequisites Before running the examples, ensure you have: - **[Go 1.25 or later](https://golang.org/doc/install)** installed - **Access to a running Symbiotic Relay Network** - **Network connectivity** to the relay server - **Valid key configurations** on the relay server (for signing operations) ## Running the Example ```bash cd api/client/examples go run main.go ``` By default, the example will try to connect to `localhost:8080`. You can specify a different server URL by setting the `RELAY_SERVER_URL` environment variable: ```bash RELAY_SERVER_URL=my-relay-server:8081 go run main.go ``` NOTE: for the signature/proof generation to work you need to run the script for all active relay servers to get the majority consensus to generate proof. ## Integration with Your Application To integrate this client into your own application: 1. **Import the client package**: ```go import client "github.com/symbioticfi/relay/api/client/v1" ``` 2. **Create a connection**: ```go conn, err := grpc.Dial(serverURL, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return err } client := client.NewSymbioticClient(conn) ``` 3. **Use the client methods** as demonstrated in the [example](main.go) 4. **Handle errors appropriately** for your use case 5. **Ensure proper connection cleanup** with `defer conn.Close()` ## More Examples For a more comprehensive example of using the client library in a real-world application, see: - **[Symbiotic Super Sum Example](https://github.com/symbioticfi/symbiotic-super-sum/tree/main/off-chain)** ## API Reference For complete API documentation, refer to: - **API Documentation**: [`docs/api/v1/doc.md`](../../../docs/api/v1/doc.md) - **Protocol Buffer definitions**: [`api/proto/v1/api.proto`](../../proto/v1/api.proto) - **Generated Go types**: [`api/client/v1/types.go`](../v1/types.go) - **Client interface**: [`api/client/v1/client.go`](../v1/client.go) ## License This client library and example code are licensed under the MIT License. See the [LICENSE](../LICENSE) file for details. ```` ## File: api/client/v1/client.go ````go package v1 ⋮---- import ( apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "google.golang.org/grpc" ) ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "google.golang.org/grpc" ⋮---- // SymbioticClient wraps the generated gRPC client type SymbioticClient struct { apiv1.SymbioticAPIServiceClient } ⋮---- // NewSymbioticClient creates a new client instance for symbiotic relay func NewSymbioticClient(conn grpc.ClientConnInterface) *SymbioticClient ```` ## File: api/client/v1/types.go ````go // Code generated by generate-client-types. DO NOT EDIT. package v1 ⋮---- import ( apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" ) ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" ⋮---- // Exported types for client usage ⋮---- // Enums ⋮---- // Enum constants const ( // ErrorCode values ErrorCode_ERROR_CODE_UNSPECIFIED = apiv1.ErrorCode_ERROR_CODE_UNSPECIFIED ErrorCode_ERROR_CODE_NO_DATA = apiv1.ErrorCode_ERROR_CODE_NO_DATA ErrorCode_ERROR_CODE_INTERNAL = apiv1.ErrorCode_ERROR_CODE_INTERNAL ErrorCode_ERROR_CODE_NOT_AGGREGATOR = apiv1.ErrorCode_ERROR_CODE_NOT_AGGREGATOR // SigningStatus values SigningStatus_SIGNING_STATUS_UNSPECIFIED = apiv1.SigningStatus_SIGNING_STATUS_UNSPECIFIED SigningStatus_SIGNING_STATUS_PENDING = apiv1.SigningStatus_SIGNING_STATUS_PENDING SigningStatus_SIGNING_STATUS_COMPLETED = apiv1.SigningStatus_SIGNING_STATUS_COMPLETED SigningStatus_SIGNING_STATUS_FAILED = apiv1.SigningStatus_SIGNING_STATUS_FAILED SigningStatus_SIGNING_STATUS_TIMEOUT = apiv1.SigningStatus_SIGNING_STATUS_TIMEOUT // ValidatorSetStatus values ValidatorSetStatus_VALIDATOR_SET_STATUS_UNSPECIFIED = apiv1.ValidatorSetStatus_VALIDATOR_SET_STATUS_UNSPECIFIED ValidatorSetStatus_VALIDATOR_SET_STATUS_DERIVED = apiv1.ValidatorSetStatus_VALIDATOR_SET_STATUS_DERIVED ValidatorSetStatus_VALIDATOR_SET_STATUS_AGGREGATED = apiv1.ValidatorSetStatus_VALIDATOR_SET_STATUS_AGGREGATED ValidatorSetStatus_VALIDATOR_SET_STATUS_COMMITTED = apiv1.ValidatorSetStatus_VALIDATOR_SET_STATUS_COMMITTED ValidatorSetStatus_VALIDATOR_SET_STATUS_MISSED = apiv1.ValidatorSetStatus_VALIDATOR_SET_STATUS_MISSED ) ⋮---- // ErrorCode values ⋮---- // SigningStatus values ⋮---- // ValidatorSetStatus values ⋮---- // Request types ⋮---- // Response types ⋮---- // Data types ```` ## File: api/client/LICENSE ```` MIT License Copyright (c) 2025 Symbiotic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ```` ## File: api/proto/v1/api.proto ````protobuf syntax = "proto3"; package api.proto.v1; import "google/protobuf/timestamp.proto"; import "google/api/annotations.proto"; option go_package = "github.com/symbioticfi/relay/api/proto/v1"; // SymbioticAPI provides access to the Symbiotic relay functions service SymbioticAPIService { // Sign a message rpc SignMessage(SignMessageRequest) returns (SignMessageResponse) { option (google.api.http) = { post: "/v1/sign" body: "*" }; } // Get aggregation proof rpc GetAggregationProof(GetAggregationProofRequest) returns (GetAggregationProofResponse) { option (google.api.http) = { get: "/v1/aggregation/proof/{request_id}" }; } // Get aggregation proofs by epoch rpc GetAggregationProofsByEpoch(GetAggregationProofsByEpochRequest) returns (GetAggregationProofsByEpochResponse) { option (google.api.http) = { get: "/v1/aggregation/proofs/epoch/{epoch}" }; } // Get current epoch rpc GetCurrentEpoch(GetCurrentEpochRequest) returns (GetCurrentEpochResponse) { option (google.api.http) = { get: "/v1/epoch/current" }; } // Get signature by request id rpc GetSignatures(GetSignaturesRequest) returns (GetSignaturesResponse) { option (google.api.http) = { get: "/v1/signatures/{request_id}" }; } // Get signature by epoch rpc GetSignaturesByEpoch(GetSignaturesByEpochRequest) returns (GetSignaturesByEpochResponse) { option (google.api.http) = { get: "/v1/signatures/epoch/{epoch}" }; } // Get all signature request IDs by epoch rpc GetSignatureRequestIDsByEpoch(GetSignatureRequestIDsByEpochRequest) returns (GetSignatureRequestIDsByEpochResponse) { option (google.api.http) = { get: "/v1/signature-request-ids/epoch/{epoch}" }; } // Get all signature requests by epoch rpc GetSignatureRequestsByEpoch(GetSignatureRequestsByEpochRequest) returns (GetSignatureRequestsByEpochResponse) { option (google.api.http) = { get: "/v1/signature-requests/epoch/{epoch}" }; } // Get signature request by request id rpc GetSignatureRequest(GetSignatureRequestRequest) returns (GetSignatureRequestResponse) { option (google.api.http) = { get: "/v1/signature-request/{request_id}" }; } // Get aggregation status, can be sent only to aggregator nodes rpc GetAggregationStatus(GetAggregationStatusRequest) returns (GetAggregationStatusResponse) { option (google.api.http) = { get: "/v1/aggregation/status/{request_id}" }; } // Get current validator set rpc GetValidatorSet(GetValidatorSetRequest) returns (GetValidatorSetResponse) { option (google.api.http) = { get: "/v1/validator-set" }; } // Get validator by address rpc GetValidatorByAddress(GetValidatorByAddressRequest) returns (GetValidatorByAddressResponse) { option (google.api.http) = { get: "/v1/validator/address/{address}" }; } // Get validator by key rpc GetValidatorByKey(GetValidatorByKeyRequest) returns (GetValidatorByKeyResponse) { option (google.api.http) = { get: "/v1/validator/key/{key_tag}/{on_chain_key}" }; } // Get local validator rpc GetLocalValidator(GetLocalValidatorRequest) returns (GetLocalValidatorResponse) { option (google.api.http) = { get: "/v1/validator/local" }; } // Get validator set header rpc GetValidatorSetHeader(GetValidatorSetHeaderRequest) returns (GetValidatorSetHeaderResponse) { option (google.api.http) = { get: "/v1/validator-set/header" }; } // Get last committed epoch for a specific settlement chain rpc GetLastCommitted(GetLastCommittedRequest) returns (GetLastCommittedResponse) { option (google.api.http) = { get: "/v1/committed/chain/{settlement_chain_id}" }; } // Get last committed epochs for all settlement chains rpc GetLastAllCommitted(GetLastAllCommittedRequest) returns (GetLastAllCommittedResponse) { option (google.api.http) = { get: "/v1/committed/all" }; } // Get validator set metadata like extra data and request id to fetch aggregation and signature requests rpc GetValidatorSetMetadata(GetValidatorSetMetadataRequest) returns (GetValidatorSetMetadataResponse) { option (google.api.http) = { get: "/v1/validator-set/metadata" }; } // Stream signatures in real-time. If start_epoch is provided, sends historical data first rpc ListenSignatures(ListenSignaturesRequest) returns (stream ListenSignaturesResponse) { option (google.api.http) = { get: "/v1/stream/signatures" }; } // Stream aggregation proofs in real-time. If start_epoch is provided, sends historical data first rpc ListenProofs(ListenProofsRequest) returns (stream ListenProofsResponse) { option (google.api.http) = { get: "/v1/stream/proofs" }; } // Stream validator set changes in real-time. If start_epoch is provided, sends historical data first rpc ListenValidatorSet(ListenValidatorSetRequest) returns (stream ListenValidatorSetResponse) { option (google.api.http) = { get: "/v1/stream/validator-set" }; } } // Request message for signing a message message SignMessageRequest { // Key tag identifier (0-127) uint32 key_tag = 1; // Message to be signed bytes message = 2; // Required epoch (optional, if not provided latest committed epoch will be used) optional uint64 required_epoch = 3; } // Response message for sign message request message SignMessageResponse { // Hash of the signature request string request_id = 1; // Epoch number uint64 epoch = 2; } // Request message for listening to signatures stream message ListenSignaturesRequest { // Optional: start epoch. If provided, stream will first send all historical signatures starting from this epoch, then continue with real-time updates // If not provided, only signatures generated after stream creation will be sent optional uint64 start_epoch = 1; } // Response message for signatures stream message ListenSignaturesResponse { // Id of the signature request string request_id = 1; // Epoch number uint64 epoch = 2; // Signature data Signature signature = 3; } // Request message for listening to aggregation proofs stream message ListenProofsRequest { // Optional: start epoch. If provided, stream will first send all historical proofs starting from this epoch, then continue with real-time updates // If not provided, only proofs generated after stream creation will be sent optional uint64 start_epoch = 1; } // Response message for aggregation proofs stream message ListenProofsResponse { // Id of the request string request_id = 1; // Epoch number uint64 epoch = 2; // Final aggregation proof AggregationProof aggregation_proof = 3; } // Request message for listening to validator set changes stream message ListenValidatorSetRequest { // Optional: start epoch. If provided, stream will first send all historical validator sets starting from this epoch, then continue with real-time updates // If not provided, only validator sets generated after stream creation will be sent optional uint64 start_epoch = 1; } // Response message for validator set changes stream message ListenValidatorSetResponse { // The validator set ValidatorSet validator_set = 1; } // Request message for getting aggregation proof message GetAggregationProofRequest { string request_id = 1; } // Request message for getting aggregation proof message GetAggregationProofsByEpochRequest { // Epoch number uint64 epoch = 1; } // Request message for getting current epoch message GetCurrentEpochRequest {} // Request message for getting signatures message GetSignaturesRequest { string request_id = 1; } // Request message for getting signatures by epoch message GetSignaturesByEpochRequest { // Epoch number uint64 epoch = 1; } // Response message for getting signatures message GetSignaturesResponse { // List of signatures repeated Signature signatures = 1; } // Response message for getting signatures by epoch message GetSignaturesByEpochResponse { // List of signatures repeated Signature signatures = 1; } // Request message for getting all signature request IDs by epoch message GetSignatureRequestIDsByEpochRequest { // Epoch number uint64 epoch = 1; } // Response message for getting all signature request IDs by epoch message GetSignatureRequestIDsByEpochResponse { // List of all signature request IDs for the epoch repeated string request_ids = 1; } // Request message for getting all signature requests by epoch message GetSignatureRequestsByEpochRequest { // Epoch number uint64 epoch = 1; } // Response message for getting all signature requests by epoch message GetSignatureRequestsByEpochResponse { // List of all signature requests for the epoch repeated SignatureRequest signature_requests = 1; } // Request message for getting signature request message GetSignatureRequestRequest { string request_id = 1; } // Request message for getting aggregation status message GetAggregationStatusRequest { string request_id = 1; } // Request message for getting validator set message GetValidatorSetRequest { // Epoch number (optional, if not provided current epoch will be used) optional uint64 epoch = 1; } // Request message for getting validator by address message GetValidatorByAddressRequest { // Epoch number (optional, if not provided current epoch will be used) optional uint64 epoch = 1; // Validator address (required) string address = 2; } // Request message for getting validator by key message GetValidatorByKeyRequest { // Epoch number (optional, if not provided current epoch will be used) optional uint64 epoch = 1; // Validator key tag (required) uint32 key_tag = 2; // Validator on chain (public) key (required) bytes on_chain_key = 3; } // Request message for getting local validator message GetLocalValidatorRequest { // Epoch number (optional, if not provided current epoch will be used) optional uint64 epoch = 1; } // Request message for getting validator set header message GetValidatorSetHeaderRequest { // Epoch number (optional, if not provided current epoch will be used) optional uint64 epoch = 1; } // Request message for getting validator set metadata message GetValidatorSetMetadataRequest { // Epoch number (optional, if not provided current epoch will be used) optional uint64 epoch = 1; } // Response message for getting current epoch message GetCurrentEpochResponse { // Epoch number uint64 epoch = 1; // Epoch start time google.protobuf.Timestamp start_time = 2; } // SignatureRequest represents a signature request message SignatureRequest { // Request ID string request_id = 1; // Key tag identifier (0-127) uint32 key_tag = 2; // Message to be signed bytes message = 3; // Required epoch uint64 required_epoch = 4; } // Response message for getting signature request message GetSignatureRequestResponse { SignatureRequest signature_request = 1; } // Response message for getting aggregation proof message GetAggregationProofResponse { AggregationProof aggregation_proof = 1; } // Response message for getting aggregation proof message GetAggregationProofsByEpochResponse { repeated AggregationProof aggregation_proofs = 1; } // Response message for getting aggregation proof message AggregationProof { // Message hash bytes message_hash = 2; // Proof data bytes proof = 3; // Request ID string request_id = 4; } // Response message for getting aggregation status message GetAggregationStatusResponse { // Current voting power of the aggregator (big integer as string) string current_voting_power = 1; // List of operator addresses that signed the request repeated string signer_operators = 2; } // Digital signature message Signature { // Signature data bytes signature = 1; // Message hash bytes message_hash = 2; // Public key bytes public_key = 3; // Request ID string request_id = 4; } // Response message for getting validator set message GetValidatorSetResponse { // The validator set ValidatorSet validator_set = 1; } // Response message for getting validator by address message GetValidatorByAddressResponse { // The validator Validator validator = 1; } // Response message for getting validator by key message GetValidatorByKeyResponse { // The validator Validator validator = 1; } // Response message for getting local validator message GetLocalValidatorResponse { // The validator Validator validator = 1; } message ExtraData { bytes key = 1; bytes value = 2; } // Response message for getting validator set header message GetValidatorSetMetadataResponse { repeated ExtraData extra_data = 1; bytes commitment_data = 2; string request_id = 3; } // Response message for getting validator set header message GetValidatorSetHeaderResponse { // Version of the validator set uint32 version = 1; // Key tag required to commit next validator set uint32 required_key_tag = 2; // Validator set epoch uint64 epoch = 3; // Epoch capture timestamp google.protobuf.Timestamp capture_timestamp = 4; // Quorum threshold (big integer as string) string quorum_threshold = 5; // Total voting power (big integer as string) string total_voting_power = 6; // Validators SSZ Merkle root (hex string) string validators_ssz_mroot = 7; } // Validator set status enumeration enum ValidatorSetStatus { // Default/unknown status VALIDATOR_SET_STATUS_UNSPECIFIED = 0; // Derived status VALIDATOR_SET_STATUS_DERIVED = 1; // Aggregated status VALIDATOR_SET_STATUS_AGGREGATED = 2; // Committed status VALIDATOR_SET_STATUS_COMMITTED = 3; // Missed status VALIDATOR_SET_STATUS_MISSED = 4; } // Validator information message Validator { // Operator address (hex string) string operator = 1; // Voting power of the validator (big integer as string) string voting_power = 2; // Indicates if the validator is active bool is_active = 3; // List of cryptographic keys repeated Key keys = 4; // List of validator vaults repeated ValidatorVault vaults = 5; } // Cryptographic key message Key { // Key tag identifier (0-127) uint32 tag = 1; // Key payload bytes payload = 2; } // Validator vault information message ValidatorVault { // Chain identifier uint64 chain_id = 1; // Vault address string vault = 2; // Voting power for this vault (big integer as string) string voting_power = 3; } // Signing process status enumeration enum SigningStatus { // Default/unknown status SIGNING_STATUS_UNSPECIFIED = 0; // Request has been created and is waiting for signatures SIGNING_STATUS_PENDING = 1; // Signing process completed successfully with proof SIGNING_STATUS_COMPLETED = 2; // Signing process failed SIGNING_STATUS_FAILED = 3; // Signing request timed out SIGNING_STATUS_TIMEOUT = 4; } // Error code enumeration enum ErrorCode { // Default/unknown error ERROR_CODE_UNSPECIFIED = 0; // No data found ERROR_CODE_NO_DATA = 1; // Internal server error ERROR_CODE_INTERNAL = 2; // Not an aggregator node ERROR_CODE_NOT_AGGREGATOR = 3; } // Request message for getting last committed epoch for a specific settlement chain message GetLastCommittedRequest { // Settlement chain ID uint64 settlement_chain_id = 1; } // Response message for getting last committed epoch message GetLastCommittedResponse { // Settlement chain ID uint64 settlement_chain_id = 1; ChainEpochInfo epoch_info = 2; } // Request message for getting last committed epochs for all chains message GetLastAllCommittedRequest { // No parameters needed } // Response message for getting all last committed epochs message GetLastAllCommittedResponse { // List of settlement chains with their last committed epochs map epoch_infos = 1; // Suggested epoch info for signatures, it is the minimum commited epoch among all chains ChainEpochInfo suggested_epoch_info = 2; } // Settlement chain with its last committed epoch message ChainEpochInfo { // Last committed epoch for this chain uint64 last_committed_epoch = 1; // Epoch start time google.protobuf.Timestamp start_time = 2; } message ValidatorSet { // Version of the validator set uint32 version = 1; // Key tag required to commit next validator set uint32 required_key_tag = 2; // Validator set epoch uint64 epoch = 3; // Epoch capture timestamp google.protobuf.Timestamp capture_timestamp = 4; // Quorum threshold (big integer as string) string quorum_threshold = 5; // Status of validator set header ValidatorSetStatus status = 6; // List of validators repeated Validator validators = 7; } ```` ## File: cmd/relay/root/app.go ````go package root ⋮---- import ( "context" "log/slog" "net/http" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/go-errors/errors" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/libp2p/go-libp2p/p2p/transport/tcp" "golang.org/x/sync/errgroup" "github.com/symbioticfi/relay/internal/client/p2p" "github.com/symbioticfi/relay/internal/client/repository/badger" "github.com/symbioticfi/relay/internal/entity" aggregationPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy" aggregatorApp "github.com/symbioticfi/relay/internal/usecase/aggregator-app" api_server "github.com/symbioticfi/relay/internal/usecase/api-server" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" signatureListener "github.com/symbioticfi/relay/internal/usecase/signature-listener" signerApp "github.com/symbioticfi/relay/internal/usecase/signer-app" sync_provider "github.com/symbioticfi/relay/internal/usecase/sync-provider" sync_runner "github.com/symbioticfi/relay/internal/usecase/sync-runner" valsetListener "github.com/symbioticfi/relay/internal/usecase/valset-listener" valsetStatusTracker "github.com/symbioticfi/relay/internal/usecase/valset-status-tracker" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/proof" "github.com/symbioticfi/relay/pkg/signals" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ) ⋮---- "context" "log/slog" "net/http" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/go-errors/errors" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/libp2p/go-libp2p/p2p/transport/tcp" "golang.org/x/sync/errgroup" ⋮---- "github.com/symbioticfi/relay/internal/client/p2p" "github.com/symbioticfi/relay/internal/client/repository/badger" "github.com/symbioticfi/relay/internal/entity" aggregationPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy" aggregatorApp "github.com/symbioticfi/relay/internal/usecase/aggregator-app" api_server "github.com/symbioticfi/relay/internal/usecase/api-server" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" signatureListener "github.com/symbioticfi/relay/internal/usecase/signature-listener" signerApp "github.com/symbioticfi/relay/internal/usecase/signer-app" sync_provider "github.com/symbioticfi/relay/internal/usecase/sync-provider" sync_runner "github.com/symbioticfi/relay/internal/usecase/sync-runner" valsetListener "github.com/symbioticfi/relay/internal/usecase/valset-listener" valsetStatusTracker "github.com/symbioticfi/relay/internal/usecase/valset-status-tracker" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/proof" "github.com/symbioticfi/relay/pkg/signals" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ⋮---- func runApp(ctx context.Context) error ⋮---- var keyProvider *keyprovider.CacheKeyProvider ⋮---- var err error ⋮---- var prover *proof.ZkProver ⋮---- // Load all missing epochs before starting services ⋮---- // also start monitoring for new epochs immediately so that we don't miss any epochs while starting other services ⋮---- var aggApp *aggregatorApp.AggregatorApp ⋮---- func initP2PService(ctx context.Context, cfg config, keyProvider keyprovider.KeyProvider, provider *sync_provider.Syncer, mtr *metrics.Metrics) (*p2p.Service, *p2p.DiscoveryService, error) ⋮---- // pad to make 20 byte to 32 bytes ⋮---- // TODO: include p2p key in valset ⋮---- libp2p.PrivateNetwork(swarmPSK), // Use a private network with the provided swarm key libp2p.Identity(p2pIdentityPK), // Use the provided identity private key to sign messages that will be sent over the P2P gossip sub ```` ## File: cmd/relay/root/config.go ````go package root ⋮---- import ( "context" "fmt" "io/fs" "reflect" "strconv" "strings" "time" "github.com/spf13/pflag" "github.com/symbioticfi/relay/pkg/signals" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/samber/lo" "github.com/spf13/cobra" "github.com/spf13/viper" ) ⋮---- "context" "fmt" "io/fs" "reflect" "strconv" "strings" "time" ⋮---- "github.com/spf13/pflag" ⋮---- "github.com/symbioticfi/relay/pkg/signals" ⋮---- "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/samber/lo" "github.com/spf13/cobra" "github.com/spf13/viper" ⋮---- // The config can be populated from command-line flags, environment variables, and a config.yaml file. // Priority order (highest to lowest): // 1. Command-line flags // 2. Environment variables (prefixed with SYMB_ and dashes replaced by underscores) // 3. config.yaml file (specified by --config or default "config.yaml") type config struct { StorageDir string `mapstructure:"storage-dir"` CircuitsDir string `mapstructure:"circuits-dir"` MaxUnsigners uint64 `mapstructure:"aggregation-policy-max-unsigners"` Log LogConfig `mapstructure:"log" validate:"required"` API APIConfig `mapstructure:"api" validate:"required"` Metrics MetricsConfig `mapstructure:"metrics"` Driver CMDCrossChainAddress `mapstructure:"driver" validate:"required"` SecretKeys CMDSecretKeySlice `mapstructure:"secret-keys"` KeyStore KeyStore `mapstructure:"keystore"` SignalCfg signals.Config `mapstructure:"signal"` Cache CacheConfig `mapstructure:"cache"` Sync SyncConfig `mapstructure:"sync"` KeyCache KeyCache `mapstructure:"key-cache"` P2P P2PConfig `mapstructure:"p2p" validate:"required"` Evm EvmConfig `mapstructure:"evm" validate:"required"` ForceRole ForceRole `mapstructure:"force-role"` Retention RetentionConfig `mapstructure:"retention"` } ⋮---- type LogConfig struct { Level string `mapstructure:"level" validate:"oneof=debug info warn error"` Mode string `mapstructure:"mode" validate:"oneof=json text pretty"` } ⋮---- type APIConfig struct { ListenAddress string `mapstructure:"listen" validate:"required"` MaxAllowedStreams uint64 `mapstructure:"max-allowed-streams" validate:"required"` VerboseLogging bool `mapstructure:"verbose-logging"` HTTPGateway bool `mapstructure:"http-gateway"` } ⋮---- type MetricsConfig struct { ListenAddress string `mapstructure:"listen"` PprofEnabled bool `mapstructure:"pprof"` } ⋮---- type CMDCrossChainAddress struct { ChainID uint64 `mapstructure:"chain-id" validate:"required"` Address string `mapstructure:"address" validate:"required"` } ⋮---- type CMDSecretKeySlice []CMDSecretKey ⋮---- func (s *CMDSecretKeySlice) String() string ⋮---- func (s *CMDSecretKeySlice) Set(str string) error ⋮---- func (s *CMDSecretKeySlice) Type() string ⋮---- type CMDSecretKey struct { Namespace string `validate:"required"` KeyType uint8 `validate:"required"` KeyId int `validate:"required"` Secret string `validate:"required"` } ⋮---- func (c *CMDSecretKey) FromStr(str string) (*CMDSecretKey, error) ⋮---- type KeyStore struct { Path string `json:"path"` Password string `json:"password"` } type CacheConfig struct { NetworkConfigCacheSize int `mapstructure:"network-config-size"` ValidatorSetCacheSize int `mapstructure:"validator-set-size"` } ⋮---- type SyncConfig struct { Enabled bool `mapstructure:"enabled"` Period time.Duration `mapstructure:"period"` Timeout time.Duration `mapstructure:"timeout"` EpochsToSync uint64 `mapstructure:"epochs"` } ⋮---- type KeyCache struct { // max size of the cache Size int `mapstructure:"size"` Enabled bool `mapstructure:"enabled"` } ⋮---- // max size of the cache ⋮---- type P2PConfig struct { ListenAddress string `mapstructure:"listen" validate:"required"` Bootnodes []string `mapstructure:"bootnodes"` DHTMode string `mapstructure:"dht-mode" validate:"oneof=auto server client disabled"` MDnsEnabled bool `mapstructure:"mdns"` } ⋮---- type EvmConfig struct { Chains []string `mapstructure:"chains" validate:"required"` MaxCalls int `mapstructure:"max-calls"` } ⋮---- type ForceRole struct { Aggregator bool `mapstructure:"aggregator"` Committer bool `mapstructure:"committer"` } ⋮---- type RetentionConfig struct { ValSetEpochs uint64 `mapstructure:"valset-epochs"` } ⋮---- func (c config) Validate() error ⋮---- // Validate that sync.epochs doesn't exceed retention.valset-epochs ⋮---- var ( configFile string ) ⋮---- func addRootFlags(cmd *cobra.Command) ⋮---- func DecodeFlagToStruct(fromType reflect.Type, toType reflect.Type, from interface ⋮---- // if not string return as is ⋮---- // Handle time.Duration specifically ⋮---- // if fromType implements pflag.Value then we can parse it from string ⋮---- func initConfig(cmd *cobra.Command, _ []string) error ⋮---- var cfg config ⋮---- // pflags allows to implement custom types by implementing pflag.Value (we can define how to parse struct from string) // but[1] viper converts back struct defined flags to string automatically using String() method :( // but[2] fortunately viper allows to pass decoder that we can use to convert string back to struct :D ⋮---- type contextKeyStruct struct{} ⋮---- func ctxWithCfg(ctx context.Context, cfg config) context.Context func cfgFromCtx(ctx context.Context) config ```` ## File: cmd/relay/root/root.go ````go package root ⋮---- import ( "context" "log/slog" "os" "os/signal" "syscall" "github.com/spf13/cobra" ) ⋮---- "context" "log/slog" "os" "os/signal" "syscall" ⋮---- "github.com/spf13/cobra" ⋮---- var Version = "local" var BuildTime = "unknown" ⋮---- func NewRootCommand() *cobra.Command ⋮---- // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "relay_sidecar", Short: "Relay sidecar for signature aggregation", Long: "A P2P service for collecting and aggregating signatures for Ethereum contracts.", SilenceUsage: true, SilenceErrors: true, PersistentPreRunE: initConfig, RunE: func(cmd *cobra.Command, args []string) error { return runApp(signalContext(cmd.Context())) }, } ⋮---- // signalContext returns a context that is canceled if either SIGTERM or SIGINT signal is received. func signalContext(ctx context.Context) context.Context ```` ## File: cmd/relay/main.go ````go package main ⋮---- import ( "context" "log/slog" "os" "github.com/go-errors/errors" "github.com/symbioticfi/relay/cmd/relay/root" ) ⋮---- "context" "log/slog" "os" ⋮---- "github.com/go-errors/errors" "github.com/symbioticfi/relay/cmd/relay/root" ⋮---- func main() ```` ## File: cmd/utils/cmd-helpers/helpers.go ````go package cmdhelpers ⋮---- import ( "fmt" "math/big" "sort" "strconv" "strings" "syscall" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/go-errors/errors" "github.com/pterm/pterm" "golang.org/x/term" ) ⋮---- "fmt" "math/big" "sort" "strconv" "strings" "syscall" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/go-errors/errors" "github.com/pterm/pterm" "golang.org/x/term" ⋮---- type SecretKeyMapFlag struct { Secrets map[uint64]string } ⋮---- func (s *SecretKeyMapFlag) String() string ⋮---- sort.Strings(parts) // Optional: consistent output order ⋮---- func (s *SecretKeyMapFlag) Set(val string) error ⋮---- func (s *SecretKeyMapFlag) Type() string ⋮---- func GetPassword() (string, error) ⋮---- func PrintTreeValidator(leveledList pterm.LeveledList, validator symbiotic.Validator, totalVotingPower *big.Int) pterm.LeveledList ⋮---- func GetPct(value *big.Int, total *big.Int) float64 ```` ## File: cmd/utils/keys/add.go ````go package keys ⋮---- import ( cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/spf13/cobra" ) ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/spf13/cobra" ⋮---- var addKeyCmd = &cobra.Command{ Use: "add", Short: "Add key", RunE: func(cmd *cobra.Command, args []string) error { if addFlags.PrivateKey == "" && !addFlags.Generate { return errors.New("add --generate if private key omitted") } if addFlags.EvmNs { if addFlags.ChainID < 0 { return errors.New("chain ID is required for evm namespace, use --chain-id=0 for default key for all chains") } return addKeyWithNamespace(keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(addFlags.ChainID), addFlags.Generate, addFlags.Force, addFlags.PrivateKey) } else if addFlags.RelayNs { if addFlags.KeyTag == uint8(symbiotic.KeyTypeInvalid) { return errors.New("key tag is required for relay namespace") } kt := symbiotic.KeyTag(addFlags.KeyTag) if kt.Type() == symbiotic.KeyTypeInvalid { return errors.New("invalid key tag, type not supported") } keyId := kt & 0x0F return addKeyWithNamespace(keyprovider.SYMBIOTIC_KEY_NAMESPACE, kt.Type(), int(keyId), addFlags.Generate, addFlags.Force, addFlags.PrivateKey) } else if addFlags.P2PNs { return addKeyWithNamespace(keyprovider.P2P_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, keyprovider.P2P_HOST_IDENTITY_KEY_ID, addFlags.Generate, addFlags.Force, addFlags.PrivateKey) } return errors.New("either --evm or --relay or --p2p must be specified") }, } ⋮---- func addKeyWithNamespace(ns string, keyType symbiotic.KeyType, id int, generate bool, force bool, privateKey string) error ⋮---- var err error ```` ## File: cmd/utils/keys/cmd.go ````go package keys ⋮---- import ( symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/spf13/cobra" ) ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/spf13/cobra" ⋮---- func NewKeysCmd() *cobra.Command ⋮---- var keysCmd = &cobra.Command{ Use: "keys", Short: "Keys tool", } ⋮---- type GlobalFlags struct { Path string Password string } ⋮---- type AddFlags struct { EvmNs bool RelayNs bool P2PNs bool KeyTag uint8 ChainID int16 PrivateKey string Generate bool Force bool } ⋮---- type RemoveFlags struct { EvmNs bool RelayNs bool P2PNs bool KeyTag uint8 ChainID int16 } ⋮---- type UpdateFlags struct { EvmNs bool RelayNs bool P2PNs bool KeyTag uint8 ChainID int16 PrivateKey string Force bool } ⋮---- var globalFlags GlobalFlags var addFlags AddFlags ⋮---- var removeFlags RemoveFlags var updateFlags UpdateFlags ⋮---- func initFlags() ```` ## File: cmd/utils/keys/print.go ````go package keys ⋮---- import ( "strconv" "github.com/pterm/pterm" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/entity" "github.com/spf13/cobra" ) ⋮---- "strconv" ⋮---- "github.com/pterm/pterm" ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/spf13/cobra" ⋮---- var printKeysCmd = &cobra.Command{ Use: "list", Short: "Print all keys", RunE: func(cmd *cobra.Command, args []string) error { var err error if globalFlags.Password == "" { globalFlags.Password, err = cmdhelpers.GetPassword() if err != nil { return err } } keyStore, err := keyprovider.NewKeystoreProvider(globalFlags.Path, globalFlags.Password) if err != nil { return err } aliases := keyStore.GetAliases() tableData := pterm.TableData{{"#", "Alias", "Key Tag (Symb Keys)", "Public Key"}} for i, alias := range aliases { ns, kType, id, err := keyprovider.AliasToKeyTypeId(alias) if err != nil { return err } pk, err := keyStore.GetPrivateKeyByNamespaceTypeId(ns, kType, id) if err != nil { return err } prettyPk, err := pk.PublicKey().OnChain().MarshalText() if err != nil { return err } tag := "-" // for other namespace no guarantees can be made about the key id size if ns == keyprovider.SYMBIOTIC_KEY_NAMESPACE { kTag, err := entity.KeyTagFromTypeAndId(kType, uint8(id)) if err != nil { return err } tag = kTag.String() } tableData = append(tableData, []string{ strconv.Itoa(i + 1), alias, tag, string(prettyPk), }) } return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render() }, } ⋮---- var err error ⋮---- // for other namespace no guarantees can be made about the key id size ```` ## File: cmd/utils/keys/remove.go ````go package keys ⋮---- import ( cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/go-errors/errors" "github.com/spf13/cobra" ) ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/go-errors/errors" "github.com/spf13/cobra" ⋮---- var removeKeyCmd = &cobra.Command{ Use: "remove", Short: "Remove key", RunE: func(cmd *cobra.Command, args []string) error { var err error if globalFlags.Password == "" { globalFlags.Password, err = cmdhelpers.GetPassword() if err != nil { return err } } keyStore, err := keyprovider.NewKeystoreProvider(globalFlags.Path, globalFlags.Password) if err != nil { return err } if removeFlags.EvmNs { if removeFlags.ChainID < 0 { return errors.New("chain ID is required for evm namespace, use --chain-id=0 for default key for all chains") } return keyStore.DeleteKeyByNamespaceTypeId(keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(removeFlags.ChainID), globalFlags.Password) } else if removeFlags.RelayNs { if removeFlags.KeyTag == uint8(symbiotic.KeyTypeInvalid) { return errors.New("key tag is required for relay namespace") } kt := symbiotic.KeyTag(removeFlags.KeyTag) if kt.Type() == symbiotic.KeyTypeInvalid { return errors.New("invalid key tag, type not supported") } keyId := kt & 0x0F return keyStore.DeleteKeyByNamespaceTypeId(keyprovider.SYMBIOTIC_KEY_NAMESPACE, kt.Type(), int(keyId), globalFlags.Password) } else if removeFlags.P2PNs { return keyStore.DeleteKeyByNamespaceTypeId(keyprovider.P2P_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, keyprovider.P2P_HOST_IDENTITY_KEY_ID, globalFlags.Password) } return errors.New("either --evm or --relay or --p2p must be specified") }, } ⋮---- var err error ```` ## File: cmd/utils/keys/update.go ````go package keys ⋮---- import ( "github.com/ethereum/go-ethereum/common" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/go-errors/errors" "github.com/spf13/cobra" ) ⋮---- "github.com/ethereum/go-ethereum/common" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/go-errors/errors" "github.com/spf13/cobra" ⋮---- var updateKeyCmd = &cobra.Command{ Use: "update", Short: "Update key", RunE: func(cmd *cobra.Command, args []string) error { var err error if globalFlags.Password == "" { globalFlags.Password, err = cmdhelpers.GetPassword() if err != nil { return err } } keyStore, err := keyprovider.NewKeystoreProvider(globalFlags.Path, globalFlags.Password) if err != nil { return err } if updateFlags.PrivateKey == "" { return errors.New("private key is required for update") } privKeyBytes := common.FromHex(updateFlags.PrivateKey) if updateFlags.EvmNs { if updateFlags.ChainID < 0 { return errors.New("chain ID is required for evm namespace, use --chain-id=0 for default key for all chains") } exists, err := keyStore.HasKeyByNamespaceTypeId(keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(updateFlags.ChainID)) if err != nil { return err } if !exists { return errors.New("key doesn't exist") } key, err := crypto.NewPrivateKey(symbiotic.KeyTypeEcdsaSecp256k1, privKeyBytes) if err != nil { return err } return keyStore.AddKeyByNamespaceTypeId(keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(updateFlags.ChainID), key, globalFlags.Password, true) } else if updateFlags.RelayNs { if updateFlags.KeyTag == uint8(symbiotic.KeyTypeInvalid) { return errors.New("key tag is required for relay namespace") } kt := symbiotic.KeyTag(updateFlags.KeyTag) if kt.Type() == symbiotic.KeyTypeInvalid { return errors.New("invalid key tag, type not supported") } keyId := kt & 0x0F exists, err := keyStore.HasKeyByNamespaceTypeId(keyprovider.SYMBIOTIC_KEY_NAMESPACE, kt.Type(), int(keyId)) if err != nil { return err } if !exists { return errors.New("key doesn't exist") } key, err := crypto.NewPrivateKey(kt.Type(), privKeyBytes) if err != nil { return err } return keyStore.AddKeyByNamespaceTypeId(keyprovider.SYMBIOTIC_KEY_NAMESPACE, kt.Type(), int(keyId), key, globalFlags.Password, true) } else if updateFlags.P2PNs { exists, err := keyStore.HasKeyByNamespaceTypeId(keyprovider.P2P_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, keyprovider.P2P_HOST_IDENTITY_KEY_ID) if err != nil { return err } if !exists { return errors.New("key doesn't exist") } key, err := crypto.NewPrivateKey(symbiotic.KeyTypeEcdsaSecp256k1, privKeyBytes) if err != nil { return err } return keyStore.AddKeyByNamespaceTypeId(keyprovider.P2P_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, keyprovider.P2P_HOST_IDENTITY_KEY_ID, key, globalFlags.Password, true) } return errors.New("either --evm or --relay or --p2p must be specified") }, } ⋮---- var err error ```` ## File: cmd/utils/network/cmd.go ````go package network ⋮---- import ( "context" "os" "os/signal" "syscall" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "context" "os" "os/signal" "syscall" ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" ⋮---- "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- func NewNetworkCmd() *cobra.Command ⋮---- var networkCmd = &cobra.Command{ Use: "network", Short: "Network tool", } ⋮---- type GlobalFlags struct { Chains []string DriverAddress string DriverChainId uint64 Epoch uint64 } ⋮---- type InfoFlags struct { Validators bool ValidatorsFull bool Addresses bool Settlement bool } ⋮---- type GenesisFlags struct { Json bool Commit bool Epoch int64 Output string Secrets cmdhelpers.SecretKeyMapFlag } ⋮---- var globalFlags GlobalFlags var infoFlags InfoFlags var genesisFlags GenesisFlags ⋮---- func initFlags() ⋮---- // signalContext returns a context that is canceled if either SIGTERM or SIGINT signal is received. func signalContext(ctx context.Context) context.Context ```` ## File: cmd/utils/network/genesis.go ````go package network ⋮---- import ( "os" "strconv" "time" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "os" "strconv" "time" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- var genesisCmd = &cobra.Command{ Use: "generate-genesis", Short: "Generate genesis validator set header", RunE: func(cmd *cobra.Command, args []string) error { ctx := signalContext(cmd.Context()) kp, err := keyprovider.NewSimpleKeystoreProvider() if err != nil { return err } evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, KeyProvider: kp, }) if err != nil { return err } if genesisFlags.Commit { privateKeyInput := pterm.DefaultInteractiveTextInput.WithMask("*") for _, chainId := range evmClient.GetChains() { secret, ok := genesisFlags.Secrets.Secrets[chainId] if !ok { secret, _ = privateKeyInput.Show("Enter private key for chain with ID: " + strconv.Itoa(int(chainId))) } pk, err := symbioticCrypto.NewPrivateKey(symbiotic.KeyTypeEcdsaSecp256k1, common.FromHex(secret)) if err != nil { return err } err = kp.AddKeyByNamespaceTypeId( keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(chainId), pk, ) if err != nil { return err } } } spinner := getSpinner("Fetching on-chain network config...") deriver, err := valsetDeriver.NewDeriver(evmClient) if err != nil { return errors.Errorf("failed to create deriver: %v", err) } currentOnchainEpoch := symbiotic.Epoch(0) if genesisFlags.Epoch >= 0 { currentOnchainEpoch = symbiotic.Epoch(genesisFlags.Epoch) } else { currentOnchainEpoch, err = evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } } captureTimestamp, err := evmClient.GetEpochStart(ctx, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get config: %w", err) } spinner.Success() spinner = getSpinner("Fetching on-chain validators data...") newValset, err := deriver.GetValidatorSet(ctx, currentOnchainEpoch, networkConfig) if err != nil { return errors.Errorf("failed to get validator set extra for epoch %d: %w", currentOnchainEpoch, err) } spinner.Success() spinner = getSpinner("Building header and extra data...") // header generation is clear now header, err := newValset.GetHeader() if err != nil { return errors.Errorf("failed to generate validator set header: %w", err) } aggregator, err := aggregator.NewAggregator(networkConfig.VerificationType, nil) if err != nil { return errors.Errorf("failed to create aggregator: %w", err) } // extra data generation is also clear but still in deriver extraData, err := aggregator.GenerateExtraData(newValset, networkConfig.RequiredKeyTags) if err != nil { return errors.Errorf("failed to generate extra data: %w", err) } spinner.Success() jsonData := printHeaderWithExtraDataToJSON(header, extraData) if !genesisFlags.Json { panels := pterm.Panels{ { {Data: pterm.DefaultBox.WithTitle("Validator Set Header").Sprint( printHeaderTable(header), )}, }, { {Data: pterm.DefaultBox.WithTitle("Extra Data").Sprint( printExtraDataTable(extraData), )}, }, } pterm.DefaultPanel.WithPanels(panels).Render() } else { pterm.Println(jsonData) } if genesisFlags.Output != "" { err = os.WriteFile(genesisFlags.Output, []byte(jsonData), 0600) if err != nil { return errors.Errorf("failed to write output file: %w", err) } pterm.Success.Println("Genesis data written to " + genesisFlags.Output) } if genesisFlags.Commit { for _, settlement := range networkConfig.Settlements { spinner = getSpinner("Setting genesis on " + settlement.Address.String()) txResult, err := evmClient.SetGenesis( ctx, settlement, header, extraData) if err != nil { spinner.Fail("Transaction failed: ", err) return errors.Errorf("failed to set genesis for network %d: %w", settlement.ChainId, err) } spinner.Success("Transaction hash: ", txResult.TxHash.String()) } } return nil }, } ⋮---- // header generation is clear now ⋮---- // extra data generation is also clear but still in deriver ⋮---- func getSpinner(text string) *pterm.SpinnerPrinter ```` ## File: cmd/utils/network/info.go ````go package network ⋮---- import ( "time" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/samber/lo" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ) ⋮---- "time" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/samber/lo" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ⋮---- var infoCmd = &cobra.Command{ Use: "info", Short: "Print network information", RunE: func(cmd *cobra.Command, args []string) error { var err error ctx := signalContext(cmd.Context()) kp, err := keyprovider.NewSimpleKeystoreProvider() if err != nil { return err } evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, KeyProvider: kp, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } if err != nil { return errors.Errorf("Failed to get evm client: %v", err) } deriver, err := valsetDeriver.NewDeriver(evmClient) if err != nil { return errors.Errorf("Failed to create deriver: %v", err) } epoch := symbiotic.Epoch(globalFlags.Epoch) if globalFlags.Epoch == 0 { epoch, err = evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("Failed to get current epoch: %w", err) } } captureTimestamp, err := evmClient.GetEpochStart(ctx, epoch) if err != nil { return errors.Errorf("Failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, epoch) if err != nil { return errors.Errorf("Failed to get config: %w", err) } epochDuration, err := evmClient.GetEpochDuration(ctx, epoch) if err != nil { return errors.Errorf("Failed to get epoch duration: %w", err) } valset, err := deriver.GetValidatorSet(ctx, epoch, networkConfig) if err != nil { return errors.Errorf("Failed to get validator set: %w", err) } // row with info and config panels := pterm.Panels{ { {Data: pterm.DefaultBox.WithTitle("Network info").Sprint( printNetworkInfo(epoch, captureTimestamp, &networkConfig, &valset), )}, {Data: pterm.DefaultBox.WithTitle("Network config").Sprint( printNetworkConfig(epochDuration, &networkConfig), )}, }, } // row with addresses [optional] if infoFlags.Addresses { panels = append(panels, []pterm.Panel{ {Data: pterm.DefaultBox.WithTitle("Addresses").Sprint( printAddresses(symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, &networkConfig), )}, }) } // row with settlements info if infoFlags.Settlement { settlementData := make([]settlementReplicaData, len(networkConfig.Settlements)) eg, egCtx := errgroup.WithContext(ctx) eg.SetLimit(5) for i, settlement := range networkConfig.Settlements { eg.Go(func() error { isCommitted, err := evmClient.IsValsetHeaderCommittedAt(egCtx, settlement, epoch) if err != nil { return errors.Errorf("Failed to get latest epoch: %w", err) } settlementData[i].IsCommitted = isCommitted if isCommitted { headerHash, err := evmClient.GetHeaderHashAt(egCtx, settlement, epoch) if err != nil { return errors.Errorf("Failed to get header hash: %w", err) } settlementData[i].HeaderHash = headerHash } lastCommittedHeaderEpoch, err := evmClient.GetLastCommittedHeaderEpoch(ctx, settlement) if err != nil { return errors.Errorf("Failed to get last committed header epoch: %w", err) } settlementData[i].LastCommittedHeaderEpoch = uint64(lastCommittedHeaderEpoch) allEpochsFromZero := lo.RepeatBy(int(epoch+1), func(i int) symbiotic.Epoch { return symbiotic.Epoch(i) }) commitmentResults, err := evmClient.IsValsetHeaderCommittedAtEpochs(egCtx, settlement, allEpochsFromZero) if err != nil { return errors.Errorf("Failed to check epoch commitments: %w", err) } settlementData[i].MissedEpochs = uint64(lo.CountBy(commitmentResults, func(committed bool) bool { return !committed })) return nil }) } if err := eg.Wait(); err != nil { return err } header, err := valset.GetHeader() if err != nil { return errors.Errorf("Failed to get header: %w", err) } panels = append(panels, []pterm.Panel{ {Data: pterm.DefaultBox.WithTitle("Settlement").Sprint( printSettlementData(header, networkConfig, settlementData), )}, }) } // row with validators [optional] if infoFlags.ValidatorsFull { panels = append(panels, []pterm.Panel{ {Data: pterm.DefaultBox.WithTitle("Validators").Sprint( printValidatorsTree(&valset), )}, }) } else if infoFlags.Validators { panels = append(panels, []pterm.Panel{ {Data: pterm.DefaultBox.WithTitle("Validators").Sprint( printValidatorsTable(&valset), )}, }) } pterm.DefaultPanel.WithPanels(panels).Render() return nil }, } ⋮---- var err error ⋮---- // row with info and config ⋮---- // row with addresses [optional] ⋮---- // row with settlements info ⋮---- // row with validators [optional] ```` ## File: cmd/utils/network/printers.go ````go package network ⋮---- import ( "encoding/json" "fmt" "math/big" "strconv" "strings" "time" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/ethereum/go-ethereum/common" "github.com/pterm/pterm" "github.com/pterm/pterm/putils" "github.com/samber/lo" ) ⋮---- "encoding/json" "fmt" "math/big" "strconv" "strings" "time" ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/pterm/pterm" "github.com/pterm/pterm/putils" "github.com/samber/lo" ⋮---- type settlementReplicaData struct { IsCommitted bool HeaderHash common.Hash MissedEpochs uint64 LastCommittedHeaderEpoch uint64 } ⋮---- func printAddresses(driver symbiotic.CrossChainAddress, networkConfig *symbiotic.NetworkConfig) string ⋮---- func printNetworkConfig(epochDuration uint64, networkConfig *symbiotic.NetworkConfig) string ⋮---- func printNetworkInfo(epoch symbiotic.Epoch, epochStart symbiotic.Timestamp, networkConfig *symbiotic.NetworkConfig, valset *symbiotic.ValidatorSet) string ⋮---- func printValidatorsTree(valset *symbiotic.ValidatorSet) string ⋮---- // Render the tree structure using the default tree printer. ⋮---- func printValidatorsTable(valset *symbiotic.ValidatorSet) string ⋮---- func printHeaderTable(header symbiotic.ValidatorSetHeader) string ⋮---- func printExtraDataTable(extraData symbiotic.ExtraDataList) string ⋮---- func printHeaderWithExtraDataToJSON(validatorSetHeader symbiotic.ValidatorSetHeader, extraDataList symbiotic.ExtraDataList) string ⋮---- type jsonHeader struct { Version uint8 `json:"version"` ValidatorsSszMRoot string `json:"validatorsSszMRoot"` // hex string Epoch uint64 `json:"epoch"` RequiredKeyTag uint8 `json:"requiredKeyTag"` CaptureTimestamp uint64 `json:"captureTimestamp"` QuorumThreshold *big.Int `json:"quorumThreshold"` TotalVotingPower *big.Int `json:"totalVotingPower"` } ⋮---- ValidatorsSszMRoot string `json:"validatorsSszMRoot"` // hex string ⋮---- type jsonExtraData struct { Key string `json:"key"` // hex string Value string `json:"value"` // hex string } ⋮---- Key string `json:"key"` // hex string Value string `json:"value"` // hex string ⋮---- type jsonValidatorSetHeaderWithExtraData struct { Header jsonHeader `json:"header"` ExtraDataList []jsonExtraData `json:"extraData"` } ⋮---- func printSettlementData( valsetHeader symbiotic.ValidatorSetHeader, networkConfig symbiotic.NetworkConfig, settlementData []settlementReplicaData, ) string ```` ## File: cmd/utils/operator/cmd.go ````go package operator ⋮---- import ( "context" "os" "os/signal" "syscall" "github.com/go-errors/errors" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "context" "os" "os/signal" "syscall" ⋮---- "github.com/go-errors/errors" ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- func NewOperatorCmd() *cobra.Command ⋮---- var operatorCmd = &cobra.Command{ Use: "operator", Short: "Operator tool", } ⋮---- type GlobalFlags struct { Chains []string DriverAddress string DriverChainId uint64 VotingProviderChainId uint64 } ⋮---- type InfoFlags struct { Epoch uint64 Full bool Path string Password string KeyTag uint8 } ⋮---- type RegisterKeyFlags struct { Secrets cmdhelpers.SecretKeyMapFlag Path string Password string KeyTag uint8 } ⋮---- type InvalidateOldSignaturesFlags struct { Secrets cmdhelpers.SecretKeyMapFlag } ⋮---- type RegisterOperatorWithSignatureFlags struct { Secrets cmdhelpers.SecretKeyMapFlag } ⋮---- type UnregisterOperatorWithSignatureFlags struct { Secrets cmdhelpers.SecretKeyMapFlag } ⋮---- type RegisterOperatorFlags struct { Secrets cmdhelpers.SecretKeyMapFlag } ⋮---- type UnregisterOperatorFlags struct { Secrets cmdhelpers.SecretKeyMapFlag } ⋮---- var globalFlags GlobalFlags var infoFlags InfoFlags var registerKeyFlags RegisterKeyFlags var invalidateOldSignaturesFlags InvalidateOldSignaturesFlags var registerOperatorWithSignatureFlags RegisterOperatorWithSignatureFlags var unregisterOperatorWithSignatureFlags UnregisterOperatorWithSignatureFlags var registerOperatorFlags RegisterOperatorFlags var unregisterOperatorFlags UnregisterOperatorFlags ⋮---- func initFlags() ⋮---- // signalContext returns a context that is canceled if either SIGTERM or SIGINT signal is received. func signalContext(ctx context.Context) context.Context ⋮---- // findVotingPowerProviderByChainId finds a voting power provider by chain id from the list func findVotingPowerProviderByChainId(providers []symbiotic.CrossChainAddress, chainId uint64) (symbiotic.CrossChainAddress, error) ```` ## File: cmd/utils/operator/info.go ````go package operator ⋮---- import ( "time" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/pterm/pterm/putils" "github.com/spf13/cobra" ) ⋮---- "time" ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/pterm/pterm/putils" "github.com/spf13/cobra" ⋮---- var infoCmd = &cobra.Command{ Use: "info", Short: "Print operator information", RunE: func(cmd *cobra.Command, args []string) error { ctx := signalContext(cmd.Context()) kp, err := keyprovider.NewSimpleKeystoreProvider() if err != nil { return err } evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, KeyProvider: kp, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } if infoFlags.Password == "" { infoFlags.Password, err = cmdhelpers.GetPassword() if err != nil { return errors.Errorf("failed to get password: %w", err) } } if infoFlags.Epoch == 0 { epoch, err := evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } infoFlags.Epoch = uint64(epoch) } captureTimestamp, err := evmClient.GetEpochStart(ctx, symbiotic.Epoch(infoFlags.Epoch)) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, symbiotic.Epoch(infoFlags.Epoch)) if err != nil { return errors.Errorf("failed to get config: %w", err) } epoch, err := evmClient.GetLastCommittedHeaderEpoch(ctx, networkConfig.Settlements[0]) if err != nil { return errors.Errorf("failed to get valset header: %w", err) } deriver, err := valsetDeriver.NewDeriver(evmClient) if err != nil { return errors.Errorf("failed to create valset deriver: %w", err) } valset, err := deriver.GetValidatorSet(ctx, epoch, networkConfig) if err != nil { return errors.Errorf("failed to get validator set: %w", err) } keyStore, err := keyprovider.NewKeystoreProvider(infoFlags.Path, infoFlags.Password) if err != nil { return err } kt := symbiotic.KeyTag(infoFlags.KeyTag) pk, err := keyStore.GetPrivateKey(kt) if err != nil { return err } validator, found := valset.FindValidatorByKey(kt, pk.PublicKey().OnChain()) if !found { return errors.Errorf("validator not found for key: %d %s", kt, common.Bytes2Hex(pk.PublicKey().Raw())) } leveledList := pterm.LeveledList{} leveledList = cmdhelpers.PrintTreeValidator(leveledList, validator, valset.GetTotalActiveVotingPower().Int) text, _ := pterm.DefaultTree.WithRoot(putils.TreeFromLeveledList(leveledList)).Srender() panels := pterm.Panels{{{Data: pterm.DefaultBox.WithTitle("Operator info").Sprint(text)}}} pterm.DefaultPanel.WithPanels(panels).Render() return nil }, } ```` ## File: cmd/utils/operator/invalidate_old_signatures.go ````go package operator ⋮---- import ( "strconv" "time" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "strconv" "time" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- var invalidateOldSignaturesCmd = &cobra.Command{ Use: "invalidate-old-signatures", Short: "Invalidate old signatures for operator", RunE: func(cmd *cobra.Command, args []string) error { ctx := signalContext(cmd.Context()) kp, err := keyprovider.NewSimpleKeystoreProvider() if err != nil { return err } evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, KeyProvider: kp, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } currentOnChainEpoch, err := evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } captureTimestamp, err := evmClient.GetEpochStart(ctx, currentOnChainEpoch) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, currentOnChainEpoch) if err != nil { return errors.Errorf("failed to get config: %w", err) } if len(networkConfig.VotingPowerProviders) == 0 { return errors.New("no voting power providers found in network config") } votingPowerProvider, err := findVotingPowerProviderByChainId(networkConfig.VotingPowerProviders, globalFlags.VotingProviderChainId) if err != nil { return err } // Load the operator key for the voting power provider's chain privateKeyInput := pterm.DefaultInteractiveTextInput.WithMask("*") secret, ok := invalidateOldSignaturesFlags.Secrets.Secrets[votingPowerProvider.ChainId] if !ok { secret, _ = privateKeyInput.Show("Enter operator private key for chain with ID: " + strconv.Itoa(int(votingPowerProvider.ChainId))) } pk, err := symbioticCrypto.NewPrivateKey(symbiotic.KeyTypeEcdsaSecp256k1, common.FromHex(secret)) if err != nil { return err } err = kp.AddKeyByNamespaceTypeId( keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(votingPowerProvider.ChainId), pk, ) if err != nil { return err } txResult, err := evmClient.InvalidateOldSignatures(ctx, votingPowerProvider) if err != nil { return errors.Errorf("failed to invalidate old signatures: %w", err) } pterm.Success.Println("Old signatures invalidated! TxHash:", txResult.TxHash.String()) return nil }, } ⋮---- // Load the operator key for the voting power provider's chain ```` ## File: cmd/utils/operator/register_key.go ````go package operator ⋮---- import ( "log/slog" "strconv" "time" "github.com/ethereum/go-ethereum/common/math" cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/bls12381Bn254" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "log/slog" "strconv" "time" ⋮---- "github.com/ethereum/go-ethereum/common/math" ⋮---- cmdhelpers "github.com/symbioticfi/relay/cmd/utils/cmd-helpers" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/bls12381Bn254" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- var registerKeyCmd = &cobra.Command{ Use: "register-key", Short: "Register operator key in key registry", RunE: func(cmd *cobra.Command, args []string) error { var err error ctx := signalContext(cmd.Context()) kp, err := keyprovider.NewSimpleKeystoreProvider() if err != nil { return err } evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, KeyProvider: kp, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } // TODO multiple chains key registration support if len(evmClient.GetChains()) != 1 { return errors.New("only single chain is supported") } chainId := evmClient.GetChains()[0] // duplicate from genesis privateKeyInput := pterm.DefaultInteractiveTextInput.WithMask("*") secret, ok := registerKeyFlags.Secrets.Secrets[chainId] if !ok { secret, _ = privateKeyInput.Show("Enter private key for chain with ID: " + strconv.Itoa(int(chainId))) } pk, err := symbioticCrypto.NewPrivateKey(symbiotic.KeyTypeEcdsaSecp256k1, common.FromHex(secret)) if err != nil { return err } err = kp.AddKeyByNamespaceTypeId( keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(chainId), pk, ) if err != nil { return err } if registerKeyFlags.Password == "" { registerKeyFlags.Password, err = cmdhelpers.GetPassword() if err != nil { return err } } keyStore, err := keyprovider.NewKeystoreProvider(registerKeyFlags.Path, registerKeyFlags.Password) if err != nil { return err } kt := symbiotic.KeyTag(registerKeyFlags.KeyTag) pk, err = keyStore.GetPrivateKey(kt) if err != nil { return errors.Errorf("failed to get private key for keyTag %v from keystore: %w", kt, err) } currentOnchainEpoch, err := evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } captureTimestamp, err := evmClient.GetEpochStart(ctx, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get config: %w", err) } eip712Domain, err := evmClient.GetEip712Domain(ctx, networkConfig.KeysProvider) if err != nil { return errors.Errorf("failed to get eip712 domain: %w", err) } ecdsaPk, err := crypto.HexToECDSA(secret) if err != nil { return err } operator := crypto.PubkeyToAddress(ecdsaPk.PublicKey) key := pk.PublicKey().OnChain() commitmentData, err := keyCommitmentData(eip712Domain, operator, key) if err != nil { return errors.Errorf("failed to get commitment data: %w", err) } signature, _, err := pk.Sign(commitmentData) if err != nil { return errors.Errorf("failed to sign commitment data: %w", err) } // For ECDSA signatures, we need to adjust the recovery ID // Go's crypto.Sign() returns V as 0 or 1, but Ethereum expects 27 or 28 if kt.Type() == symbiotic.KeyTypeEcdsaSecp256k1 && len(signature) == 65 { // Convert recovery ID from 0/1 to 27/28 for Ethereum signature[64] += 27 } var extraData []byte switch kt.Type() { case symbiotic.KeyTypeBlsBn254: blsKey, err := blsBn254.FromRaw(pk.PublicKey().Raw()) if err != nil { return errors.Errorf("failed to parse BLS public key: %w", err) } rawByte := blsKey.G2().RawBytes() extraData = rawByte[:] case symbiotic.KeyTypeBls12381Bn254: blsKey, err := bls12381Bn254.FromRaw(pk.PublicKey().Raw()) if err != nil { return errors.Errorf("failed to parse BLS public key: %w", err) } rawByte := blsKey.G2().RawBytes() extraData = rawByte[:] case symbiotic.KeyTypeEcdsaSecp256k1: // no extra data needed for ECDSA keys case symbiotic.KeyTypeInvalid: return errors.New("invalid key type") } // Use the adjusted signature for registration txResult, err := evmClient.RegisterKey(ctx, networkConfig.KeysProvider, kt, key, signature, extraData) if err != nil { return errors.Errorf("failed to register operator: %w", err) } slog.InfoContext(ctx, "Operator Key registered!", "txHash", txResult.TxHash.String(), "key-tag", kt) return nil }, } ⋮---- var err error ⋮---- // TODO multiple chains key registration support ⋮---- // duplicate from genesis ⋮---- // For ECDSA signatures, we need to adjust the recovery ID // Go's crypto.Sign() returns V as 0 or 1, but Ethereum expects 27 or 28 ⋮---- // Convert recovery ID from 0/1 to 27/28 for Ethereum ⋮---- var extraData []byte ⋮---- // no extra data needed for ECDSA keys ⋮---- // Use the adjusted signature for registration ⋮---- func keyCommitmentData(eip712Domain symbiotic.Eip712Domain, operator common.Address, keyBytes []byte) ([]byte, error) ```` ## File: cmd/utils/operator/register_operator.go ````go package operator ⋮---- import ( "strconv" "time" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "strconv" "time" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- var registerOperatorCmd = &cobra.Command{ Use: "register-operator", Short: "Register operator on-chain via VotingPowerProvider", RunE: func(cmd *cobra.Command, args []string) error { ctx := signalContext(cmd.Context()) kp, err := keyprovider.NewSimpleKeystoreProvider() if err != nil { return err } evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, KeyProvider: kp, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } currentOnchainEpoch, err := evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } captureTimestamp, err := evmClient.GetEpochStart(ctx, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get config: %w", err) } if len(networkConfig.VotingPowerProviders) == 0 { return errors.New("no voting power providers found in network config") } votingPowerProvider, err := findVotingPowerProviderByChainId(networkConfig.VotingPowerProviders, globalFlags.VotingProviderChainId) if err != nil { return err } // Load the operator key for the voting power provider's chain privateKeyInput := pterm.DefaultInteractiveTextInput.WithMask("*") secret, ok := registerOperatorFlags.Secrets.Secrets[votingPowerProvider.ChainId] if !ok { secret, _ = privateKeyInput.Show("Enter operator private key for chain with ID: " + strconv.Itoa(int(votingPowerProvider.ChainId))) } pk, err := symbioticCrypto.NewPrivateKey(symbiotic.KeyTypeEcdsaSecp256k1, common.FromHex(secret)) if err != nil { return err } err = kp.AddKeyByNamespaceTypeId( keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(votingPowerProvider.ChainId), pk, ) if err != nil { return err } txResult, err := evmClient.RegisterOperatorVotingPowerProvider(ctx, votingPowerProvider) if err != nil { return errors.Errorf("failed to register operator: %w", err) } pterm.Success.Println("Operator registered! TxHash:", txResult.TxHash.String()) return nil }, } ⋮---- // Load the operator key for the voting power provider's chain ```` ## File: cmd/utils/operator/register_with_signature.go ````go package operator ⋮---- import ( "strconv" "time" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "strconv" "time" ⋮---- "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- var registerOperatorWithSignatureCmd = &cobra.Command{ Use: "register-operator-with-signature", Short: "Generate EIP-712 signature for operator registration", RunE: func(cmd *cobra.Command, args []string) error { ctx := signalContext(cmd.Context()) evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } privateKeyInput := pterm.DefaultInteractiveTextInput.WithMask("*") secret, ok := registerOperatorWithSignatureFlags.Secrets.Secrets[globalFlags.DriverChainId] if !ok { secret, _ = privateKeyInput.Show("Enter operator private key for chain with ID: " + strconv.Itoa(int(globalFlags.DriverChainId))) } ecdsaPk, err := crypto.HexToECDSA(secret) if err != nil { return errors.Errorf("failed to parse private key: %w", err) } operator := crypto.PubkeyToAddress(ecdsaPk.PublicKey) currentOnchainEpoch, err := evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } captureTimestamp, err := evmClient.GetEpochStart(ctx, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get config: %w", err) } // Find VotingPowerProvider by chain ID if len(networkConfig.VotingPowerProviders) == 0 { return errors.New("no voting power providers found in network config") } votingPowerProvider, err := findVotingPowerProviderByChainId(networkConfig.VotingPowerProviders, globalFlags.VotingProviderChainId) if err != nil { return err } eip712Domain, err := evmClient.GetVotingPowerProviderEip712Domain(ctx, votingPowerProvider) if err != nil { return errors.Errorf("failed to get eip712 domain: %w", err) } nonce, err := evmClient.GetOperatorNonce(ctx, votingPowerProvider, operator) if err != nil { return errors.Errorf("failed to get operator nonce: %w", err) } // Build EIP-712 typed data for RegisterOperator typedData := apitypes.TypedData{ Types: apitypes.Types{ "EIP712Domain": []apitypes.Type{ {Name: "name", Type: "string"}, {Name: "version", Type: "string"}, {Name: "chainId", Type: "uint256"}, {Name: "verifyingContract", Type: "address"}, }, "RegisterOperator": []apitypes.Type{ {Name: "operator", Type: "address"}, {Name: "nonce", Type: "uint256"}, }, }, PrimaryType: "RegisterOperator", Domain: apitypes.TypedDataDomain{ Name: eip712Domain.Name, Version: eip712Domain.Version, ChainId: (*math.HexOrDecimal256)(eip712Domain.ChainId), VerifyingContract: eip712Domain.VerifyingContract.Hex(), }, Message: apitypes.TypedDataMessage{ "operator": operator.Hex(), "nonce": (*math.HexOrDecimal256)(nonce), }, } typedDataHash, _, err := apitypes.TypedDataAndHash(typedData) if err != nil { return errors.Errorf("failed to hash typed data: %w", err) } signature, err := crypto.Sign(typedDataHash, ecdsaPk) if err != nil { return errors.Errorf("failed to sign: %w", err) } // Ethereum expects recovery ID to be 27 or 28, not 0 or 1 if len(signature) == 65 { signature[64] += 27 } pterm.Success.Printf("0x%x\n", signature) return nil }, } ⋮---- // Find VotingPowerProvider by chain ID ⋮---- // Build EIP-712 typed data for RegisterOperator ⋮---- // Ethereum expects recovery ID to be 27 or 28, not 0 or 1 ```` ## File: cmd/utils/operator/unregister_operator.go ````go package operator ⋮---- import ( "strconv" "time" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "strconv" "time" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- var unregisterOperatorCmd = &cobra.Command{ Use: "unregister-operator", Short: "Unregister operator on-chain via VotingPowerProvider", RunE: func(cmd *cobra.Command, args []string) error { ctx := signalContext(cmd.Context()) kp, err := keyprovider.NewSimpleKeystoreProvider() if err != nil { return err } evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, KeyProvider: kp, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } currentOnchainEpoch, err := evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } captureTimestamp, err := evmClient.GetEpochStart(ctx, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get config: %w", err) } if len(networkConfig.VotingPowerProviders) == 0 { return errors.New("no voting power providers found in network config") } votingPowerProvider, err := findVotingPowerProviderByChainId(networkConfig.VotingPowerProviders, globalFlags.VotingProviderChainId) if err != nil { return err } // Load the operator key for the voting power provider's chain privateKeyInput := pterm.DefaultInteractiveTextInput.WithMask("*") secret, ok := unregisterOperatorFlags.Secrets.Secrets[votingPowerProvider.ChainId] if !ok { secret, _ = privateKeyInput.Show("Enter operator private key for chain with ID: " + strconv.Itoa(int(votingPowerProvider.ChainId))) } pk, err := symbioticCrypto.NewPrivateKey(symbiotic.KeyTypeEcdsaSecp256k1, common.FromHex(secret)) if err != nil { return err } err = kp.AddKeyByNamespaceTypeId( keyprovider.EVM_KEY_NAMESPACE, symbiotic.KeyTypeEcdsaSecp256k1, int(votingPowerProvider.ChainId), pk, ) if err != nil { return err } txResult, err := evmClient.UnregisterOperatorVotingPowerProvider(ctx, votingPowerProvider) if err != nil { return errors.Errorf("failed to unregister operator: %w", err) } pterm.Success.Println("Operator unregistered! TxHash:", txResult.TxHash.String()) return nil }, } ⋮---- // Load the operator key for the voting power provider's chain ```` ## File: cmd/utils/operator/unregister_with_signature.go ````go package operator ⋮---- import ( "strconv" "time" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "strconv" "time" ⋮---- "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- var unregisterOperatorWithSignatureCmd = &cobra.Command{ Use: "unregister-operator-with-signature", Short: "Generate EIP-712 signature for operator unregistration", RunE: func(cmd *cobra.Command, args []string) error { ctx := signalContext(cmd.Context()) evmClient, err := evm.NewEvmClient(ctx, evm.Config{ ChainURLs: globalFlags.Chains, DriverAddress: symbiotic.CrossChainAddress{ ChainId: globalFlags.DriverChainId, Address: common.HexToAddress(globalFlags.DriverAddress), }, RequestTimeout: 5 * time.Second, Metrics: metrics.New(metrics.Config{}), }) if err != nil { return err } privateKeyInput := pterm.DefaultInteractiveTextInput.WithMask("*") secret, ok := unregisterOperatorWithSignatureFlags.Secrets.Secrets[globalFlags.DriverChainId] if !ok { secret, _ = privateKeyInput.Show("Enter operator private key for chain with ID: " + strconv.Itoa(int(globalFlags.DriverChainId))) } ecdsaPk, err := crypto.HexToECDSA(secret) if err != nil { return errors.Errorf("failed to parse private key: %w", err) } operator := crypto.PubkeyToAddress(ecdsaPk.PublicKey) currentOnchainEpoch, err := evmClient.GetCurrentEpoch(ctx) if err != nil { return errors.Errorf("failed to get current epoch: %w", err) } captureTimestamp, err := evmClient.GetEpochStart(ctx, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get capture timestamp: %w", err) } networkConfig, err := evmClient.GetConfig(ctx, captureTimestamp, currentOnchainEpoch) if err != nil { return errors.Errorf("failed to get config: %w", err) } // Find VotingPowerProvider by chain ID if len(networkConfig.VotingPowerProviders) == 0 { return errors.New("no voting power providers found in network config") } votingPowerProvider, err := findVotingPowerProviderByChainId(networkConfig.VotingPowerProviders, globalFlags.VotingProviderChainId) if err != nil { return err } eip712Domain, err := evmClient.GetVotingPowerProviderEip712Domain(ctx, votingPowerProvider) if err != nil { return errors.Errorf("failed to get eip712 domain: %w", err) } nonce, err := evmClient.GetOperatorNonce(ctx, votingPowerProvider, operator) if err != nil { return errors.Errorf("failed to get operator nonce: %w", err) } // Build EIP-712 typed data for UnregisterOperator typedData := apitypes.TypedData{ Types: apitypes.Types{ "EIP712Domain": []apitypes.Type{ {Name: "name", Type: "string"}, {Name: "version", Type: "string"}, {Name: "chainId", Type: "uint256"}, {Name: "verifyingContract", Type: "address"}, }, "UnregisterOperator": []apitypes.Type{ {Name: "operator", Type: "address"}, {Name: "nonce", Type: "uint256"}, }, }, PrimaryType: "UnregisterOperator", Domain: apitypes.TypedDataDomain{ Name: eip712Domain.Name, Version: eip712Domain.Version, ChainId: (*math.HexOrDecimal256)(eip712Domain.ChainId), VerifyingContract: eip712Domain.VerifyingContract.Hex(), }, Message: apitypes.TypedDataMessage{ "operator": operator.Hex(), "nonce": (*math.HexOrDecimal256)(nonce), }, } typedDataHash, _, err := apitypes.TypedDataAndHash(typedData) if err != nil { return errors.Errorf("failed to hash typed data: %w", err) } signature, err := crypto.Sign(typedDataHash, ecdsaPk) if err != nil { return errors.Errorf("failed to sign: %w", err) } // Ethereum expects recovery ID to be 27 or 28, not 0 or 1 if len(signature) == 65 { signature[64] += 27 } pterm.Success.Printf("0x%x\n", signature) return nil }, } ⋮---- // Find VotingPowerProvider by chain ID ⋮---- // Build EIP-712 typed data for UnregisterOperator ⋮---- // Ethereum expects recovery ID to be 27 or 28, not 0 or 1 ```` ## File: cmd/utils/root/root.go ````go package root ⋮---- import ( "runtime" "github.com/symbioticfi/relay/cmd/utils/keys" "github.com/symbioticfi/relay/cmd/utils/network" "github.com/symbioticfi/relay/cmd/utils/operator" "github.com/symbioticfi/relay/pkg/log" "github.com/pterm/pterm" "github.com/spf13/cobra" ) ⋮---- "runtime" ⋮---- "github.com/symbioticfi/relay/cmd/utils/keys" "github.com/symbioticfi/relay/cmd/utils/network" "github.com/symbioticfi/relay/cmd/utils/operator" "github.com/symbioticfi/relay/pkg/log" ⋮---- "github.com/pterm/pterm" "github.com/spf13/cobra" ⋮---- type config struct { logLevel string logMode string } ⋮---- var Version = "local" var BuildTime = "unknown" ⋮---- var cfg config ⋮---- func NewRootCommand() *cobra.Command ⋮---- var rootCmd = &cobra.Command{ Use: "utils", Short: "Utils tool", PreRun: func(cmd *cobra.Command, args []string) { log.Init(cfg.logLevel, cfg.logMode) }, } ⋮---- var versionCommand = &cobra.Command{ Use: "version", Short: "Print the version of the utils tool", Run: func(cmd *cobra.Command, args []string) { pterm.Info.Println("Utils tool version:", Version) pterm.Info.Println("Go version:", runtime.Version()) pterm.Info.Println("OS/Arch:", runtime.GOOS+"/"+runtime.GOARCH) pterm.Info.Println("Build time:", BuildTime) }, } ```` ## File: cmd/utils/main.go ````go package main ⋮---- import ( "os" "github.com/pterm/pterm" "github.com/symbioticfi/relay/cmd/utils/root" ) ⋮---- "os" ⋮---- "github.com/pterm/pterm" "github.com/symbioticfi/relay/cmd/utils/root" ⋮---- func main() ```` ## File: docs/api/v1/api.swagger.json ````json { "swagger": "2.0", "info": { "title": "v1/api.proto", "version": "version not set" }, "tags": [ { "name": "SymbioticAPIService" } ], "consumes": [ "application/json" ], "produces": [ "application/json" ], "paths": { "/v1/aggregation/proof/{requestId}": { "get": { "summary": "Get aggregation proof", "operationId": "SymbioticAPIService_GetAggregationProof", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetAggregationProofResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "requestId", "in": "path", "required": true, "type": "string" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/aggregation/proofs/epoch/{epoch}": { "get": { "summary": "Get aggregation proofs by epoch", "operationId": "SymbioticAPIService_GetAggregationProofsByEpoch", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetAggregationProofsByEpochResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number", "in": "path", "required": true, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/aggregation/status/{requestId}": { "get": { "summary": "Get aggregation status, can be sent only to aggregator nodes", "operationId": "SymbioticAPIService_GetAggregationStatus", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetAggregationStatusResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "requestId", "in": "path", "required": true, "type": "string" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/committed/all": { "get": { "summary": "Get last committed epochs for all settlement chains", "operationId": "SymbioticAPIService_GetLastAllCommitted", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetLastAllCommittedResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "tags": [ "SymbioticAPIService" ] } }, "/v1/committed/chain/{settlementChainId}": { "get": { "summary": "Get last committed epoch for a specific settlement chain", "operationId": "SymbioticAPIService_GetLastCommitted", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetLastCommittedResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "settlementChainId", "description": "Settlement chain ID", "in": "path", "required": true, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/epoch/current": { "get": { "summary": "Get current epoch", "operationId": "SymbioticAPIService_GetCurrentEpoch", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetCurrentEpochResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "tags": [ "SymbioticAPIService" ] } }, "/v1/sign": { "post": { "summary": "Sign a message", "operationId": "SymbioticAPIService_SignMessage", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/SignMessageResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/SignMessageRequest" } } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/signature-request-ids/epoch/{epoch}": { "get": { "summary": "Get all signature request IDs by epoch", "operationId": "SymbioticAPIService_GetSignatureRequestIDsByEpoch", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetSignatureRequestIDsByEpochResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number", "in": "path", "required": true, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/signature-request/{requestId}": { "get": { "summary": "Get signature request by request id", "operationId": "SymbioticAPIService_GetSignatureRequest", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetSignatureRequestResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "requestId", "in": "path", "required": true, "type": "string" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/signature-requests/epoch/{epoch}": { "get": { "summary": "Get all signature requests by epoch", "operationId": "SymbioticAPIService_GetSignatureRequestsByEpoch", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetSignatureRequestsByEpochResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number", "in": "path", "required": true, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/signatures/epoch/{epoch}": { "get": { "summary": "Get signature by epoch", "operationId": "SymbioticAPIService_GetSignaturesByEpoch", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetSignaturesByEpochResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number", "in": "path", "required": true, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/signatures/{requestId}": { "get": { "summary": "Get signature by request id", "operationId": "SymbioticAPIService_GetSignatures", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetSignaturesResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "requestId", "in": "path", "required": true, "type": "string" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/stream/proofs": { "get": { "summary": "Stream aggregation proofs in real-time. If start_epoch is provided, sends historical data first", "operationId": "SymbioticAPIService_ListenProofs", "responses": { "200": { "description": "A successful response.(streaming responses)", "schema": { "type": "object", "properties": { "result": { "$ref": "#/definitions/ListenProofsResponse" }, "error": { "$ref": "#/definitions/Status" } }, "title": "Stream result of ListenProofsResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "startEpoch", "description": "Optional: start epoch. If provided, stream will first send all historical proofs starting from this epoch, then continue with real-time updates\nIf not provided, only proofs generated after stream creation will be sent", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/stream/signatures": { "get": { "summary": "Stream signatures in real-time. If start_epoch is provided, sends historical data first", "operationId": "SymbioticAPIService_ListenSignatures", "responses": { "200": { "description": "A successful response.(streaming responses)", "schema": { "type": "object", "properties": { "result": { "$ref": "#/definitions/ListenSignaturesResponse" }, "error": { "$ref": "#/definitions/Status" } }, "title": "Stream result of ListenSignaturesResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "startEpoch", "description": "Optional: start epoch. If provided, stream will first send all historical signatures starting from this epoch, then continue with real-time updates\nIf not provided, only signatures generated after stream creation will be sent", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/stream/validator-set": { "get": { "summary": "Stream validator set changes in real-time. If start_epoch is provided, sends historical data first", "operationId": "SymbioticAPIService_ListenValidatorSet", "responses": { "200": { "description": "A successful response.(streaming responses)", "schema": { "type": "object", "properties": { "result": { "$ref": "#/definitions/ListenValidatorSetResponse" }, "error": { "$ref": "#/definitions/Status" } }, "title": "Stream result of ListenValidatorSetResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "startEpoch", "description": "Optional: start epoch. If provided, stream will first send all historical validator sets starting from this epoch, then continue with real-time updates\nIf not provided, only validator sets generated after stream creation will be sent", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/validator-set": { "get": { "summary": "Get current validator set", "operationId": "SymbioticAPIService_GetValidatorSet", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetValidatorSetResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number (optional, if not provided current epoch will be used)", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/validator-set/header": { "get": { "summary": "Get validator set header", "operationId": "SymbioticAPIService_GetValidatorSetHeader", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetValidatorSetHeaderResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number (optional, if not provided current epoch will be used)", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/validator-set/metadata": { "get": { "summary": "Get validator set metadata like extra data and request id to fetch aggregation and signature requests", "operationId": "SymbioticAPIService_GetValidatorSetMetadata", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetValidatorSetMetadataResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number (optional, if not provided current epoch will be used)", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/validator/address/{address}": { "get": { "summary": "Get validator by address", "operationId": "SymbioticAPIService_GetValidatorByAddress", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetValidatorByAddressResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "address", "description": "Validator address (required)", "in": "path", "required": true, "type": "string" }, { "name": "epoch", "description": "Epoch number (optional, if not provided current epoch will be used)", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/validator/key/{keyTag}/{onChainKey}": { "get": { "summary": "Get validator by key", "operationId": "SymbioticAPIService_GetValidatorByKey", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetValidatorByKeyResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "keyTag", "description": "Validator key tag (required)", "in": "path", "required": true, "type": "integer", "format": "int64" }, { "name": "onChainKey", "description": "Validator on chain (public) key (required)", "in": "path", "required": true, "type": "string", "format": "byte" }, { "name": "epoch", "description": "Epoch number (optional, if not provided current epoch will be used)", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } }, "/v1/validator/local": { "get": { "summary": "Get local validator", "operationId": "SymbioticAPIService_GetLocalValidator", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": "#/definitions/GetLocalValidatorResponse" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "#/definitions/Status" } } }, "parameters": [ { "name": "epoch", "description": "Epoch number (optional, if not provided current epoch will be used)", "in": "query", "required": false, "type": "string", "format": "uint64" } ], "tags": [ "SymbioticAPIService" ] } } }, "definitions": { "AggregationProof": { "type": "object", "properties": { "messageHash": { "type": "string", "format": "byte", "title": "Message hash" }, "proof": { "type": "string", "format": "byte", "title": "Proof data" }, "requestId": { "type": "string", "title": "Request ID" } }, "title": "Response message for getting aggregation proof" }, "Any": { "type": "object", "properties": { "@type": { "type": "string" } }, "additionalProperties": {} }, "ChainEpochInfo": { "type": "object", "properties": { "lastCommittedEpoch": { "type": "string", "format": "uint64", "title": "Last committed epoch for this chain" }, "startTime": { "type": "string", "format": "date-time", "title": "Epoch start time" } }, "title": "Settlement chain with its last committed epoch" }, "ExtraData": { "type": "object", "properties": { "key": { "type": "string", "format": "byte" }, "value": { "type": "string", "format": "byte" } } }, "GetAggregationProofResponse": { "type": "object", "properties": { "aggregationProof": { "$ref": "#/definitions/AggregationProof" } }, "title": "Response message for getting aggregation proof" }, "GetAggregationProofsByEpochResponse": { "type": "object", "properties": { "aggregationProofs": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/AggregationProof" } } }, "title": "Response message for getting aggregation proof" }, "GetAggregationStatusResponse": { "type": "object", "properties": { "currentVotingPower": { "type": "string", "title": "Current voting power of the aggregator (big integer as string)" }, "signerOperators": { "type": "array", "items": { "type": "string" }, "title": "List of operator addresses that signed the request" } }, "title": "Response message for getting aggregation status" }, "GetCurrentEpochResponse": { "type": "object", "properties": { "epoch": { "type": "string", "format": "uint64", "title": "Epoch number" }, "startTime": { "type": "string", "format": "date-time", "title": "Epoch start time" } }, "title": "Response message for getting current epoch" }, "GetLastAllCommittedResponse": { "type": "object", "properties": { "epochInfos": { "type": "object", "additionalProperties": { "$ref": "#/definitions/ChainEpochInfo" }, "title": "List of settlement chains with their last committed epochs" }, "suggestedEpochInfo": { "$ref": "#/definitions/ChainEpochInfo", "title": "Suggested epoch info for signatures, it is the minimum commited epoch among all chains" } }, "title": "Response message for getting all last committed epochs" }, "GetLastCommittedResponse": { "type": "object", "properties": { "settlementChainId": { "type": "string", "format": "uint64", "title": "Settlement chain ID" }, "epochInfo": { "$ref": "#/definitions/ChainEpochInfo" } }, "title": "Response message for getting last committed epoch" }, "GetLocalValidatorResponse": { "type": "object", "properties": { "validator": { "$ref": "#/definitions/Validator", "title": "The validator" } }, "title": "Response message for getting local validator" }, "GetSignatureRequestIDsByEpochResponse": { "type": "object", "properties": { "requestIds": { "type": "array", "items": { "type": "string" }, "title": "List of all signature request IDs for the epoch" } }, "title": "Response message for getting all signature request IDs by epoch" }, "GetSignatureRequestResponse": { "type": "object", "properties": { "signatureRequest": { "$ref": "#/definitions/SignatureRequest" } }, "title": "Response message for getting signature request" }, "GetSignatureRequestsByEpochResponse": { "type": "object", "properties": { "signatureRequests": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/SignatureRequest" }, "title": "List of all signature requests for the epoch" } }, "title": "Response message for getting all signature requests by epoch" }, "GetSignaturesByEpochResponse": { "type": "object", "properties": { "signatures": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/Signature" }, "title": "List of signatures" } }, "title": "Response message for getting signatures by epoch" }, "GetSignaturesResponse": { "type": "object", "properties": { "signatures": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/Signature" }, "title": "List of signatures" } }, "title": "Response message for getting signatures" }, "GetValidatorByAddressResponse": { "type": "object", "properties": { "validator": { "$ref": "#/definitions/Validator", "title": "The validator" } }, "title": "Response message for getting validator by address" }, "GetValidatorByKeyResponse": { "type": "object", "properties": { "validator": { "$ref": "#/definitions/Validator", "title": "The validator" } }, "title": "Response message for getting validator by key" }, "GetValidatorSetHeaderResponse": { "type": "object", "properties": { "version": { "type": "integer", "format": "int64", "title": "Version of the validator set" }, "requiredKeyTag": { "type": "integer", "format": "int64", "title": "Key tag required to commit next validator set" }, "epoch": { "type": "string", "format": "uint64", "title": "Validator set epoch" }, "captureTimestamp": { "type": "string", "format": "date-time", "title": "Epoch capture timestamp" }, "quorumThreshold": { "type": "string", "title": "Quorum threshold (big integer as string)" }, "totalVotingPower": { "type": "string", "title": "Total voting power (big integer as string)" }, "validatorsSszMroot": { "type": "string", "title": "Validators SSZ Merkle root (hex string)" } }, "title": "Response message for getting validator set header" }, "GetValidatorSetMetadataResponse": { "type": "object", "properties": { "extraData": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/ExtraData" } }, "commitmentData": { "type": "string", "format": "byte" }, "requestId": { "type": "string" } }, "title": "Response message for getting validator set header" }, "GetValidatorSetResponse": { "type": "object", "properties": { "validatorSet": { "$ref": "#/definitions/ValidatorSet", "title": "The validator set" } }, "title": "Response message for getting validator set" }, "Key": { "type": "object", "properties": { "tag": { "type": "integer", "format": "int64", "title": "Key tag identifier (0-127)" }, "payload": { "type": "string", "format": "byte", "title": "Key payload" } }, "title": "Cryptographic key" }, "ListenProofsResponse": { "type": "object", "properties": { "requestId": { "type": "string", "title": "Id of the request" }, "epoch": { "type": "string", "format": "uint64", "title": "Epoch number" }, "aggregationProof": { "$ref": "#/definitions/AggregationProof", "title": "Final aggregation proof" } }, "title": "Response message for aggregation proofs stream" }, "ListenSignaturesResponse": { "type": "object", "properties": { "requestId": { "type": "string", "title": "Id of the signature request" }, "epoch": { "type": "string", "format": "uint64", "title": "Epoch number" }, "signature": { "$ref": "#/definitions/Signature", "title": "Signature data" } }, "title": "Response message for signatures stream" }, "ListenValidatorSetResponse": { "type": "object", "properties": { "validatorSet": { "$ref": "#/definitions/ValidatorSet", "title": "The validator set" } }, "title": "Response message for validator set changes stream" }, "SignMessageRequest": { "type": "object", "properties": { "keyTag": { "type": "integer", "format": "int64", "title": "Key tag identifier (0-127)" }, "message": { "type": "string", "format": "byte", "title": "Message to be signed" }, "requiredEpoch": { "type": "string", "format": "uint64", "title": "Required epoch (optional, if not provided latest committed epoch will be used)" } }, "title": "Request message for signing a message" }, "SignMessageResponse": { "type": "object", "properties": { "requestId": { "type": "string", "title": "Hash of the signature request" }, "epoch": { "type": "string", "format": "uint64", "title": "Epoch number" } }, "title": "Response message for sign message request" }, "Signature": { "type": "object", "properties": { "signature": { "type": "string", "format": "byte", "title": "Signature data" }, "messageHash": { "type": "string", "format": "byte", "title": "Message hash" }, "publicKey": { "type": "string", "format": "byte", "title": "Public key" }, "requestId": { "type": "string", "title": "Request ID" } }, "title": "Digital signature" }, "SignatureRequest": { "type": "object", "properties": { "requestId": { "type": "string", "title": "Request ID" }, "keyTag": { "type": "integer", "format": "int64", "title": "Key tag identifier (0-127)" }, "message": { "type": "string", "format": "byte", "title": "Message to be signed" }, "requiredEpoch": { "type": "string", "format": "uint64", "title": "Required epoch" } }, "title": "SignatureRequest represents a signature request" }, "Status": { "type": "object", "properties": { "code": { "type": "integer", "format": "int32" }, "message": { "type": "string" }, "details": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/Any" } } } }, "Validator": { "type": "object", "properties": { "operator": { "type": "string", "title": "Operator address (hex string)" }, "votingPower": { "type": "string", "title": "Voting power of the validator (big integer as string)" }, "isActive": { "type": "boolean", "title": "Indicates if the validator is active" }, "keys": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/Key" }, "title": "List of cryptographic keys" }, "vaults": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/ValidatorVault" }, "title": "List of validator vaults" } }, "title": "Validator information" }, "ValidatorSet": { "type": "object", "properties": { "version": { "type": "integer", "format": "int64", "title": "Version of the validator set" }, "requiredKeyTag": { "type": "integer", "format": "int64", "title": "Key tag required to commit next validator set" }, "epoch": { "type": "string", "format": "uint64", "title": "Validator set epoch" }, "captureTimestamp": { "type": "string", "format": "date-time", "title": "Epoch capture timestamp" }, "quorumThreshold": { "type": "string", "title": "Quorum threshold (big integer as string)" }, "status": { "$ref": "#/definitions/ValidatorSetStatus", "title": "Status of validator set header" }, "validators": { "type": "array", "items": { "type": "object", "$ref": "#/definitions/Validator" }, "title": "List of validators" } } }, "ValidatorSetStatus": { "type": "string", "enum": [ "VALIDATOR_SET_STATUS_UNSPECIFIED", "VALIDATOR_SET_STATUS_DERIVED", "VALIDATOR_SET_STATUS_AGGREGATED", "VALIDATOR_SET_STATUS_COMMITTED", "VALIDATOR_SET_STATUS_MISSED" ], "default": "VALIDATOR_SET_STATUS_UNSPECIFIED", "description": "- VALIDATOR_SET_STATUS_UNSPECIFIED: Default/unknown status\n - VALIDATOR_SET_STATUS_DERIVED: Derived status\n - VALIDATOR_SET_STATUS_AGGREGATED: Aggregated status\n - VALIDATOR_SET_STATUS_COMMITTED: Committed status\n - VALIDATOR_SET_STATUS_MISSED: Missed status", "title": "Validator set status enumeration" }, "ValidatorVault": { "type": "object", "properties": { "chainId": { "type": "string", "format": "uint64", "title": "Chain identifier" }, "vault": { "type": "string", "title": "Vault address" }, "votingPower": { "type": "string", "title": "Voting power for this vault (big integer as string)" } }, "title": "Validator vault information" } } } ```` ## File: docs/api/v1/doc.md ````markdown # Protocol Documentation ## Table of Contents - [v1/api.proto](#v1_api-proto) - [AggregationProof](#api-proto-v1-AggregationProof) - [ChainEpochInfo](#api-proto-v1-ChainEpochInfo) - [ExtraData](#api-proto-v1-ExtraData) - [GetAggregationProofRequest](#api-proto-v1-GetAggregationProofRequest) - [GetAggregationProofResponse](#api-proto-v1-GetAggregationProofResponse) - [GetAggregationProofsByEpochRequest](#api-proto-v1-GetAggregationProofsByEpochRequest) - [GetAggregationProofsByEpochResponse](#api-proto-v1-GetAggregationProofsByEpochResponse) - [GetAggregationStatusRequest](#api-proto-v1-GetAggregationStatusRequest) - [GetAggregationStatusResponse](#api-proto-v1-GetAggregationStatusResponse) - [GetCurrentEpochRequest](#api-proto-v1-GetCurrentEpochRequest) - [GetCurrentEpochResponse](#api-proto-v1-GetCurrentEpochResponse) - [GetLastAllCommittedRequest](#api-proto-v1-GetLastAllCommittedRequest) - [GetLastAllCommittedResponse](#api-proto-v1-GetLastAllCommittedResponse) - [GetLastAllCommittedResponse.EpochInfosEntry](#api-proto-v1-GetLastAllCommittedResponse-EpochInfosEntry) - [GetLastCommittedRequest](#api-proto-v1-GetLastCommittedRequest) - [GetLastCommittedResponse](#api-proto-v1-GetLastCommittedResponse) - [GetLocalValidatorRequest](#api-proto-v1-GetLocalValidatorRequest) - [GetLocalValidatorResponse](#api-proto-v1-GetLocalValidatorResponse) - [GetSignatureRequestIDsByEpochRequest](#api-proto-v1-GetSignatureRequestIDsByEpochRequest) - [GetSignatureRequestIDsByEpochResponse](#api-proto-v1-GetSignatureRequestIDsByEpochResponse) - [GetSignatureRequestRequest](#api-proto-v1-GetSignatureRequestRequest) - [GetSignatureRequestResponse](#api-proto-v1-GetSignatureRequestResponse) - [GetSignatureRequestsByEpochRequest](#api-proto-v1-GetSignatureRequestsByEpochRequest) - [GetSignatureRequestsByEpochResponse](#api-proto-v1-GetSignatureRequestsByEpochResponse) - [GetSignaturesByEpochRequest](#api-proto-v1-GetSignaturesByEpochRequest) - [GetSignaturesByEpochResponse](#api-proto-v1-GetSignaturesByEpochResponse) - [GetSignaturesRequest](#api-proto-v1-GetSignaturesRequest) - [GetSignaturesResponse](#api-proto-v1-GetSignaturesResponse) - [GetValidatorByAddressRequest](#api-proto-v1-GetValidatorByAddressRequest) - [GetValidatorByAddressResponse](#api-proto-v1-GetValidatorByAddressResponse) - [GetValidatorByKeyRequest](#api-proto-v1-GetValidatorByKeyRequest) - [GetValidatorByKeyResponse](#api-proto-v1-GetValidatorByKeyResponse) - [GetValidatorSetHeaderRequest](#api-proto-v1-GetValidatorSetHeaderRequest) - [GetValidatorSetHeaderResponse](#api-proto-v1-GetValidatorSetHeaderResponse) - [GetValidatorSetMetadataRequest](#api-proto-v1-GetValidatorSetMetadataRequest) - [GetValidatorSetMetadataResponse](#api-proto-v1-GetValidatorSetMetadataResponse) - [GetValidatorSetRequest](#api-proto-v1-GetValidatorSetRequest) - [GetValidatorSetResponse](#api-proto-v1-GetValidatorSetResponse) - [Key](#api-proto-v1-Key) - [ListenProofsRequest](#api-proto-v1-ListenProofsRequest) - [ListenProofsResponse](#api-proto-v1-ListenProofsResponse) - [ListenSignaturesRequest](#api-proto-v1-ListenSignaturesRequest) - [ListenSignaturesResponse](#api-proto-v1-ListenSignaturesResponse) - [ListenValidatorSetRequest](#api-proto-v1-ListenValidatorSetRequest) - [ListenValidatorSetResponse](#api-proto-v1-ListenValidatorSetResponse) - [SignMessageRequest](#api-proto-v1-SignMessageRequest) - [SignMessageResponse](#api-proto-v1-SignMessageResponse) - [Signature](#api-proto-v1-Signature) - [SignatureRequest](#api-proto-v1-SignatureRequest) - [Validator](#api-proto-v1-Validator) - [ValidatorSet](#api-proto-v1-ValidatorSet) - [ValidatorVault](#api-proto-v1-ValidatorVault) - [ErrorCode](#api-proto-v1-ErrorCode) - [SigningStatus](#api-proto-v1-SigningStatus) - [ValidatorSetStatus](#api-proto-v1-ValidatorSetStatus) - [SymbioticAPIService](#api-proto-v1-SymbioticAPIService) - [Scalar Value Types](#scalar-value-types)

Top

## v1/api.proto ### AggregationProof Response message for getting aggregation proof | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | message_hash | [bytes](#bytes) | | Message hash | | proof | [bytes](#bytes) | | Proof data | | request_id | [string](#string) | | Request ID | ### ChainEpochInfo Settlement chain with its last committed epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | last_committed_epoch | [uint64](#uint64) | | Last committed epoch for this chain | | start_time | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | | Epoch start time | ### ExtraData | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | key | [bytes](#bytes) | | | | value | [bytes](#bytes) | | | ### GetAggregationProofRequest Request message for getting aggregation proof | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | | ### GetAggregationProofResponse Response message for getting aggregation proof | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | aggregation_proof | [AggregationProof](#api-proto-v1-AggregationProof) | | | ### GetAggregationProofsByEpochRequest Request message for getting aggregation proof | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | | Epoch number | ### GetAggregationProofsByEpochResponse Response message for getting aggregation proof | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | aggregation_proofs | [AggregationProof](#api-proto-v1-AggregationProof) | repeated | | ### GetAggregationStatusRequest Request message for getting aggregation status | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | | ### GetAggregationStatusResponse Response message for getting aggregation status | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | current_voting_power | [string](#string) | | Current voting power of the aggregator (big integer as string) | | signer_operators | [string](#string) | repeated | List of operator addresses that signed the request | ### GetCurrentEpochRequest Request message for getting current epoch ### GetCurrentEpochResponse Response message for getting current epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | | Epoch number | | start_time | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | | Epoch start time | ### GetLastAllCommittedRequest Request message for getting last committed epochs for all chains No parameters needed ### GetLastAllCommittedResponse Response message for getting all last committed epochs | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch_infos | [GetLastAllCommittedResponse.EpochInfosEntry](#api-proto-v1-GetLastAllCommittedResponse-EpochInfosEntry) | repeated | List of settlement chains with their last committed epochs | | suggested_epoch_info | [ChainEpochInfo](#api-proto-v1-ChainEpochInfo) | | Suggested epoch info for signatures, it is the minimum commited epoch among all chains | ### GetLastAllCommittedResponse.EpochInfosEntry | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | key | [uint64](#uint64) | | | | value | [ChainEpochInfo](#api-proto-v1-ChainEpochInfo) | | | ### GetLastCommittedRequest Request message for getting last committed epoch for a specific settlement chain | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | settlement_chain_id | [uint64](#uint64) | | Settlement chain ID | ### GetLastCommittedResponse Response message for getting last committed epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | settlement_chain_id | [uint64](#uint64) | | Settlement chain ID | | epoch_info | [ChainEpochInfo](#api-proto-v1-ChainEpochInfo) | | | ### GetLocalValidatorRequest Request message for getting local validator | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | optional | Epoch number (optional, if not provided current epoch will be used) | ### GetLocalValidatorResponse Response message for getting local validator | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | validator | [Validator](#api-proto-v1-Validator) | | The validator | ### GetSignatureRequestIDsByEpochRequest Request message for getting all signature request IDs by epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | | Epoch number | ### GetSignatureRequestIDsByEpochResponse Response message for getting all signature request IDs by epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_ids | [string](#string) | repeated | List of all signature request IDs for the epoch | ### GetSignatureRequestRequest Request message for getting signature request | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | | ### GetSignatureRequestResponse Response message for getting signature request | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | signature_request | [SignatureRequest](#api-proto-v1-SignatureRequest) | | | ### GetSignatureRequestsByEpochRequest Request message for getting all signature requests by epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | | Epoch number | ### GetSignatureRequestsByEpochResponse Response message for getting all signature requests by epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | signature_requests | [SignatureRequest](#api-proto-v1-SignatureRequest) | repeated | List of all signature requests for the epoch | ### GetSignaturesByEpochRequest Request message for getting signatures by epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | | Epoch number | ### GetSignaturesByEpochResponse Response message for getting signatures by epoch | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | signatures | [Signature](#api-proto-v1-Signature) | repeated | List of signatures | ### GetSignaturesRequest Request message for getting signatures | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | | ### GetSignaturesResponse Response message for getting signatures | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | signatures | [Signature](#api-proto-v1-Signature) | repeated | List of signatures | ### GetValidatorByAddressRequest Request message for getting validator by address | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | optional | Epoch number (optional, if not provided current epoch will be used) | | address | [string](#string) | | Validator address (required) | ### GetValidatorByAddressResponse Response message for getting validator by address | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | validator | [Validator](#api-proto-v1-Validator) | | The validator | ### GetValidatorByKeyRequest Request message for getting validator by key | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | optional | Epoch number (optional, if not provided current epoch will be used) | | key_tag | [uint32](#uint32) | | Validator key tag (required) | | on_chain_key | [bytes](#bytes) | | Validator on chain (public) key (required) | ### GetValidatorByKeyResponse Response message for getting validator by key | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | validator | [Validator](#api-proto-v1-Validator) | | The validator | ### GetValidatorSetHeaderRequest Request message for getting validator set header | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | optional | Epoch number (optional, if not provided current epoch will be used) | ### GetValidatorSetHeaderResponse Response message for getting validator set header | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | version | [uint32](#uint32) | | Version of the validator set | | required_key_tag | [uint32](#uint32) | | Key tag required to commit next validator set | | epoch | [uint64](#uint64) | | Validator set epoch | | capture_timestamp | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | | Epoch capture timestamp | | quorum_threshold | [string](#string) | | Quorum threshold (big integer as string) | | total_voting_power | [string](#string) | | Total voting power (big integer as string) | | validators_ssz_mroot | [string](#string) | | Validators SSZ Merkle root (hex string) | ### GetValidatorSetMetadataRequest Request message for getting validator set metadata | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | optional | Epoch number (optional, if not provided current epoch will be used) | ### GetValidatorSetMetadataResponse Response message for getting validator set header | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | extra_data | [ExtraData](#api-proto-v1-ExtraData) | repeated | | | commitment_data | [bytes](#bytes) | | | | request_id | [string](#string) | | | ### GetValidatorSetRequest Request message for getting validator set | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | epoch | [uint64](#uint64) | optional | Epoch number (optional, if not provided current epoch will be used) | ### GetValidatorSetResponse Response message for getting validator set | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | validator_set | [ValidatorSet](#api-proto-v1-ValidatorSet) | | The validator set | ### Key Cryptographic key | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | tag | [uint32](#uint32) | | Key tag identifier (0-127) | | payload | [bytes](#bytes) | | Key payload | ### ListenProofsRequest Request message for listening to aggregation proofs stream | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | start_epoch | [uint64](#uint64) | optional | Optional: start epoch. If provided, stream will first send all historical proofs starting from this epoch, then continue with real-time updates If not provided, only proofs generated after stream creation will be sent | ### ListenProofsResponse Response message for aggregation proofs stream | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | Id of the request | | epoch | [uint64](#uint64) | | Epoch number | | aggregation_proof | [AggregationProof](#api-proto-v1-AggregationProof) | | Final aggregation proof | ### ListenSignaturesRequest Request message for listening to signatures stream | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | start_epoch | [uint64](#uint64) | optional | Optional: start epoch. If provided, stream will first send all historical signatures starting from this epoch, then continue with real-time updates If not provided, only signatures generated after stream creation will be sent | ### ListenSignaturesResponse Response message for signatures stream | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | Id of the signature request | | epoch | [uint64](#uint64) | | Epoch number | | signature | [Signature](#api-proto-v1-Signature) | | Signature data | ### ListenValidatorSetRequest Request message for listening to validator set changes stream | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | start_epoch | [uint64](#uint64) | optional | Optional: start epoch. If provided, stream will first send all historical validator sets starting from this epoch, then continue with real-time updates If not provided, only validator sets generated after stream creation will be sent | ### ListenValidatorSetResponse Response message for validator set changes stream | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | validator_set | [ValidatorSet](#api-proto-v1-ValidatorSet) | | The validator set | ### SignMessageRequest Request message for signing a message | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | key_tag | [uint32](#uint32) | | Key tag identifier (0-127) | | message | [bytes](#bytes) | | Message to be signed | | required_epoch | [uint64](#uint64) | optional | Required epoch (optional, if not provided latest committed epoch will be used) | ### SignMessageResponse Response message for sign message request | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | Hash of the signature request | | epoch | [uint64](#uint64) | | Epoch number | ### Signature Digital signature | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | signature | [bytes](#bytes) | | Signature data | | message_hash | [bytes](#bytes) | | Message hash | | public_key | [bytes](#bytes) | | Public key | | request_id | [string](#string) | | Request ID | ### SignatureRequest SignatureRequest represents a signature request | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | request_id | [string](#string) | | Request ID | | key_tag | [uint32](#uint32) | | Key tag identifier (0-127) | | message | [bytes](#bytes) | | Message to be signed | | required_epoch | [uint64](#uint64) | | Required epoch | ### Validator Validator information | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | operator | [string](#string) | | Operator address (hex string) | | voting_power | [string](#string) | | Voting power of the validator (big integer as string) | | is_active | [bool](#bool) | | Indicates if the validator is active | | keys | [Key](#api-proto-v1-Key) | repeated | List of cryptographic keys | | vaults | [ValidatorVault](#api-proto-v1-ValidatorVault) | repeated | List of validator vaults | ### ValidatorSet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | version | [uint32](#uint32) | | Version of the validator set | | required_key_tag | [uint32](#uint32) | | Key tag required to commit next validator set | | epoch | [uint64](#uint64) | | Validator set epoch | | capture_timestamp | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | | Epoch capture timestamp | | quorum_threshold | [string](#string) | | Quorum threshold (big integer as string) | | status | [ValidatorSetStatus](#api-proto-v1-ValidatorSetStatus) | | Status of validator set header | | validators | [Validator](#api-proto-v1-Validator) | repeated | List of validators | ### ValidatorVault Validator vault information | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | chain_id | [uint64](#uint64) | | Chain identifier | | vault | [string](#string) | | Vault address | | voting_power | [string](#string) | | Voting power for this vault (big integer as string) | ### ErrorCode Error code enumeration | Name | Number | Description | | ---- | ------ | ----------- | | ERROR_CODE_UNSPECIFIED | 0 | Default/unknown error | | ERROR_CODE_NO_DATA | 1 | No data found | | ERROR_CODE_INTERNAL | 2 | Internal server error | | ERROR_CODE_NOT_AGGREGATOR | 3 | Not an aggregator node | ### SigningStatus Signing process status enumeration | Name | Number | Description | | ---- | ------ | ----------- | | SIGNING_STATUS_UNSPECIFIED | 0 | Default/unknown status | | SIGNING_STATUS_PENDING | 1 | Request has been created and is waiting for signatures | | SIGNING_STATUS_COMPLETED | 2 | Signing process completed successfully with proof | | SIGNING_STATUS_FAILED | 3 | Signing process failed | | SIGNING_STATUS_TIMEOUT | 4 | Signing request timed out | ### ValidatorSetStatus Validator set status enumeration | Name | Number | Description | | ---- | ------ | ----------- | | VALIDATOR_SET_STATUS_UNSPECIFIED | 0 | Default/unknown status | | VALIDATOR_SET_STATUS_DERIVED | 1 | Derived status | | VALIDATOR_SET_STATUS_AGGREGATED | 2 | Aggregated status | | VALIDATOR_SET_STATUS_COMMITTED | 3 | Committed status | | VALIDATOR_SET_STATUS_MISSED | 4 | Missed status | ### SymbioticAPIService SymbioticAPI provides access to the Symbiotic relay functions | Method Name | Request Type | Response Type | Description | | ----------- | ------------ | ------------- | ------------| | SignMessage | [SignMessageRequest](#api-proto-v1-SignMessageRequest) | [SignMessageResponse](#api-proto-v1-SignMessageResponse) | Sign a message | | GetAggregationProof | [GetAggregationProofRequest](#api-proto-v1-GetAggregationProofRequest) | [GetAggregationProofResponse](#api-proto-v1-GetAggregationProofResponse) | Get aggregation proof | | GetAggregationProofsByEpoch | [GetAggregationProofsByEpochRequest](#api-proto-v1-GetAggregationProofsByEpochRequest) | [GetAggregationProofsByEpochResponse](#api-proto-v1-GetAggregationProofsByEpochResponse) | Get aggregation proofs by epoch | | GetCurrentEpoch | [GetCurrentEpochRequest](#api-proto-v1-GetCurrentEpochRequest) | [GetCurrentEpochResponse](#api-proto-v1-GetCurrentEpochResponse) | Get current epoch | | GetSignatures | [GetSignaturesRequest](#api-proto-v1-GetSignaturesRequest) | [GetSignaturesResponse](#api-proto-v1-GetSignaturesResponse) | Get signature by request id | | GetSignaturesByEpoch | [GetSignaturesByEpochRequest](#api-proto-v1-GetSignaturesByEpochRequest) | [GetSignaturesByEpochResponse](#api-proto-v1-GetSignaturesByEpochResponse) | Get signature by epoch | | GetSignatureRequestIDsByEpoch | [GetSignatureRequestIDsByEpochRequest](#api-proto-v1-GetSignatureRequestIDsByEpochRequest) | [GetSignatureRequestIDsByEpochResponse](#api-proto-v1-GetSignatureRequestIDsByEpochResponse) | Get all signature request IDs by epoch | | GetSignatureRequestsByEpoch | [GetSignatureRequestsByEpochRequest](#api-proto-v1-GetSignatureRequestsByEpochRequest) | [GetSignatureRequestsByEpochResponse](#api-proto-v1-GetSignatureRequestsByEpochResponse) | Get all signature requests by epoch | | GetSignatureRequest | [GetSignatureRequestRequest](#api-proto-v1-GetSignatureRequestRequest) | [GetSignatureRequestResponse](#api-proto-v1-GetSignatureRequestResponse) | Get signature request by request id | | GetAggregationStatus | [GetAggregationStatusRequest](#api-proto-v1-GetAggregationStatusRequest) | [GetAggregationStatusResponse](#api-proto-v1-GetAggregationStatusResponse) | Get aggregation status, can be sent only to aggregator nodes | | GetValidatorSet | [GetValidatorSetRequest](#api-proto-v1-GetValidatorSetRequest) | [GetValidatorSetResponse](#api-proto-v1-GetValidatorSetResponse) | Get current validator set | | GetValidatorByAddress | [GetValidatorByAddressRequest](#api-proto-v1-GetValidatorByAddressRequest) | [GetValidatorByAddressResponse](#api-proto-v1-GetValidatorByAddressResponse) | Get validator by address | | GetValidatorByKey | [GetValidatorByKeyRequest](#api-proto-v1-GetValidatorByKeyRequest) | [GetValidatorByKeyResponse](#api-proto-v1-GetValidatorByKeyResponse) | Get validator by key | | GetLocalValidator | [GetLocalValidatorRequest](#api-proto-v1-GetLocalValidatorRequest) | [GetLocalValidatorResponse](#api-proto-v1-GetLocalValidatorResponse) | Get local validator | | GetValidatorSetHeader | [GetValidatorSetHeaderRequest](#api-proto-v1-GetValidatorSetHeaderRequest) | [GetValidatorSetHeaderResponse](#api-proto-v1-GetValidatorSetHeaderResponse) | Get validator set header | | GetLastCommitted | [GetLastCommittedRequest](#api-proto-v1-GetLastCommittedRequest) | [GetLastCommittedResponse](#api-proto-v1-GetLastCommittedResponse) | Get last committed epoch for a specific settlement chain | | GetLastAllCommitted | [GetLastAllCommittedRequest](#api-proto-v1-GetLastAllCommittedRequest) | [GetLastAllCommittedResponse](#api-proto-v1-GetLastAllCommittedResponse) | Get last committed epochs for all settlement chains | | GetValidatorSetMetadata | [GetValidatorSetMetadataRequest](#api-proto-v1-GetValidatorSetMetadataRequest) | [GetValidatorSetMetadataResponse](#api-proto-v1-GetValidatorSetMetadataResponse) | Get validator set metadata like extra data and request id to fetch aggregation and signature requests | | ListenSignatures | [ListenSignaturesRequest](#api-proto-v1-ListenSignaturesRequest) | [ListenSignaturesResponse](#api-proto-v1-ListenSignaturesResponse) stream | Stream signatures in real-time. If start_epoch is provided, sends historical data first | | ListenProofs | [ListenProofsRequest](#api-proto-v1-ListenProofsRequest) | [ListenProofsResponse](#api-proto-v1-ListenProofsResponse) stream | Stream aggregation proofs in real-time. If start_epoch is provided, sends historical data first | | ListenValidatorSet | [ListenValidatorSetRequest](#api-proto-v1-ListenValidatorSetRequest) | [ListenValidatorSetResponse](#api-proto-v1-ListenValidatorSetResponse) stream | Stream validator set changes in real-time. If start_epoch is provided, sends historical data first | ## Scalar Value Types | .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | | ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- | | double | | double | double | float | float64 | double | float | Float | | float | | float | float | float | float32 | float | float | Float | | int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | | int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum | | uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) | | uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) | | sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | | sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum | | fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) | | fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum | | sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | | sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum | | bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | | string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) | | bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) | ```` ## File: docs/api/v1/index.html ````html Protocol Documentation

Protocol Documentation

Table of Contents

v1/api.proto

Top

AggregationProof

Response message for getting aggregation proof

FieldTypeLabelDescription
message_hash bytes

Message hash

proof bytes

Proof data

request_id string

Request ID

ChainEpochInfo

Settlement chain with its last committed epoch

FieldTypeLabelDescription
last_committed_epoch uint64

Last committed epoch for this chain

start_time google.protobuf.Timestamp

Epoch start time

ExtraData

FieldTypeLabelDescription
key bytes

value bytes

GetAggregationProofRequest

Request message for getting aggregation proof

FieldTypeLabelDescription
request_id string

GetAggregationProofResponse

Response message for getting aggregation proof

FieldTypeLabelDescription
aggregation_proof AggregationProof

GetAggregationProofsByEpochRequest

Request message for getting aggregation proof

FieldTypeLabelDescription
epoch uint64

Epoch number

GetAggregationProofsByEpochResponse

Response message for getting aggregation proof

FieldTypeLabelDescription
aggregation_proofs AggregationProof repeated

GetAggregationStatusRequest

Request message for getting aggregation status

FieldTypeLabelDescription
request_id string

GetAggregationStatusResponse

Response message for getting aggregation status

FieldTypeLabelDescription
current_voting_power string

Current voting power of the aggregator (big integer as string)

signer_operators string repeated

List of operator addresses that signed the request

GetCurrentEpochRequest

Request message for getting current epoch

GetCurrentEpochResponse

Response message for getting current epoch

FieldTypeLabelDescription
epoch uint64

Epoch number

start_time google.protobuf.Timestamp

Epoch start time

GetLastAllCommittedRequest

Request message for getting last committed epochs for all chains

No parameters needed

GetLastAllCommittedResponse

Response message for getting all last committed epochs

FieldTypeLabelDescription
epoch_infos GetLastAllCommittedResponse.EpochInfosEntry repeated

List of settlement chains with their last committed epochs

suggested_epoch_info ChainEpochInfo

Suggested epoch info for signatures, it is the minimum commited epoch among all chains

GetLastAllCommittedResponse.EpochInfosEntry

FieldTypeLabelDescription
key uint64

value ChainEpochInfo

GetLastCommittedRequest

Request message for getting last committed epoch for a specific settlement chain

FieldTypeLabelDescription
settlement_chain_id uint64

Settlement chain ID

GetLastCommittedResponse

Response message for getting last committed epoch

FieldTypeLabelDescription
settlement_chain_id uint64

Settlement chain ID

epoch_info ChainEpochInfo

GetLocalValidatorRequest

Request message for getting local validator

FieldTypeLabelDescription
epoch uint64 optional

Epoch number (optional, if not provided current epoch will be used)

GetLocalValidatorResponse

Response message for getting local validator

FieldTypeLabelDescription
validator Validator

The validator

GetSignatureRequestIDsByEpochRequest

Request message for getting all signature request IDs by epoch

FieldTypeLabelDescription
epoch uint64

Epoch number

GetSignatureRequestIDsByEpochResponse

Response message for getting all signature request IDs by epoch

FieldTypeLabelDescription
request_ids string repeated

List of all signature request IDs for the epoch

GetSignatureRequestRequest

Request message for getting signature request

FieldTypeLabelDescription
request_id string

GetSignatureRequestResponse

Response message for getting signature request

FieldTypeLabelDescription
signature_request SignatureRequest

GetSignatureRequestsByEpochRequest

Request message for getting all signature requests by epoch

FieldTypeLabelDescription
epoch uint64

Epoch number

GetSignatureRequestsByEpochResponse

Response message for getting all signature requests by epoch

FieldTypeLabelDescription
signature_requests SignatureRequest repeated

List of all signature requests for the epoch

GetSignaturesByEpochRequest

Request message for getting signatures by epoch

FieldTypeLabelDescription
epoch uint64

Epoch number

GetSignaturesByEpochResponse

Response message for getting signatures by epoch

FieldTypeLabelDescription
signatures Signature repeated

List of signatures

GetSignaturesRequest

Request message for getting signatures

FieldTypeLabelDescription
request_id string

GetSignaturesResponse

Response message for getting signatures

FieldTypeLabelDescription
signatures Signature repeated

List of signatures

GetValidatorByAddressRequest

Request message for getting validator by address

FieldTypeLabelDescription
epoch uint64 optional

Epoch number (optional, if not provided current epoch will be used)

address string

Validator address (required)

GetValidatorByAddressResponse

Response message for getting validator by address

FieldTypeLabelDescription
validator Validator

The validator

GetValidatorByKeyRequest

Request message for getting validator by key

FieldTypeLabelDescription
epoch uint64 optional

Epoch number (optional, if not provided current epoch will be used)

key_tag uint32

Validator key tag (required)

on_chain_key bytes

Validator on chain (public) key (required)

GetValidatorByKeyResponse

Response message for getting validator by key

FieldTypeLabelDescription
validator Validator

The validator

GetValidatorSetHeaderRequest

Request message for getting validator set header

FieldTypeLabelDescription
epoch uint64 optional

Epoch number (optional, if not provided current epoch will be used)

GetValidatorSetHeaderResponse

Response message for getting validator set header

FieldTypeLabelDescription
version uint32

Version of the validator set

required_key_tag uint32

Key tag required to commit next validator set

epoch uint64

Validator set epoch

capture_timestamp google.protobuf.Timestamp

Epoch capture timestamp

quorum_threshold string

Quorum threshold (big integer as string)

total_voting_power string

Total voting power (big integer as string)

validators_ssz_mroot string

Validators SSZ Merkle root (hex string)

GetValidatorSetMetadataRequest

Request message for getting validator set metadata

FieldTypeLabelDescription
epoch uint64 optional

Epoch number (optional, if not provided current epoch will be used)

GetValidatorSetMetadataResponse

Response message for getting validator set header

FieldTypeLabelDescription
extra_data ExtraData repeated

commitment_data bytes

request_id string

GetValidatorSetRequest

Request message for getting validator set

FieldTypeLabelDescription
epoch uint64 optional

Epoch number (optional, if not provided current epoch will be used)

GetValidatorSetResponse

Response message for getting validator set

FieldTypeLabelDescription
validator_set ValidatorSet

The validator set

Key

Cryptographic key

FieldTypeLabelDescription
tag uint32

Key tag identifier (0-127)

payload bytes

Key payload

ListenProofsRequest

Request message for listening to aggregation proofs stream

FieldTypeLabelDescription
start_epoch uint64 optional

Optional: start epoch. If provided, stream will first send all historical proofs starting from this epoch, then continue with real-time updates If not provided, only proofs generated after stream creation will be sent

ListenProofsResponse

Response message for aggregation proofs stream

FieldTypeLabelDescription
request_id string

Id of the request

epoch uint64

Epoch number

aggregation_proof AggregationProof

Final aggregation proof

ListenSignaturesRequest

Request message for listening to signatures stream

FieldTypeLabelDescription
start_epoch uint64 optional

Optional: start epoch. If provided, stream will first send all historical signatures starting from this epoch, then continue with real-time updates If not provided, only signatures generated after stream creation will be sent

ListenSignaturesResponse

Response message for signatures stream

FieldTypeLabelDescription
request_id string

Id of the signature request

epoch uint64

Epoch number

signature Signature

Signature data

ListenValidatorSetRequest

Request message for listening to validator set changes stream

FieldTypeLabelDescription
start_epoch uint64 optional

Optional: start epoch. If provided, stream will first send all historical validator sets starting from this epoch, then continue with real-time updates If not provided, only validator sets generated after stream creation will be sent

ListenValidatorSetResponse

Response message for validator set changes stream

FieldTypeLabelDescription
validator_set ValidatorSet

The validator set

SignMessageRequest

Request message for signing a message

FieldTypeLabelDescription
key_tag uint32

Key tag identifier (0-127)

message bytes

Message to be signed

required_epoch uint64 optional

Required epoch (optional, if not provided latest committed epoch will be used)

SignMessageResponse

Response message for sign message request

FieldTypeLabelDescription
request_id string

Hash of the signature request

epoch uint64

Epoch number

Signature

Digital signature

FieldTypeLabelDescription
signature bytes

Signature data

message_hash bytes

Message hash

public_key bytes

Public key

request_id string

Request ID

SignatureRequest

SignatureRequest represents a signature request

FieldTypeLabelDescription
request_id string

Request ID

key_tag uint32

Key tag identifier (0-127)

message bytes

Message to be signed

required_epoch uint64

Required epoch

Validator

Validator information

FieldTypeLabelDescription
operator string

Operator address (hex string)

voting_power string

Voting power of the validator (big integer as string)

is_active bool

Indicates if the validator is active

keys Key repeated

List of cryptographic keys

vaults ValidatorVault repeated

List of validator vaults

ValidatorSet

FieldTypeLabelDescription
version uint32

Version of the validator set

required_key_tag uint32

Key tag required to commit next validator set

epoch uint64

Validator set epoch

capture_timestamp google.protobuf.Timestamp

Epoch capture timestamp

quorum_threshold string

Quorum threshold (big integer as string)

status ValidatorSetStatus

Status of validator set header

validators Validator repeated

List of validators

ValidatorVault

Validator vault information

FieldTypeLabelDescription
chain_id uint64

Chain identifier

vault string

Vault address

voting_power string

Voting power for this vault (big integer as string)

ErrorCode

Error code enumeration

NameNumberDescription
ERROR_CODE_UNSPECIFIED 0

Default/unknown error

ERROR_CODE_NO_DATA 1

No data found

ERROR_CODE_INTERNAL 2

Internal server error

ERROR_CODE_NOT_AGGREGATOR 3

Not an aggregator node

SigningStatus

Signing process status enumeration

NameNumberDescription
SIGNING_STATUS_UNSPECIFIED 0

Default/unknown status

SIGNING_STATUS_PENDING 1

Request has been created and is waiting for signatures

SIGNING_STATUS_COMPLETED 2

Signing process completed successfully with proof

SIGNING_STATUS_FAILED 3

Signing process failed

SIGNING_STATUS_TIMEOUT 4

Signing request timed out

ValidatorSetStatus

Validator set status enumeration

NameNumberDescription
VALIDATOR_SET_STATUS_UNSPECIFIED 0

Default/unknown status

VALIDATOR_SET_STATUS_DERIVED 1

Derived status

VALIDATOR_SET_STATUS_AGGREGATED 2

Aggregated status

VALIDATOR_SET_STATUS_COMMITTED 3

Committed status

VALIDATOR_SET_STATUS_MISSED 4

Missed status

SymbioticAPIService

SymbioticAPI provides access to the Symbiotic relay functions

Method NameRequest TypeResponse TypeDescription
SignMessage SignMessageRequest SignMessageResponse

Sign a message

GetAggregationProof GetAggregationProofRequest GetAggregationProofResponse

Get aggregation proof

GetAggregationProofsByEpoch GetAggregationProofsByEpochRequest GetAggregationProofsByEpochResponse

Get aggregation proofs by epoch

GetCurrentEpoch GetCurrentEpochRequest GetCurrentEpochResponse

Get current epoch

GetSignatures GetSignaturesRequest GetSignaturesResponse

Get signature by request id

GetSignaturesByEpoch GetSignaturesByEpochRequest GetSignaturesByEpochResponse

Get signature by epoch

GetSignatureRequestIDsByEpoch GetSignatureRequestIDsByEpochRequest GetSignatureRequestIDsByEpochResponse

Get all signature request IDs by epoch

GetSignatureRequestsByEpoch GetSignatureRequestsByEpochRequest GetSignatureRequestsByEpochResponse

Get all signature requests by epoch

GetSignatureRequest GetSignatureRequestRequest GetSignatureRequestResponse

Get signature request by request id

GetAggregationStatus GetAggregationStatusRequest GetAggregationStatusResponse

Get aggregation status, can be sent only to aggregator nodes

GetValidatorSet GetValidatorSetRequest GetValidatorSetResponse

Get current validator set

GetValidatorByAddress GetValidatorByAddressRequest GetValidatorByAddressResponse

Get validator by address

GetValidatorByKey GetValidatorByKeyRequest GetValidatorByKeyResponse

Get validator by key

GetLocalValidator GetLocalValidatorRequest GetLocalValidatorResponse

Get local validator

GetValidatorSetHeader GetValidatorSetHeaderRequest GetValidatorSetHeaderResponse

Get validator set header

GetLastCommitted GetLastCommittedRequest GetLastCommittedResponse

Get last committed epoch for a specific settlement chain

GetLastAllCommitted GetLastAllCommittedRequest GetLastAllCommittedResponse

Get last committed epochs for all settlement chains

GetValidatorSetMetadata GetValidatorSetMetadataRequest GetValidatorSetMetadataResponse

Get validator set metadata like extra data and request id to fetch aggregation and signature requests

ListenSignatures ListenSignaturesRequest ListenSignaturesResponse stream

Stream signatures in real-time. If start_epoch is provided, sends historical data first

ListenProofs ListenProofsRequest ListenProofsResponse stream

Stream aggregation proofs in real-time. If start_epoch is provided, sends historical data first

ListenValidatorSet ListenValidatorSetRequest ListenValidatorSetResponse stream

Stream validator set changes in real-time. If start_epoch is provided, sends historical data first

Methods with HTTP bindings

Method Name Method Pattern Body
SignMessage POST /v1/sign *
GetAggregationProof GET /v1/aggregation/proof/{request_id}
GetAggregationProofsByEpoch GET /v1/aggregation/proofs/epoch/{epoch}
GetCurrentEpoch GET /v1/epoch/current
GetSignatures GET /v1/signatures/{request_id}
GetSignaturesByEpoch GET /v1/signatures/epoch/{epoch}
GetSignatureRequestIDsByEpoch GET /v1/signature-request-ids/epoch/{epoch}
GetSignatureRequestsByEpoch GET /v1/signature-requests/epoch/{epoch}
GetSignatureRequest GET /v1/signature-request/{request_id}
GetAggregationStatus GET /v1/aggregation/status/{request_id}
GetValidatorSet GET /v1/validator-set
GetValidatorByAddress GET /v1/validator/address/{address}
GetValidatorByKey GET /v1/validator/key/{key_tag}/{on_chain_key}
GetLocalValidator GET /v1/validator/local
GetValidatorSetHeader GET /v1/validator-set/header
GetLastCommitted GET /v1/committed/chain/{settlement_chain_id}
GetLastAllCommitted GET /v1/committed/all
GetValidatorSetMetadata GET /v1/validator-set/metadata
ListenSignatures GET /v1/stream/signatures
ListenProofs GET /v1/stream/proofs
ListenValidatorSet GET /v1/stream/validator-set

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
double double double float float64 double float Float
float float float float float32 float float Float
int32 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. int32 int int int32 int integer Bignum or Fixnum (as required)
int64 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. int64 long int/long int64 long integer/string Bignum
uint32 Uses variable-length encoding. uint32 int int/long uint32 uint integer Bignum or Fixnum (as required)
uint64 Uses variable-length encoding. uint64 long int/long uint64 ulong integer/string Bignum or Fixnum (as required)
sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 int integer Bignum or Fixnum (as required)
sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long int64 long integer/string Bignum
fixed32 Always four bytes. More efficient than uint32 if values are often greater than 2^28. uint32 int int uint32 uint integer Bignum or Fixnum (as required)
fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 2^56. uint64 long int/long uint64 ulong integer/string Bignum
sfixed32 Always four bytes. int32 int int int32 int integer Bignum or Fixnum (as required)
sfixed64 Always eight bytes. int64 long int/long int64 long integer/string Bignum
bool bool boolean boolean bool bool boolean TrueClass/FalseClass
string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode string string string String (UTF-8)
bytes May contain any arbitrary sequence of bytes. string ByteString str []byte ByteString string String (ASCII-8BIT)
```` ## File: docs/cli/relay/relay_sidecar.md ````markdown # `relay sidecar` Command Reference ## relay_sidecar Relay sidecar for signature aggregation ### Synopsis A P2P service for collecting and aggregating signatures for Ethereum contracts. ``` relay_sidecar [flags] ``` ### Options ``` --aggregation-policy-max-unsigners uint Max unsigners for low cost agg policy (default 50) --api.http-gateway Enable HTTP/JSON REST API gateway on /api/v1/* path --api.listen string API Server listener address --api.max-allowed-streams uint Max allowed streams count API Server (default 100) --api.verbose-logging Enable verbose logging for the API Server --cache.network-config-size int Network config cache size (default 10) --cache.validator-set-size int Validator set cache size (default 10) --circuits-dir string Directory path to load zk circuits from, if empty then zp prover is disabled --config string Path to config file (default "config.yaml") --driver.address string Driver contract address --driver.chain-id uint Driver contract chain id --evm.chains strings Chains, comma separated rpc-url,.. --evm.max-calls int Max calls in multicall --force-role.aggregator Force node to act as aggregator regardless of deterministic scheduling --force-role.committer Force node to act as committer regardless of deterministic scheduling -h, --help help for relay_sidecar --key-cache.enabled Enable key cache (default true) --key-cache.size int Key cache size (default 100) --keystore.password string Password for the keystore file, if provided will be used to decrypt the keystore file --keystore.path string Path to optional keystore file, if provided will be used instead of secret-keys flag --log.level string Log level (debug, info, warn, error) (default "info") --log.mode string Log mode (text, pretty, json) (default "json") --metrics.listen string Http listener address for metrics endpoint --metrics.pprof Enable pprof debug endpoints --p2p.bootnodes strings List of bootnodes in multiaddr format --p2p.dht-mode string DHT mode: auto, server, client, disabled (default "server") --p2p.listen string P2P listen address --p2p.mdns Enable mDNS discovery for P2P --retention.valset-epochs uint Number of historical validator set epochs to retain on fresh node startup (0 = unlimited) --secret-keys secret-key-slice Secret keys, comma separated {namespace}/{type}/{id}/{key},.. --signal.buffer-size int Signal buffer size (default 20) --signal.worker-count int Signal worker count (default 10) --storage-dir string Dir to store data (default ".data") --sync.enabled Enable signature syncer (default true) --sync.epochs uint Epochs to sync (default 5) --sync.period duration Signature sync period (default 5s) --sync.timeout duration Signature sync timeout (default 1m0s) ``` ```` ## File: docs/cli/utils/utils_keys_add.md ````markdown # `utils keys add` Command Reference ## utils keys add Add key ``` utils keys add [flags] ``` ### Options ``` --chain-id int16 chain id for evm keys, use 0 for default key for all chains (default -1) --evm use evm namespace keys --force force overwrite key --generate generate key -h, --help help for add --key-tag uint8 key tag for relay keys (default 255) --p2p use p2p key --private-key string private key to add in hex --relay use relay namespace keys ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --password string Keystore password -p, --path string Path to keystore (default "./keystore.jks") ``` ### SEE ALSO * [utils keys](utils_keys.md) - Keys tool ```` ## File: docs/cli/utils/utils_keys_list.md ````markdown # `utils keys list` Command Reference ## utils keys list Print all keys ``` utils keys list [flags] ``` ### Options ``` -h, --help help for list ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --password string Keystore password -p, --path string Path to keystore (default "./keystore.jks") ``` ### SEE ALSO * [utils keys](utils_keys.md) - Keys tool ```` ## File: docs/cli/utils/utils_keys_remove.md ````markdown # `utils keys remove` Command Reference ## utils keys remove Remove key ``` utils keys remove [flags] ``` ### Options ``` --chain-id int16 chain id for evm keys, use 0 for default key for all chains (default -1) --evm use evm namespace keys -h, --help help for remove --key-tag uint8 key tag for relay keys (default 255) --p2p use p2p key --relay use relay namespace keys ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --password string Keystore password -p, --path string Path to keystore (default "./keystore.jks") ``` ### SEE ALSO * [utils keys](utils_keys.md) - Keys tool ```` ## File: docs/cli/utils/utils_keys_update.md ````markdown # `utils keys update` Command Reference ## utils keys update Update key ``` utils keys update [flags] ``` ### Options ``` --chain-id int16 chain id for evm keys, use 0 for default key for all chains (default -1) --evm use evm namespace keys --force force overwrite key -h, --help help for update --key-tag uint8 key tag for relay keys (default 255) --p2p use p2p key --private-key string private key to add in hex --relay use relay namespace keys ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --password string Keystore password -p, --path string Path to keystore (default "./keystore.jks") ``` ### SEE ALSO * [utils keys](utils_keys.md) - Keys tool ```` ## File: docs/cli/utils/utils_keys.md ````markdown # `utils keys` Command Reference ## utils keys Keys tool ### Options ``` -h, --help help for keys --password string Keystore password -p, --path string Path to keystore (default "./keystore.jks") ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils](utils.md) - Utils tool * [utils keys add](utils_keys_add.md) - Add key * [utils keys list](utils_keys_list.md) - Print all keys * [utils keys remove](utils_keys_remove.md) - Remove key * [utils keys update](utils_keys_update.md) - Update key ```` ## File: docs/cli/utils/utils_network_generate-genesis.md ````markdown # `utils network generate-genesis` Command Reference ## utils network generate-genesis Generate genesis validator set header ``` utils network generate-genesis [flags] ``` ### Options ``` --commit Commit genesis flag -e, --epoch int Epoch to generate genesis for (default: current epoch - 1) (default -1) -h, --help help for generate-genesis -j, --json Print as json -o, --output string Output file path --secret-keys secretKeyMap Secret key for genesis commit in format 'chainId:key,chainId:key' (e.g. '1:0xabc,137:0xdef') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils network](utils_network.md) - Network tool ```` ## File: docs/cli/utils/utils_network_info.md ````markdown # `utils network info` Command Reference ## utils network info Print network information ``` utils network info [flags] ``` ### Options ``` -a, --addresses Print addresses -h, --help help for info -s, --settlement Print settlement info -v, --validators Print compact validators info -V, --validators-full Print full validators info ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id -e, --epoch uint Network epoch to fetch info --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils network](utils_network.md) - Network tool ```` ## File: docs/cli/utils/utils_network.md ````markdown # `utils network` Command Reference ## utils network Network tool ### Options ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id -e, --epoch uint Network epoch to fetch info -h, --help help for network ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils](utils.md) - Utils tool * [utils network generate-genesis](utils_network_generate-genesis.md) - Generate genesis validator set header * [utils network info](utils_network_info.md) - Print network information ```` ## File: docs/cli/utils/utils_operator_info.md ````markdown # `utils operator info` Command Reference ## utils operator info Print operator information ``` utils operator info [flags] ``` ### Options ``` -e, --epoch uint Network epoch to fetch info -h, --help help for info --key-tag uint8 key tag (default 255) --password string Keystore password -p, --path string Path to keystore (default "./keystore.jks") ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --voting-provider-chain-id uint Voting power provider chain id ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_invalidate-old-signatures.md ````markdown # `utils operator invalidate-old-signatures` Command Reference ## utils operator invalidate-old-signatures Invalidate old signatures for operator ``` utils operator invalidate-old-signatures [flags] ``` ### Options ``` -h, --help help for invalidate-old-signatures --secret-keys secretKeyMap Secret key for signing in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --voting-provider-chain-id uint Voting power provider chain id ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_register-key.md ````markdown # `utils operator register-key` Command Reference ## utils operator register-key Register operator key in key registry ``` utils operator register-key [flags] ``` ### Options ``` -h, --help help for register-key --key-tag uint8 key tag (default 255) --password string Keystore password -p, --path string Path to keystore (default "./keystore.jks") --secret-keys secretKeyMap Secret key for key register in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --voting-provider-chain-id uint Voting power provider chain id ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_register-operator-with-signature.md ````markdown # `utils operator register-operator-with-signature` Command Reference ## utils operator register-operator-with-signature Generate EIP-712 signature for operator registration ``` utils operator register-operator-with-signature [flags] ``` ### Options ``` -h, --help help for register-operator-with-signature --secret-keys secretKeyMap Secret key for signing in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --voting-provider-chain-id uint Voting power provider chain id ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_register-operator.md ````markdown # `utils operator register-operator` Command Reference ## utils operator register-operator Register operator on-chain via VotingPowerProvider ``` utils operator register-operator [flags] ``` ### Options ``` -h, --help help for register-operator --secret-keys secretKeyMap Secret key for operator in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --voting-provider-chain-id uint Voting power provider chain id ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_register-signature.md ````markdown # `utils operator register-signature` Command Reference ## utils operator register-signature Generate EIP-712 signature for operator registration ``` utils operator register-signature [flags] ``` ### Options ``` -h, --help help for register-signature --secret-keys secretKeyMap Secret key for signing in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_unregister-operator-with-signature.md ````markdown # `utils operator unregister-operator-with-signature` Command Reference ## utils operator unregister-operator-with-signature Generate EIP-712 signature for operator unregistration ``` utils operator unregister-operator-with-signature [flags] ``` ### Options ``` -h, --help help for unregister-operator-with-signature --secret-keys secretKeyMap Secret key for signing in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --voting-provider-chain-id uint Voting power provider chain id ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_unregister-operator.md ````markdown # `utils operator unregister-operator` Command Reference ## utils operator unregister-operator Unregister operator on-chain via VotingPowerProvider ``` utils operator unregister-operator [flags] ``` ### Options ``` -h, --help help for unregister-operator --secret-keys secretKeyMap Secret key for operator in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") --voting-provider-chain-id uint Voting power provider chain id ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator_unregister-signature.md ````markdown # `utils operator unregister-signature` Command Reference ## utils operator unregister-signature Generate EIP-712 signature for operator unregistration ``` utils operator unregister-signature [flags] ``` ### Options ``` -h, --help help for unregister-signature --secret-keys secretKeyMap Secret key for signing in format 'chainId:key' (e.g. '1:0xabc') ``` ### Options inherited from parent commands ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils operator](utils_operator.md) - Operator tool ```` ## File: docs/cli/utils/utils_operator.md ````markdown # `utils operator` Command Reference ## utils operator Operator tool ### Options ``` -c, --chains strings Chains rpc url, comma separated --driver.address string Driver contract address --driver.chainid uint Driver contract chain id -h, --help help for operator --voting-provider-chain-id uint Voting power provider chain id ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils](utils.md) - Utils tool * [utils operator info](utils_operator_info.md) - Print operator information * [utils operator invalidate-old-signatures](utils_operator_invalidate-old-signatures.md) - Invalidate old signatures for operator * [utils operator register-key](utils_operator_register-key.md) - Register operator key in key registry * [utils operator register-operator](utils_operator_register-operator.md) - Register operator on-chain via VotingPowerProvider * [utils operator register-operator-with-signature](utils_operator_register-operator-with-signature.md) - Generate EIP-712 signature for operator registration * [utils operator unregister-operator](utils_operator_unregister-operator.md) - Unregister operator on-chain via VotingPowerProvider * [utils operator unregister-operator-with-signature](utils_operator_unregister-operator-with-signature.md) - Generate EIP-712 signature for operator unregistration ```` ## File: docs/cli/utils/utils_version.md ````markdown # `utils version` Command Reference ## utils version Print the version of the utils tool ``` utils version [flags] ``` ### Options ``` -h, --help help for version ``` ### Options inherited from parent commands ``` --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils](utils.md) - Utils tool ```` ## File: docs/cli/utils/utils.md ````markdown # `utils` Command Reference ## utils Utils tool ### Options ``` -h, --help help for utils --log.level string log level(info, debug, warn, error) (default "info") --log.mode string log mode(pretty, text, json) (default "text") ``` ### SEE ALSO * [utils keys](utils_keys.md) - Keys tool * [utils network](utils_network.md) - Network tool * [utils operator](utils_operator.md) - Operator tool * [utils version](utils_version.md) - Print the version of the utils tool ```` ## File: e2e/scripts/deploy.sh ````bash #!/bin/sh set -e echo "Waiting for anvil to be ready..." until cast client --rpc-url http://anvil:8545 > /dev/null 2>&1; do sleep 1; done until cast client --rpc-url http://anvil-settlement:8546 > /dev/null 2>&1; do sleep 1; done echo "Deploying contracts..." forge script script/LocalDeploy.s.sol:LocalDeploy --rpc-url http://anvil:8545 -vv --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | tee /deploy-data/deployment.log forge script script/SettlementChainDeploy.s.sol:SettlementChainDeploy --rpc-url http://anvil-settlement:8546 -vv --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | tee /deploy-data/settlement-deployment.log forge script script/ValSetDriverDeploy.s.sol:ValSetDriverDeploy --rpc-url http://anvil:8545 -vv --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | tee /deploy-data/valsetdriver-deployment.log echo "Deploying multicall3 contracts..." cast send --rpc-url http://anvil:8545 0x05f32b3cc3888453ff71b01135b34ff8e41263f2 --value 100000000000000000 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 cast publish --rpc-url http://anvil:8545 0xf90f538085174876e800830f42408080b90f00608060405234801561001057600080fd5b50610ee0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c00331ca0edce47092c0f398cebf3ffc267f05c8e7076e3b89445e0fe50f6332273d4569ba01b0b9d000e19b24c5869b0fc3b22b0d6fa47cd63316875cbbd577d76e6fde086 cast send --rpc-url http://anvil-settlement:8546 0x05f32b3cc3888453ff71b01135b34ff8e41263f2 --value 100000000000000000 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 cast publish --rpc-url http://anvil-settlement:8546 0xf90f538085174876e800830f42408080b90f00608060405234801561001057600080fd5b50610ee0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c00331ca0edce47092c0f398cebf3ffc267f05c8e7076e3b89445e0fe50f6332273d4569ba01b0b9d000e19b24c5869b0fc3b22b0d6fa47cd63316875cbbd577d76e6fde086 echo 'Waiting for relay contracts file...' until [ -f /deploy-data/relay_contracts.json ]; do sleep 2; done echo "Setting interval mining..." BLOCK_TIME=${BLOCK_TIME:-1} cast rpc --rpc-url http://anvil:8545 evm_setIntervalMining $BLOCK_TIME cast rpc --rpc-url http://anvil-settlement:8546 evm_setIntervalMining $BLOCK_TIME echo "Mine a single block to finalize the deployment..." cast rpc --rpc-url http://anvil:8545 evm_mine cast rpc --rpc-url http://anvil-settlement:8546 evm_mine echo "Deployment completed successfully!" # Create deployment completion marker echo "$(date): Deployment completed successfully" > /deploy-data/deployment-complete.marker echo "Deployment completion marker created" ```` ## File: e2e/scripts/generate_network.sh ````bash #!/bin/bash # Symbiotic Network Infrastructure Generator # This script generates a Docker Compose setup for blockchain infrastructure # (anvil chains, deployer, genesis-generator) with configurable parameters # # Environment Variables: # OPERATORS - Number of operators (default: 4, max: 999) # COMMITERS - Number of commiters (default: 1) # AGGREGATORS - Number of aggregators (default: 1) # VERIFICATION_TYPE - Verification type: 0=BLS-BN254-ZK, 1=BLS-BN254-SIMPLE (default: 1) # EPOCH_TIME - Time for new epochs in relay network (default: 30) # BLOCK_TIME - Block time in seconds for anvil interval mining (default: 1) # FINALITY_BLOCKS - Number of blocks for finality (default: 1) # GENERATE_SIDECARS - Generate relay sidecar services (default: true) # # Example usage: # OPERATORS=6 COMMITERS=2 AGGREGATORS=1 VERIFICATION_TYPE=0 EPOCH_TIME=32 BLOCK_TIME=2 ./generate_network.sh # GENERATE_SIDECARS=false ./generate_network.sh # Skip generating relay sidecars set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Default values DEFAULT_OPERATORS=4 DEFAULT_COMMITERS=1 DEFAULT_AGGREGATORS=1 DEFAULT_VERIFICATION_TYPE=1 # BLS-BN254-SIMPLE DEFAULT_EPOCH_TIME=30 DEFAULT_BLOCK_TIME=1 DEFAULT_FINALITY_BLOCKS=2 DEFAULT_GENERATE_SIDECARS=false MAX_OPERATORS=999 print_status() { echo -e "${GREEN}[INFO]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } print_header() { echo -e "${BLUE}================================${NC}" echo -e "${BLUE}$1${NC}" echo -e "${BLUE}================================${NC}" } validate_number() { local num=$1 local name=$2 if ! [[ "$num" =~ ^[0-9]+$ ]] || [ "$num" -lt 1 ]; then print_error "$name must be a positive integer" exit 1 fi } validate_verification_type() { local type=$1 local name=$2 if ! [[ "$type" =~ ^[0-1]$ ]]; then print_error "$name must be 0 (BLS-BN254-ZK) or 1 (BLS-BN254-SIMPLE)" exit 1 fi } get_config_from_env() { echo print_header "Symbiotic Network Configuration" echo # Read from environment variables with defaults operators=${OPERATORS:-$DEFAULT_OPERATORS} commiters=${COMMITERS:-$DEFAULT_COMMITERS} aggregators=${AGGREGATORS:-$DEFAULT_AGGREGATORS} verification_type=${VERIFICATION_TYPE:-$DEFAULT_VERIFICATION_TYPE} epoch_size=${EPOCH_TIME:-$DEFAULT_EPOCH_TIME} block_time=${BLOCK_TIME:-$DEFAULT_BLOCK_TIME} finality_blocks=${FINALITY_BLOCKS:-$DEFAULT_FINALITY_BLOCKS} generate_sidecars=${GENERATE_SIDECARS:-$DEFAULT_GENERATE_SIDECARS} # Validate inputs validate_number "$operators" "Number of operators (OPERATORS env var)" validate_number "$commiters" "Number of commiters (COMMITERS env var)" validate_number "$aggregators" "Number of aggregators (AGGREGATORS env var)" validate_verification_type "$verification_type" "Verification type (VERIFICATION_TYPE env var)" validate_number "$epoch_size" "Epoch size (EPOCH_TIME env var)" validate_number "$block_time" "Block time (BLOCK_TIME env var)" validate_number "$finality_blocks" "Finality blocks (FINALITY_BLOCKS env var)" # Validate generate_sidecars is true or false if [[ "$generate_sidecars" != "true" && "$generate_sidecars" != "false" ]]; then print_error "GENERATE_SIDECARS must be 'true' or 'false', got: $generate_sidecars" exit 1 fi # Validate that commiters + aggregators <= operators total_special_roles=$((commiters + aggregators)) if [ "$total_special_roles" -gt "$operators" ]; then print_error "Total commiters ($commiters) + aggregators ($aggregators) cannot exceed total operators ($operators)" exit 1 fi if [ "$operators" -gt $MAX_OPERATORS ]; then print_error "Maximum $MAX_OPERATORS operators supported. Requested: $operators" exit 1 fi # Convert verification type to description local verification_desc case $verification_type in 0) verification_desc="BLS-BN254-ZK" ;; 1) verification_desc="BLS-BN254-SIMPLE" ;; esac print_status "Configuration (from environment variables):" print_status " Operators: $operators (OPERATORS=${OPERATORS:-default})" print_status " Committers: $commiters (COMMITERS=${COMMITERS:-default})" print_status " Aggregators: $aggregators (AGGREGATORS=${AGGREGATORS:-default})" print_status " Regular signers: $((operators - total_special_roles))" print_status " Verification type: $verification_type ($verification_desc) (VERIFICATION_TYPE=${VERIFICATION_TYPE:-default})" print_status " Epoch size: $epoch_size slots (EPOCH_TIME=${EPOCH_TIME:-default})" print_status " Block time: $block_time seconds (BLOCK_TIME=${BLOCK_TIME:-default})" print_status " Finality blocks: $finality_blocks (FINALITY_BLOCKS=${FINALITY_BLOCKS:-default})" print_status " Generate sidecars: $generate_sidecars (GENERATE_SIDECARS=${GENERATE_SIDECARS:-default})" } # Function to generate Docker Compose file generate_docker_compose() { local operators=$1 local commiters=$2 local aggregators=$3 local verification_type=$4 local epoch_size=$5 local block_time=$6 local finality_blocks=$7 local generate_sidecars=$8 local network_dir="temp-network" if [ -d "$network_dir" ]; then print_status "Cleaning up existing $network_dir directory..." rm -rf "$network_dir" fi mkdir -p "$network_dir/deploy-data" # Ensure deploy-data directory is writable for Docker containers chmod 777 "$network_dir/deploy-data" for i in $(seq 1 $operators); do local storage_dir="$network_dir/data-$(printf "%02d" $i)" mkdir -p "$storage_dir" # Make sure the directory is writable chmod 777 "$storage_dir" done local anvil_port=8545 local anvil_settlement_port=8546 local relay_start_port=8081 local sum_start_port=9091 # Calculate timestamp as current unix timestamp + 5 seconds local timestamp=$(($(date +%s) + 5)) cat > "$network_dir/docker-compose.yml" << EOF services: # Main Anvil local Ethereum network (Chain ID: 31337) anvil: image: ghcr.io/foundry-rs/foundry:v1.2.3 container_name: symbiotic-anvil entrypoint: ["anvil"] command: "--port 8545 --chain-id 31337 --timestamp $timestamp --auto-impersonate --slots-in-an-epoch $finality_blocks --accounts 10 --balance 10000 --gas-limit 30000000" environment: - ANVIL_IP_ADDR=0.0.0.0 ports: - "8545:8545" networks: - symbiotic-network healthcheck: test: ["CMD", "cast", "client", "--rpc-url", "http://localhost:8545"] interval: 2s timeout: 1s retries: 10 # Settlement Anvil local Ethereum network (Chain ID: 31338) anvil-settlement: image: ghcr.io/foundry-rs/foundry:v1.2.3 container_name: symbiotic-anvil-settlement entrypoint: ["anvil"] command: "--port 8546 --chain-id 31338 --timestamp $timestamp --auto-impersonate --slots-in-an-epoch $finality_blocks --accounts 10 --balance 10000 --gas-limit 30000000" environment: - ANVIL_IP_ADDR=0.0.0.0 ports: - "8546:8546" networks: - symbiotic-network healthcheck: test: ["CMD", "cast", "client", "--rpc-url", "http://localhost:8546"] interval: 2s timeout: 1s retries: 10 # Contract deployment service for main chain deployer: image: ghcr.io/foundry-rs/foundry:v1.3.0 container_name: symbiotic-deployer volumes: - ../contracts/:/app - ../scripts:/app/deploy-scripts - ../temp-network:/app/temp-network - ./deploy-data:/deploy-data working_dir: /app command: ./deploy-scripts/deploy.sh depends_on: anvil: condition: service_healthy anvil-settlement: condition: service_healthy networks: - symbiotic-network environment: - OPERATOR_COUNT=$operators - VERIFICATION_TYPE=$verification_type - BLOCK_TIME=$block_time - EPOCH_TIME=$epoch_size - FOUNDRY_CACHE_PATH=/tmp/.foundry-cache - NUM_AGGREGATORS=$aggregators - NUM_COMMITTERS=$commiters # Genesis generation service genesis-generator: image: relay_sidecar:dev container_name: symbiotic-genesis-generator volumes: - ../:/workspace - ./deploy-data:/deploy-data working_dir: /workspace command: ./scripts/genesis-generator.sh depends_on: deployer: condition: service_completed_successfully networks: - symbiotic-network EOF # Skip generating relay sidecars if disabled if [ "$generate_sidecars" = "false" ]; then print_status "Skipping relay sidecar generation (GENERATE_SIDECARS=false)" cat >> "$network_dir/docker-compose.yml" << EOF networks: symbiotic-network: driver: bridge EOF return fi local committer_count=0 local aggregator_count=0 local signer_count=0 # Calculate symb private key properly # ECDSA secp256k1 private keys must be 32 bytes (64 hex chars) and within range [1, n-1] # where n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 BASE_PRIVATE_KEY=1000000000000000000 for i in $(seq 1 $operators); do local port=$((relay_start_port + i - 1)) local storage_dir="data-$(printf "%02d" $i)" local key_index=$((i - 1)) SYMB_PRIVATE_KEY_DECIMAL=$(($BASE_PRIVATE_KEY + $key_index)) SYMB_SECONDARY_PRIVATE_KEY_DECIMAL=$(($BASE_PRIVATE_KEY + $key_index + 10000)) SYMB_PRIVATE_KEY_HEX=$(printf "%064x" $SYMB_PRIVATE_KEY_DECIMAL) SYMB_SECONDARY_PRIVATE_KEY_HEX=$(printf "%064x" $SYMB_SECONDARY_PRIVATE_KEY_DECIMAL) # Validate ECDSA secp256k1 private key range (must be between 1 and n-1) # Maximum valid key: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 if [ $SYMB_PRIVATE_KEY_DECIMAL -eq 0 ]; then echo "ERROR: Generated private key is zero (invalid for ECDSA)" exit 1 fi # Set circuits directory parameter based on verification type if [ "$verification_type" = "0" ]; then circuits_param="/app/circuits" else circuits_param="" fi cat >> "$network_dir/docker-compose.yml" << EOF # Relay sidecar $i relay-sidecar-$i: image: relay_sidecar:dev container_name: symbiotic-relay-$i command: - sh - -c - "chmod 777 /app/$storage_dir /deploy-data 2>/dev/null || true && /workspace/scripts/sidecar-start.sh symb/0/15/0x$SYMB_PRIVATE_KEY_HEX,symb/0/11/0x$SYMB_SECONDARY_PRIVATE_KEY_HEX,symb/1/0/0x$SYMB_PRIVATE_KEY_HEX,evm/1/31337/0x$SYMB_PRIVATE_KEY_HEX,evm/1/31338/0x$SYMB_PRIVATE_KEY_HEX,p2p/1/1/$SYMB_PRIVATE_KEY_HEX /app/$storage_dir $circuits_param" ports: - "$port:8080" volumes: - ../:/workspace - ./$storage_dir:/app/$storage_dir - ./deploy-data:/deploy-data EOF # Add circuits volume only if verification type is 0 if [ "$verification_type" = "0" ]; then cat >> "$network_dir/docker-compose.yml" << EOF - ./circuits:/app/circuits EOF fi cat >> "$network_dir/docker-compose.yml" << EOF depends_on: genesis-generator: condition: service_completed_successfully networks: - symbiotic-network restart: unless-stopped environment: - MAX_VALIDATORS=10,100 healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/healthz"] interval: 30s timeout: 10s retries: 3 start_period: 40s EOF done cat >> "$network_dir/docker-compose.yml" << EOF networks: symbiotic-network: driver: bridge EOF } # Main execution main() { print_header "Symbiotic Network Generator" # Check if required tools are available if ! command -v docker &> /dev/null; then print_error "Docker is not installed or not in PATH" exit 1 fi if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then print_error "Docker Compose is not installed or not in PATH" exit 1 fi get_config_from_env print_status "Generating Docker Compose configuration..." print_status "Creating $operators new operator accounts..." generate_docker_compose "$operators" "$commiters" "$aggregators" "$verification_type" "$epoch_size" "$block_time" "$finality_blocks" "$generate_sidecars" } main "$@" ```` ## File: e2e/scripts/genesis-generator.sh ````bash #!/bin/sh apk add --no-cache jq echo 'Waiting for deployment completion...' until [ -f /deploy-data/deployment-complete.marker ]; do sleep 2; done echo 'Waiting for relay contracts file...' until [ -f /deploy-data/relay_contracts.json ]; do sleep 2; done DRIVER_ADDRESS=$(jq -r '.driver.addr' /deploy-data/relay_contracts.json) echo "Driver address from relay_contracts.json: $DRIVER_ADDRESS" MAX_RETRIES=50 RETRY_DELAY=2 attempt=1 while [ $attempt -le $MAX_RETRIES ]; do echo "Attempt $attempt of $MAX_RETRIES: Generating network genesis..." if /app/relay_utils network \ --chains http://anvil:8545,http://anvil-settlement:8546 \ --driver.address "$DRIVER_ADDRESS" \ --driver.chainid 31337 \ generate-genesis \ --commit \ --secret-keys 31337:0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80,31338:0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80; then echo 'Genesis generation completed successfully!' # Create genesis completion marker echo "$(date): Genesis generation completed successfully" > /deploy-data/genesis-complete.marker echo "Genesis completion marker created" echo "Waiting few seconds before exiting..." sleep 5 exit 0 else echo "Genesis generation failed on attempt $attempt" if [ $attempt -lt $MAX_RETRIES ]; then echo "Waiting $RETRY_DELAY seconds before retry..." sleep $RETRY_DELAY else echo "All $MAX_RETRIES attempts failed. Exiting with error." exit 1 fi attempt=$((attempt + 1)) fi done ```` ## File: e2e/scripts/sidecar-start.sh ````bash #!/bin/sh apk add --no-cache jq echo "Waiting for relay_contracts.json file..." until [ -f /deploy-data/relay_contracts.json ]; do sleep 2; done DRIVER_ADDRESS=$(jq -r '.driver.addr' /deploy-data/relay_contracts.json) echo "Driver address from relay_contracts.json: $DRIVER_ADDRESS" cat > /tmp/sidecar.yaml << EOFCONFIG # Logging log: level: "debug" mode: "pretty" # API Server Configuration api: listen: ":8080" http-gateway: true # Metrics Configuration metrics: pprof: true # Driver Contract driver: chain-id: 31337 address: "$DRIVER_ADDRESS" # P2P Configuration p2p: listen: "/ip4/0.0.0.0/tcp/8880" bootnodes: - /dns4/relay-sidecar-1/tcp/8880/p2p/16Uiu2HAmFUiPYAJ7bE88Q8d7Kznrw5ifrje2e5QFyt7uFPk2G3iR dht-mode: "server" mdns: true # EVM Configuration evm: chains: - "http://anvil:8545" - "http://anvil-settlement:8546" max-calls: 30 # Retention config retention: valset-epochs: 5 EOFCONFIG # Ensure environment variables are explicitly preserved export MAX_VALIDATORS="${MAX_VALIDATORS:-}" # Handle optional circuits directory parameter if [ -n "$3" ] && [ -d "$3" ]; then echo "Using circuits directory: $3" echo "Starting relay_sidecar with MAX_VALIDATORS=$MAX_VALIDATORS" exec /app/relay_sidecar --config /tmp/sidecar.yaml --secret-keys "$1" --storage-dir "$2" --circuits-dir "$3" else echo "No circuits directory provided or directory doesn't exist, running without circuits" echo "Starting relay_sidecar with MAX_VALIDATORS=$MAX_VALIDATORS" exec /app/relay_sidecar --config /tmp/sidecar.yaml --secret-keys "$1" --storage-dir "$2" fi ```` ## File: e2e/tests/api_test.go ````go package tests ⋮---- import ( "context" "fmt" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/api/client/v1" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ) ⋮---- "context" "fmt" "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/api/client/v1" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ⋮---- // ContractExpectedData holds expected values derived from smart contracts type ContractExpectedData struct { CurrentEpoch symbiotic.Epoch EpochStartTime symbiotic.Timestamp CurrentEpochDuration uint64 ValidatorSet symbiotic.ValidatorSet NetworkConfig symbiotic.NetworkConfig IsEpochCommitted bool } ⋮---- // getExpectedDataFromContracts retrieves expected values directly from smart contracts func getExpectedDataFromContracts(t *testing.T, relayContracts RelayContractsData) *ContractExpectedData ⋮---- // Check if current epoch is committed ⋮---- // validateValidatorSetAgainstExpected compares API response with expected contract data func validateValidatorSetAgainstExpected(t *testing.T, apiResponse *apiv1.GetValidatorSetResponse, expected *ContractExpectedData) ⋮---- // TestRelayAPIConnectivity tests that all relay servers are accessible via gRPC func TestRelayAPIConnectivity(t *testing.T) ⋮---- // TestValidatorSetAPI tests the GetValidatorSet API endpoint func TestValidatorSetAPI(t *testing.T) ⋮---- const retryAttempts = 4 ⋮---- func TestAPIsSequence(t *testing.T) ⋮---- func testListenSignaturesAPI(t *testing.T) ⋮---- func testListenProofsAPI(t *testing.T) ⋮---- func testListenValidatorSetAPI(t *testing.T) ⋮---- func testGetSignaturesByEpochAPI(t *testing.T) ⋮---- // Verify request_id field is present in each signature ⋮---- func testGetAggregationProofsByEpochAPI(t *testing.T) ⋮---- // Verify request_id field is present in each proof ⋮---- func testGetValidatorByKeyAPI(t *testing.T) ⋮---- func testGetSignatureRequestIDsByEpochAPI(t *testing.T) ⋮---- // Verify each request ID is a valid hex hash ⋮---- func testGetSignatureRequestsByEpochAPI(t *testing.T) ⋮---- // Verify each signature request has valid fields ⋮---- // Verify request ID ⋮---- // Verify key tag ⋮---- // Verify message ⋮---- // Verify required epoch matches the requested epoch ⋮---- func testGetSignatureRequestAPI(t *testing.T) ⋮---- // First, get current epoch ⋮---- // Get signature request IDs for current epoch ⋮---- // Get the first signature request by ID ⋮---- // Verify request ID is included and matches ⋮---- // Verify other fields are populated ⋮---- func testGetLocalValidatorAPI(t *testing.T) ```` ## File: e2e/tests/epoch_test.go ````go package tests ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // TestEpochProgression tests that epochs progress correctly over time func TestEpochProgression(t *testing.T) ⋮---- // ensure the current epoch gets committed, timeout after 2x epoch time and error if still not committed ⋮---- // Check if the epoch has been committed ⋮---- // start watching for any new epochs being committed, will keep timeout to 5x the epoch duration ```` ## File: e2e/tests/genesis_test.go ````go package tests ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // TestGenesisDone tests that the genesis validator set header has been committed func TestGenesisDone(t *testing.T) ⋮---- // TestContractData tests that the data in the contract matches expected values func TestContractData(t *testing.T) ```` ## File: e2e/tests/http_gateway_test.go ````go package tests ⋮---- import ( "bufio" "context" "encoding/json" "errors" "fmt" "io" "net/http" "strings" "testing" "time" "github.com/stretchr/testify/require" "google.golang.org/protobuf/encoding/protojson" apiv1 "github.com/symbioticfi/relay/api/client/v1" ) ⋮---- "bufio" "context" "encoding/json" "errors" "fmt" "io" "net/http" "strings" "testing" "time" ⋮---- "github.com/stretchr/testify/require" "google.golang.org/protobuf/encoding/protojson" ⋮---- apiv1 "github.com/symbioticfi/relay/api/client/v1" ⋮---- // httpGatewayBaseURL constructs the base URL for HTTP gateway requests func httpGatewayBaseURL(t *testing.T) string ⋮---- // TestHTTPGateway_GetCurrentEpoch tests the HTTP gateway GET endpoint for current epoch func TestHTTPGateway_GetCurrentEpoch(t *testing.T) ⋮---- // Get expected data from gRPC API ⋮---- // Make HTTP request ⋮---- // Verify HTTP status ⋮---- // Verify Content-Type ⋮---- // Parse response using protobuf JSON unmarshaler ⋮---- var httpResult apiv1.GetCurrentEpochResponse ⋮---- // Verify response matches gRPC data ⋮---- // TestHTTPGateway_GetValidatorSet tests the HTTP gateway GET endpoint for validator set func TestHTTPGateway_GetValidatorSet(t *testing.T) ⋮---- var httpResult apiv1.GetValidatorSetResponse ⋮---- // TestHTTPGateway_StreamProofs tests the HTTP gateway streaming endpoint for proofs func TestHTTPGateway_StreamProofs(t *testing.T) ⋮---- // Make HTTP streaming request ⋮---- // Verify SSE Content-Type ⋮---- // Verify SSE headers ⋮---- // Read streaming responses with timeout ⋮---- // Channel to signal when we've read enough messages ⋮---- // Skip empty lines ⋮---- // Parse SSE format: "data: {...}" ⋮---- // Parse the wrapper to extract the result field var wrapper struct { Result json.RawMessage `json:"result"` } ⋮---- // Use protojson to unmarshal the result field var sseMessage apiv1.ListenProofsResponse ⋮---- // Verify message structure (log warnings instead of failing in goroutine) ⋮---- // Wait for messages or timeout ⋮---- // Successfully received messages ⋮---- // Timeout - this is OK if no proofs were generated during test ⋮---- // Check for scanner errors ⋮---- // Only fail if we didn't receive any messages ⋮---- // TestHTTPGateway_StreamSignatures tests the HTTP gateway streaming endpoint for signatures func TestHTTPGateway_StreamSignatures(t *testing.T) ⋮---- // Verify HTTP status and headers ⋮---- // Read a few messages to verify streaming ⋮---- var sseMessage apiv1.ListenSignaturesResponse ```` ## File: e2e/tests/metadata_test.go ````go package tests ⋮---- import ( "context" "fmt" "testing" "time" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/api/client/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "fmt" "testing" "time" ⋮---- "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/api/client/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // TestGetValidatorSetMetadata tests the GetValidatorSetMetadata API endpoint // and verifies that the request id can be used to retrieve the proof of a committed valset func TestGetValidatorSetMetadata(t *testing.T) ⋮---- // Get last committed epochs to find a committed epoch ≥1 for testing // We need committed epochs because that's when proofs and signatures are available var committedEpoch uint64 const maxRetries = 10 const retryDelay = 10 * time.Second ⋮---- // Find the minimum committed epoch across all chains that is ≥1 ⋮---- // Test 1: Get metadata for committed epoch (should work and have proofs/signatures) ⋮---- // Validate response structure ⋮---- // ExtraData can be empty, so we don't require it to be non-empty ⋮---- // Test 2: Use the request id to get signature request ⋮---- // Validate the signature request ⋮---- // Test 3: Get aggregation proof (should exist for committed epochs) ⋮---- // For committed epochs, aggregation proof should be available ⋮---- // Test 4: Get signatures for the request id (should exist for committed epochs) ⋮---- // For committed epochs, signatures should be available ⋮---- // Validate signatures structure ⋮---- // Test 5: Get metadata without specifying epoch (should use current epoch) ⋮---- // Test 6: Try to get metadata for a future epoch (should fail) ⋮---- // Get current epoch to determine what would be a future epoch ⋮---- // TestGetLastAllCommitted tests the GetLastAllCommitted API endpoint // and validates whether it returns proper epoch info for the contracts func TestGetLastAllCommitted(t *testing.T) ⋮---- // Get expected data from contracts to validate against ⋮---- // Test the GetLastAllCommitted API ⋮---- // Get current epoch for validation ⋮---- // Validate that we have epoch info for all settlement chains in the network config ⋮---- // Validate that the epoch is reasonable (not 0 and not way in the future) ⋮---- // Validate start time is reasonable (not zero and not in the future) ⋮---- // Test individual GetLastCommitted for each chain to ensure consistency ⋮---- // Compare with the result from GetLastAllCommitted ⋮---- // Test edge case: query for non-existent chain ```` ## File: e2e/tests/setup_test.go ````go package tests ⋮---- import ( "context" "encoding/hex" "fmt" "os" "path/filepath" "strings" "sync" "testing" "time" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" apiv1 "github.com/symbioticfi/relay/api/client/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "encoding/hex" "fmt" "os" "path/filepath" "strings" "sync" "testing" "time" ⋮---- "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ⋮---- apiv1 "github.com/symbioticfi/relay/api/client/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- var globalTestEnv *TestEnvironment ⋮---- func TestMain(m *testing.M) ⋮---- // Setup test environment before all tests var err error ⋮---- // Run all tests ⋮---- // Cleanup after all tests ⋮---- type RelaySidecarConfig struct { Keys string DataDir string ContainerName string RequiredSymKey crypto.PrivateKey } ⋮---- type TestEnvironment struct { Containers map[int]testcontainers.Container ContainerPorts map[int]string SidecarConfigs []RelaySidecarConfig } ⋮---- func generateSidecarConfigs(env EnvInfo) []RelaySidecarConfig ⋮---- const ( basePrivateKey = 1000000000000000000 ) ⋮---- // Generate key string in the same format as generate_network.sh ⋮---- func setupGlobalTestEnvironment() (*TestEnvironment, error) ⋮---- // Use the existing docker-compose network ⋮---- // Generate sidecar configurations based on environment variables ⋮---- // Get project root directory (assuming we're in e2e/tests/) ⋮---- // Start each relay sidecar container concurrently type containerResult struct { index int container testcontainers.Container port string } ⋮---- var wg sync.WaitGroup ⋮---- // Create data directory path ⋮---- var env map[string]string ⋮---- // Build the command to start the sidecar ⋮---- // Get the mapped port ⋮---- // Wait for all goroutines to complete ⋮---- // Check for errors ⋮---- // Collect results ⋮---- func cleanupGlobalTestEnvironment(env *TestEnvironment) ⋮---- // Stop and remove containers ⋮---- // Note: We don't remove the network since it might be used by docker-compose // The network will be cleaned up when docker-compose is stopped ⋮---- func (env *TestEnvironment) GetContainerPort(i int) string ⋮---- // Helper function to get container port func (env *TestEnvironment) GetHealthEndpoint(i int) string ⋮---- func (env *TestEnvironment) GetGRPCAddress(index int) string ⋮---- func (env *TestEnvironment) GetGRPCClient(t *testing.T, index int) *apiv1.SymbioticClient ```` ## File: e2e/tests/sidecar.yaml ````yaml # E2E Test Sidecar Configuration # Logging log: level: "debug" mode: "json" # API Server Configuration api: listen: ":8080" verbose-logging: false http-gateway: true # Metrics Configuration metrics: pprof: false # Driver Contract (address is set via command-line flag in tests) driver: chain-id: 31337 # P2P Configuration p2p: listen: "/ip4/0.0.0.0/tcp/8880" bootnodes: - /dns4/relay-sidecar-1/tcp/8880/p2p/16Uiu2HAmFUiPYAJ7bE88Q8d7Kznrw5ifrje2e5QFyt7uFPk2G3iR dht-mode: "server" mdns: true # EVM Configuration evm: chains: - "http://anvil:8545" - "http://anvil-settlement:8546" max-calls: 30 ```` ## File: e2e/tests/sign_test.go ````go package tests ⋮---- import ( "bytes" "context" "crypto/rand" "testing" "time" "github.com/ethereum/go-ethereum/crypto" "github.com/samber/lo" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/api/client/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" cryptoModule "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "bytes" "context" "crypto/rand" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/crypto" "github.com/samber/lo" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/api/client/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" cryptoModule "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- const ( defaultECDSAKeyTag = 16 secondaryBLSKeyTag = 11 ) ⋮---- // TestNonHeaderKeySignature tests signing with different non-header key types func TestNonHeaderKeySignature(t *testing.T) ⋮---- var resp *apiv1.SignMessageResponse // retry sign call 3 times as it can get transaction conflict ⋮---- // wait for signatures ⋮---- // expect all n signatures for ECDSA ⋮---- // need at least 2/3 signatures for BLS, signers skip signing is proof is already generated so we may not get all n sigs ⋮---- // verify signatures based on key type ⋮---- // ECDSA signature verification using ethereum crypto ⋮---- // the contract stores 32 bytes padded address for ecdsa addrs, // so stripping first 12 bytes to get to the address ⋮---- // Create public key from stored payload ⋮---- // Verify signature using BLS verification ⋮---- // check for proof var proof *apiv1.GetAggregationProofResponse ⋮---- // if it's ZK proof, poll for the proof to be generated for the epoch duration ```` ## File: e2e/tests/sync_test.go ````go package tests ⋮---- import ( "context" "net/http" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/api/client/v1" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ) ⋮---- "context" "net/http" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/api/client/v1" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ⋮---- // TestAggregatorSignatureSync tests that aggregators can sync missed signatures // and generate proofs even when they were offline during signature collection. // // Test scenario: // 1. Get current epoch from EVM client // 2. Stop all aggregators before signatures are generated // 3. Wait for next epoch to trigger signature generation by signers // 4. Verify signers have generated signatures // 5. Start aggregators back up // 6. Verify aggregators sync missed signatures and generate proofs func TestAggregatorSignatureSync(t *testing.T) ⋮---- // Load deployment data to get contract addresses and environment info ⋮---- // Identify aggregators ⋮---- var aggregatorIndexes []int ⋮---- // Step 1: Get current epoch from EVM client ⋮---- // Step 2: Stop all aggregator containers ⋮---- // Step 3: Wait for next epoch to trigger signature generation // During this time, signers will generate signatures but aggregators are offline ⋮---- // Step 4: Verify signers have generated signatures ⋮---- // Step 5: Start aggregators back up ⋮---- // Step 6: Verify aggregators have synced and generated proofs ⋮---- // Wait for aggregator to be healthy ⋮---- func waitForErrorIsNil(ctx context.Context, timeout time.Duration, f func() error) error ⋮---- // waitForHealthy polls a health endpoint until it returns 200 or timeout occurs func waitForHealthy(ctx context.Context, healthURL string, timeout time.Duration) error ⋮---- // createEVMClient creates an EVM client for interacting with the blockchain func createEVMClient(t *testing.T, deploymentData RelayContractsData) *evm.Client ⋮---- // waitForEpoch waits until the specified epoch is reached func waitForEpoch(ctx context.Context, client evm.IEvmClient, targetEpoch symbiotic.Epoch, timeout time.Duration) error ⋮---- // Continue trying on error, but log it ```` ## File: e2e/tests/types_test.go ````go package tests ⋮---- import ( "context" "encoding/json" "os" "time" "github.com/go-errors/errors" "github.com/kelseyhightower/envconfig" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "encoding/json" "os" "time" ⋮---- "github.com/go-errors/errors" "github.com/kelseyhightower/envconfig" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- var ( settlementChains = []string{ "http://localhost:8545", // Main anvil chain "http://localhost:8546", // Settlement anvil chain } ) ⋮---- "http://localhost:8545", // Main anvil chain "http://localhost:8546", // Settlement anvil chain ⋮---- // RelayServerEndpoint represents a relay server endpoint for testing type RelayServerEndpoint struct { Address string Port string Role string // "committer", "aggregator", "signer" } ⋮---- Role string // "committer", "aggregator", "signer" ⋮---- // ContractAddress represents a contract address with chain ID type ContractAddress struct { Addr string `json:"addr"` ChainId uint64 `json:"chainId"` } ⋮---- // RelayContractsData represents the structure from relay_contracts.json type RelayContractsData struct { Driver ContractAddress `json:"driver"` KeyRegistry ContractAddress `json:"keyRegistry"` Network string `json:"network"` Settlements []ContractAddress `json:"settlements"` StakingTokens []ContractAddress `json:"stakingTokens"` VotingPowerProviders []ContractAddress `json:"votingPowerProviders"` Env EnvInfo `json:"-"` } ⋮---- type EnvInfo struct { Operators int64 `default:"4" split_words:"true"` Commiters int64 `default:"1" split_words:"true"` Aggregators int64 `default:"1" split_words:"true"` EpochTime uint64 `default:"30" split_words:"true"` VerificationType uint32 `default:"1" split_words:"true"` } ⋮---- // GetDriverAddress returns the driver address as a string for backward compatibility func (d RelayContractsData) GetDriverAddress() string ⋮---- // GetKeyRegistryAddress returns the key registry address as a string func (d RelayContractsData) GetKeyRegistryAddress() string ⋮---- // GetVotingPowerProviderAddress returns the first voting power provider address func (d RelayContractsData) GetVotingPowerProviderAddress() string ⋮---- // GetSettlementAddresses returns all settlement addresses func (d RelayContractsData) GetSettlementAddresses() []ContractAddress ⋮---- func loadDeploymentData(ctx context.Context) (RelayContractsData, error) ⋮---- // Wait for relay_contracts.json to be created by shell script const maxWaitTime = 60 * time.Second const checkInterval = 500 * time.Millisecond ⋮---- break // File exists, break the loop ⋮---- var relayContracts RelayContractsData ⋮---- // testMockKeyProvider is a mock key provider for testing type testMockKeyProvider struct{} ⋮---- func (m *testMockKeyProvider) GetPrivateKey(_ symbiotic.KeyTag) (symbioticCrypto.PrivateKey, error) ⋮---- func (m *testMockKeyProvider) GetPrivateKeyByAlias(_ string) (symbioticCrypto.PrivateKey, error) ⋮---- func (m *testMockKeyProvider) GetPrivateKeyByNamespaceTypeId(_ string, _ symbiotic.KeyType, _ int) (symbioticCrypto.PrivateKey, error) ⋮---- func (m *testMockKeyProvider) HasKey(_ symbiotic.KeyTag) (bool, error) ⋮---- func (m *testMockKeyProvider) HasKeyByAlias(_ string) (bool, error) ⋮---- func (m *testMockKeyProvider) HasKeyByNamespaceTypeId(_ string, _ symbiotic.KeyType, _ int) (bool, error) ```` ## File: e2e/README.md ````markdown # E2E Testing Guide This directory contains end-to-end tests for the Symbiotic Relay project. The tests run against a local blockchain network with configurable relay operators, commiters, and aggregators. ## Prerequisites - Docker and Docker Compose - Go 1.25+ - Node.js and npm (for smart contract compilation) - Foundry (forge) for contract building ## Quick Start 1. **Setup the test environment:** ```bash ./setup.sh ``` 2. **Start the network:** ```bash cd temp-network docker compose up -d cd .. ``` 3. **Run the tests:** ```bash cd tests go test -v ``` ## Configuration You can customize the test environment by setting environment variables before running `setup.sh`. All variables have sensible defaults. ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `OPERATORS` | `4` | Number of relay operators (max: 999) | | `COMMITERS` | `1` | Number of commiter nodes | | `AGGREGATORS` | `1` | Number of aggregator nodes | | `VERIFICATION_TYPE` | `1` | Verification type: `0`=BLS-BN254-ZK, `1`=BLS-BN254-SIMPLE | | `EPOCH_TIME` | `30` | Time for new epochs in relay network (seconds) | | `BLOCK_TIME` | `1` | Block time in seconds for anvil interval mining | | `FINALITY_BLOCKS` | `2` | Number of blocks for finality | ### Example with Custom Configuration ```bash # Set custom configuration export OPERATORS=6 export COMMITERS=2 export AGGREGATORS=1 export VERIFICATION_TYPE=0 export EPOCH_TIME=32 export BLOCK_TIME=2 # Run setup ./setup.sh # Start network cd temp-network docker compose up -d cd .. # Run tests cd tests go test -v ``` ## Contract Information The tests use smart contracts from the Symbiotic protocol: - **Repository**: https://github.com/symbioticfi/symbiotic-super-sum The commit hash can be updated in `setup.sh` if needed for testing against different contract versions. ```` ## File: e2e/setup.sh ````bash #!/bin/bash set -eo pipefail # Configuration # Contracts commit hash to use CONTRACTS_COMMIT="24bcb351c8b6125b0412d5bf7916da405c548000" # Circuits commit CIRCUITS_COMMIT="e2e-branch" # ----------------------------------------- echo "Building Relay Docker image for e2e tests..." # go to root of repo cd .. make image TAG=dev # get back into e2e cd e2e # Check if temp-network directory exists and clean up any running containers if [ -d "temp-network" ]; then echo "Found existing temp-network directory. Attempting to clean up running containers..." cd temp-network if ! docker compose down; then echo "WARNING: Failed to run 'docker compose down' in temp-network directory." echo "Please manually clean up the temp-network directory and any running containers before proceeding." echo "You can try: cd temp-network && docker compose down --remove-orphans && cd .. && rm -rf temp-network" exit 1 fi cd .. echo "Successfully cleaned up existing containers." fi echo "Setting up Symbiotic contracts..." if [ ! -d "contracts" ]; then echo "Cloning Symbiotic contracts repository..." git clone https://github.com/symbioticfi/symbiotic-super-sum contracts else echo "Contracts directory already exists, skipping clone..." fi cd contracts git fetch origin git checkout $CONTRACTS_COMMIT echo "Installing dependencies..." npm install echo "Building contracts..." forge build cd .. # Pass through all environment variables to generate_network.sh with defaults export OPERATORS=${OPERATORS} export COMMITERS=${COMMITERS} export AGGREGATORS=${AGGREGATORS} export VERIFICATION_TYPE=${VERIFICATION_TYPE} export EPOCH_TIME=${EPOCH_TIME} export BLOCK_TIME=${BLOCK_TIME} export FINALITY_BLOCKS=${FINALITY_BLOCKS} export GENERATE_SIDECARS=${GENERATE_SIDECARS} # Call the generate network script ./scripts/generate_network.sh # If verification type is 0, clone the circuit keys repository if [ "${VERIFICATION_TYPE}" = "0" ]; then echo "Verification type is 0, cloning circuit keys repository..." if [ ! -d "temp-network/circuits" ]; then echo "Cloning circuit keys repository (shallow clone of specific commit)..." # Create circuits directory in temp-network mkdir -p temp-network/circuits cd temp-network/circuits # Initialize empty git repo and add remote git init git remote add origin https://github.com/symbioticfi/relay-bn254-example-circuit-keys # Fetch only the specific commit (shallow) with parallel jobs for speed git fetch --depth 1 --jobs=4 origin $CIRCUITS_COMMIT git checkout FETCH_HEAD # Remove git metadata to keep only the files rm -rf .git cd ../.. echo "Circuit keys cloned successfully to temp-network/circuits/" else echo "Circuits directory already exists in temp-network, skipping clone..." fi echo "Copying circuits to contracts directory and building..." cp -r temp-network/circuits contracts/circuits cd contracts echo "Building circuits with Forge..." forge build circuits/ else echo "Verification type is not 0, skipping circuit keys clone..." fi echo "Setup complete! Network configuration generated in temp-network/ directory." ```` ## File: hack/codegen/generate-client-types.go ````go package main ⋮---- // generate-client-types is a tool to parse the generated protobuf file and create a client types file // that exports types for client usage, including enums, requests, responses, and data types. ⋮---- import ( "fmt" "go/ast" "go/parser" "go/token" "os" "regexp" "sort" "strings" ) ⋮---- "fmt" "go/ast" "go/parser" "go/token" "os" "regexp" "sort" "strings" ⋮---- const clientTemplate = `// Code generated by generate-client-types. DO NOT EDIT. package v1 import ( apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" ) // Exported types for client usage %s ` ⋮---- type TypeInfo struct { Name string Category string IsEnum bool Constants []string } ⋮---- func main() ⋮---- // Parse the generated protobuf file ⋮---- // Generate the client file content ⋮---- // Write to client file ⋮---- func parseGeneratedFile(filename string) ([]TypeInfo, error) ⋮---- // Read the file content ⋮---- // Parse using AST ⋮---- var types []TypeInfo ⋮---- // Walk the AST to find type declarations ⋮---- // Skip internal/private types ⋮---- // Determine type category and if it's an enum ⋮---- // Check if it's an enum (int32 type) ⋮---- func isExportedType(typeName string) bool ⋮---- // Skip internal protobuf types and unexported types ⋮---- func categorizeStruct(typeName string) string ⋮---- return "response" // ErrorResponse goes with responses ⋮---- func findEnumConstants(content, enumName string) []string ⋮---- var constants []string ⋮---- // Use regex to find enum constants ⋮---- func generateClientContent(types []TypeInfo) string ⋮---- var sections []string ⋮---- // Group types by category ⋮---- // Sort each category ⋮---- // Generate enums section ⋮---- // Generate enum constants ⋮---- // Generate request types section ⋮---- // Generate response types section ⋮---- // Generate data types section ⋮---- func hasEnumConstants(enums []TypeInfo) bool ```` ## File: hack/docgen/generate-cli-docs.go ````go package main ⋮---- import ( "fmt" "log" "os" "path/filepath" "strings" "github.com/spf13/cobra/doc" relay "github.com/symbioticfi/relay/cmd/relay/root" utils "github.com/symbioticfi/relay/cmd/utils/root" ) ⋮---- "fmt" "log" "os" "path/filepath" "strings" ⋮---- "github.com/spf13/cobra/doc" relay "github.com/symbioticfi/relay/cmd/relay/root" utils "github.com/symbioticfi/relay/cmd/utils/root" ⋮---- func main() ⋮---- // The default header looks like `Argocd app get`. The leading capital letter is off-putting. // This header overrides the default. It's better visually and for search results. ⋮---- filename = filename[:len(filename)-3] // Drop the '.md' ⋮---- // Create docs/cli directory ⋮---- // Disable auto-generated timestamp line ```` ## File: internal/client/p2p/proto/v1/message_grpc.pb.go ````go // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 // - protoc (unknown) // source: v1/message.proto ⋮---- package v1 ⋮---- import ( context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ) ⋮---- context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ⋮---- // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. // Requires gRPC-Go v1.64.0 or later. const _ = grpc.SupportPackageIsVersion9 ⋮---- const ( SymbioticP2PService_WantSignatures_FullMethodName = "/internal.client.p2p.proto.v1.SymbioticP2PService/WantSignatures" SymbioticP2PService_WantAggregationProofs_FullMethodName = "/internal.client.p2p.proto.v1.SymbioticP2PService/WantAggregationProofs" ) ⋮---- // SymbioticP2PServiceClient is the client API for SymbioticP2PService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type SymbioticP2PServiceClient interface { WantSignatures(ctx context.Context, in *WantSignaturesRequest, opts ...grpc.CallOption) (*WantSignaturesResponse, error) WantAggregationProofs(ctx context.Context, in *WantAggregationProofsRequest, opts ...grpc.CallOption) (*WantAggregationProofsResponse, error) } ⋮---- type symbioticP2PServiceClient struct { cc grpc.ClientConnInterface } ⋮---- func NewSymbioticP2PServiceClient(cc grpc.ClientConnInterface) SymbioticP2PServiceClient ⋮---- func (c *symbioticP2PServiceClient) WantSignatures(ctx context.Context, in *WantSignaturesRequest, opts ...grpc.CallOption) (*WantSignaturesResponse, error) ⋮---- func (c *symbioticP2PServiceClient) WantAggregationProofs(ctx context.Context, in *WantAggregationProofsRequest, opts ...grpc.CallOption) (*WantAggregationProofsResponse, error) ⋮---- // SymbioticP2PServiceServer is the server API for SymbioticP2PService service. // All implementations must embed UnimplementedSymbioticP2PServiceServer // for forward compatibility. type SymbioticP2PServiceServer interface { WantSignatures(context.Context, *WantSignaturesRequest) (*WantSignaturesResponse, error) WantAggregationProofs(context.Context, *WantAggregationProofsRequest) (*WantAggregationProofsResponse, error) mustEmbedUnimplementedSymbioticP2PServiceServer() } ⋮---- // UnimplementedSymbioticP2PServiceServer must be embedded to have // forward compatible implementations. ⋮---- // NOTE: this should be embedded by value instead of pointer to avoid a nil // pointer dereference when methods are called. type UnimplementedSymbioticP2PServiceServer struct{} ⋮---- func (UnimplementedSymbioticP2PServiceServer) mustEmbedUnimplementedSymbioticP2PServiceServer() func (UnimplementedSymbioticP2PServiceServer) testEmbeddedByValue() ⋮---- // UnsafeSymbioticP2PServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to SymbioticP2PServiceServer will // result in compilation errors. type UnsafeSymbioticP2PServiceServer interface { mustEmbedUnimplementedSymbioticP2PServiceServer() } ⋮---- func RegisterSymbioticP2PServiceServer(s grpc.ServiceRegistrar, srv SymbioticP2PServiceServer) ⋮---- // If the following call pancis, it indicates UnimplementedSymbioticP2PServiceServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. ⋮---- func _SymbioticP2PService_WantSignatures_Handler(srv interface ⋮---- func _SymbioticP2PService_WantAggregationProofs_Handler(srv interface ⋮---- // SymbioticP2PService_ServiceDesc is the grpc.ServiceDesc for SymbioticP2PService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var SymbioticP2PService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "internal.client.p2p.proto.v1.SymbioticP2PService", HandlerType: (*SymbioticP2PServiceServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "WantSignatures", Handler: _SymbioticP2PService_WantSignatures_Handler, }, { MethodName: "WantAggregationProofs", Handler: _SymbioticP2PService_WantAggregationProofs_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "v1/message.proto", } ```` ## File: internal/client/p2p/proto/v1/message.pb.go ````go // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.6 // protoc (unknown) // source: v1/message.proto ⋮---- package v1 ⋮---- import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" unsafe "unsafe" ) ⋮---- protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" unsafe "unsafe" ⋮---- const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ⋮---- // Verify that this generated code is sufficiently up-to-date. ⋮---- // Verify that runtime/protoimpl is sufficiently up-to-date. ⋮---- // AggregationProof represents the aggregated signatures message type AggregationProof struct { state protoimpl.MessageState `protogen:"open.v1"` KeyTag uint32 `protobuf:"varint,2,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` MessageHash []byte `protobuf:"bytes,4,opt,name=message_hash,json=messageHash,proto3" json:"message_hash,omitempty"` Proof []byte `protobuf:"bytes,5,opt,name=proof,proto3" json:"proof,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- func (x *AggregationProof) Reset() ⋮---- func (x *AggregationProof) String() string ⋮---- func (*AggregationProof) ProtoMessage() ⋮---- func (x *AggregationProof) ProtoReflect() protoreflect.Message ⋮---- // Deprecated: Use AggregationProof.ProtoReflect.Descriptor instead. func (*AggregationProof) Descriptor() ([]byte, []int) ⋮---- func (x *AggregationProof) GetKeyTag() uint32 ⋮---- func (x *AggregationProof) GetEpoch() uint64 ⋮---- func (x *AggregationProof) GetMessageHash() []byte ⋮---- func (x *AggregationProof) GetProof() []byte ⋮---- // P2PMessage represents a peer-to-peer message wrapper type P2PMessage struct { state protoimpl.MessageState `protogen:"open.v1"` Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use P2PMessage.ProtoReflect.Descriptor instead. ⋮---- func (x *P2PMessage) GetSender() string ⋮---- func (x *P2PMessage) GetTimestamp() int64 ⋮---- func (x *P2PMessage) GetData() []byte ⋮---- type WantSignaturesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Map of request id to bitmap of wanted validator indices WantSignatures map[string][]byte `protobuf:"bytes,1,rep,name=want_signatures,json=wantSignatures,proto3" json:"want_signatures,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // key: hex string of common.Hash, value: roaring bitmap bytes unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Map of request id to bitmap of wanted validator indices WantSignatures map[string][]byte `protobuf:"bytes,1,rep,name=want_signatures,json=wantSignatures,proto3" json:"want_signatures,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // key: hex string of common.Hash, value: roaring bitmap bytes ⋮---- // Deprecated: Use WantSignaturesRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *WantSignaturesRequest) GetWantSignatures() map[string][]byte ⋮---- type WantSignaturesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Map of request id to list of validator signatures Signatures map[string]*ValidatorSignatureList `protobuf:"bytes,2,rep,name=signatures,proto3" json:"signatures,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // key: hex string of common.Hash unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Map of request id to list of validator signatures Signatures map[string]*ValidatorSignatureList `protobuf:"bytes,2,rep,name=signatures,proto3" json:"signatures,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // key: hex string of common.Hash ⋮---- // Deprecated: Use WantSignaturesResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *WantSignaturesResponse) GetSignatures() map[string]*ValidatorSignatureList ⋮---- // ValidatorSignatureList contains a list of validator signatures for a specific request type ValidatorSignatureList struct { state protoimpl.MessageState `protogen:"open.v1"` Signatures []*ValidatorSignature `protobuf:"bytes,1,rep,name=signatures,proto3" json:"signatures,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ValidatorSignatureList.ProtoReflect.Descriptor instead. ⋮---- // ValidatorSignature pairs a signature with its validator index type ValidatorSignature struct { state protoimpl.MessageState `protogen:"open.v1"` ValidatorIndex uint32 `protobuf:"varint,1,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty"` Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ValidatorSignature.ProtoReflect.Descriptor instead. ⋮---- func (x *ValidatorSignature) GetValidatorIndex() uint32 ⋮---- func (x *ValidatorSignature) GetSignature() *Signature ⋮---- // Signature represents extended signature data type Signature struct { state protoimpl.MessageState `protogen:"open.v1"` MessageHash []byte `protobuf:"bytes,1,opt,name=message_hash,json=messageHash,proto3" json:"message_hash,omitempty"` KeyTag uint32 `protobuf:"varint,2,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` PublicKey []byte `protobuf:"bytes,5,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use Signature.ProtoReflect.Descriptor instead. ⋮---- func (x *Signature) GetPublicKey() []byte ⋮---- type WantAggregationProofsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // List of request ids for which aggregation proofs are needed RequestIds []string `protobuf:"bytes,1,rep,name=request_ids,json=requestIds,proto3" json:"request_ids,omitempty"` // hex strings of common.Hash unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // List of request ids for which aggregation proofs are needed RequestIds []string `protobuf:"bytes,1,rep,name=request_ids,json=requestIds,proto3" json:"request_ids,omitempty"` // hex strings of common.Hash ⋮---- // Deprecated: Use WantAggregationProofsRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *WantAggregationProofsRequest) GetRequestIds() []string ⋮---- type WantAggregationProofsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Map of request ids to aggregation proof Proofs map[string]*AggregationProof `protobuf:"bytes,1,rep,name=proofs,proto3" json:"proofs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // key: hex string of common.Hash unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Map of request ids to aggregation proof Proofs map[string]*AggregationProof `protobuf:"bytes,1,rep,name=proofs,proto3" json:"proofs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // key: hex string of common.Hash ⋮---- // Deprecated: Use WantAggregationProofsResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *WantAggregationProofsResponse) GetProofs() map[string]*AggregationProof ⋮---- var File_v1_message_proto protoreflect.FileDescriptor ⋮---- const file_v1_message_proto_rawDesc = "" + "\n" + "\x10v1/message.proto\x12\x1cinternal.client.p2p.proto.v1\"z\n" + "\x10AggregationProof\x12\x17\n" + "\akey_tag\x18\x02 \x01(\rR\x06keyTag\x12\x14\n" + "\x05epoch\x18\x03 \x01(\x04R\x05epoch\x12!\n" + "\fmessage_hash\x18\x04 \x01(\fR\vmessageHash\x12\x14\n" + "\x05proof\x18\x05 \x01(\fR\x05proof\"V\n" + "\n" + "P2PMessage\x12\x16\n" + "\x06sender\x18\x01 \x01(\tR\x06sender\x12\x1c\n" + "\ttimestamp\x18\x02 \x01(\x03R\ttimestamp\x12\x12\n" + "\x04data\x18\x03 \x01(\fR\x04data\"\xcc\x01\n" + "\x15WantSignaturesRequest\x12p\n" + "\x0fwant_signatures\x18\x01 \x03(\v2G.internal.client.p2p.proto.v1.WantSignaturesRequest.WantSignaturesEntryR\x0ewantSignatures\x1aA\n" + "\x13WantSignaturesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\xf3\x01\n" + "\x16WantSignaturesResponse\x12d\n" + "\n" + "signatures\x18\x02 \x03(\v2D.internal.client.p2p.proto.v1.WantSignaturesResponse.SignaturesEntryR\n" + "signatures\x1as\n" + "\x0fSignaturesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12J\n" + "\x05value\x18\x02 \x01(\v24.internal.client.p2p.proto.v1.ValidatorSignatureListR\x05value:\x028\x01\"j\n" + "\x16ValidatorSignatureList\x12P\n" + "\n" + "signatures\x18\x01 \x03(\v20.internal.client.p2p.proto.v1.ValidatorSignatureR\n" + "signatures\"\x84\x01\n" + "\x12ValidatorSignature\x12'\n" + "\x0fvalidator_index\x18\x01 \x01(\rR\x0evalidatorIndex\x12E\n" + "\tsignature\x18\x02 \x01(\v2'.internal.client.p2p.proto.v1.SignatureR\tsignature\"\x9a\x01\n" + "\tSignature\x12!\n" + "\fmessage_hash\x18\x01 \x01(\fR\vmessageHash\x12\x17\n" + "\akey_tag\x18\x02 \x01(\rR\x06keyTag\x12\x14\n" + "\x05epoch\x18\x03 \x01(\x04R\x05epoch\x12\x1c\n" + "\tsignature\x18\x04 \x01(\fR\tsignature\x12\x1d\n" + "\n" + "public_key\x18\x05 \x01(\fR\tpublicKey\"?\n" + "\x1cWantAggregationProofsRequest\x12\x1f\n" + "\vrequest_ids\x18\x01 \x03(\tR\n" + "requestIds\"\xeb\x01\n" + "\x1dWantAggregationProofsResponse\x12_\n" + "\x06proofs\x18\x01 \x03(\v2G.internal.client.p2p.proto.v1.WantAggregationProofsResponse.ProofsEntryR\x06proofs\x1ai\n" + "\vProofsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12D\n" + "\x05value\x18\x02 \x01(\v2..internal.client.p2p.proto.v1.AggregationProofR\x05value:\x028\x012\xa5\x02\n" + "\x13SymbioticP2PService\x12{\n" + "\x0eWantSignatures\x123.internal.client.p2p.proto.v1.WantSignaturesRequest\x1a4.internal.client.p2p.proto.v1.WantSignaturesResponse\x12\x90\x01\n" + "\x15WantAggregationProofs\x12:.internal.client.p2p.proto.v1.WantAggregationProofsRequest\x1a;.internal.client.p2p.proto.v1.WantAggregationProofsResponseB\x80\x02\n" + " com.internal.client.p2p.proto.v1B\fMessageProtoP\x01Z9github.com/symbioticfi/relay/internal/client/p2p/proto/v1\xa2\x02\x04ICPP\xaa\x02\x1cInternal.Client.P2p.Proto.V1\xca\x02\x1cInternal\\Client\\P2p\\Proto\\V1\xe2\x02(Internal\\Client\\P2p\\Proto\\V1\\GPBMetadata\xea\x02 Internal::Client::P2p::Proto::V1b\x06proto3" ⋮---- var ( file_v1_message_proto_rawDescOnce sync.Once file_v1_message_proto_rawDescData []byte ) ⋮---- func file_v1_message_proto_rawDescGZIP() []byte ⋮---- var file_v1_message_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_v1_message_proto_goTypes = []any{ (*AggregationProof)(nil), // 0: internal.client.p2p.proto.v1.AggregationProof (*P2PMessage)(nil), // 1: internal.client.p2p.proto.v1.P2PMessage (*WantSignaturesRequest)(nil), // 2: internal.client.p2p.proto.v1.WantSignaturesRequest (*WantSignaturesResponse)(nil), // 3: internal.client.p2p.proto.v1.WantSignaturesResponse (*ValidatorSignatureList)(nil), // 4: internal.client.p2p.proto.v1.ValidatorSignatureList (*ValidatorSignature)(nil), // 5: internal.client.p2p.proto.v1.ValidatorSignature (*Signature)(nil), // 6: internal.client.p2p.proto.v1.Signature (*WantAggregationProofsRequest)(nil), // 7: internal.client.p2p.proto.v1.WantAggregationProofsRequest (*WantAggregationProofsResponse)(nil), // 8: internal.client.p2p.proto.v1.WantAggregationProofsResponse nil, // 9: internal.client.p2p.proto.v1.WantSignaturesRequest.WantSignaturesEntry nil, // 10: internal.client.p2p.proto.v1.WantSignaturesResponse.SignaturesEntry nil, // 11: internal.client.p2p.proto.v1.WantAggregationProofsResponse.ProofsEntry } ⋮---- (*AggregationProof)(nil), // 0: internal.client.p2p.proto.v1.AggregationProof (*P2PMessage)(nil), // 1: internal.client.p2p.proto.v1.P2PMessage (*WantSignaturesRequest)(nil), // 2: internal.client.p2p.proto.v1.WantSignaturesRequest (*WantSignaturesResponse)(nil), // 3: internal.client.p2p.proto.v1.WantSignaturesResponse (*ValidatorSignatureList)(nil), // 4: internal.client.p2p.proto.v1.ValidatorSignatureList (*ValidatorSignature)(nil), // 5: internal.client.p2p.proto.v1.ValidatorSignature (*Signature)(nil), // 6: internal.client.p2p.proto.v1.Signature (*WantAggregationProofsRequest)(nil), // 7: internal.client.p2p.proto.v1.WantAggregationProofsRequest (*WantAggregationProofsResponse)(nil), // 8: internal.client.p2p.proto.v1.WantAggregationProofsResponse nil, // 9: internal.client.p2p.proto.v1.WantSignaturesRequest.WantSignaturesEntry nil, // 10: internal.client.p2p.proto.v1.WantSignaturesResponse.SignaturesEntry nil, // 11: internal.client.p2p.proto.v1.WantAggregationProofsResponse.ProofsEntry ⋮---- var file_v1_message_proto_depIdxs = []int32{ 9, // 0: internal.client.p2p.proto.v1.WantSignaturesRequest.want_signatures:type_name -> internal.client.p2p.proto.v1.WantSignaturesRequest.WantSignaturesEntry 10, // 1: internal.client.p2p.proto.v1.WantSignaturesResponse.signatures:type_name -> internal.client.p2p.proto.v1.WantSignaturesResponse.SignaturesEntry 5, // 2: internal.client.p2p.proto.v1.ValidatorSignatureList.signatures:type_name -> internal.client.p2p.proto.v1.ValidatorSignature 6, // 3: internal.client.p2p.proto.v1.ValidatorSignature.signature:type_name -> internal.client.p2p.proto.v1.Signature 11, // 4: internal.client.p2p.proto.v1.WantAggregationProofsResponse.proofs:type_name -> internal.client.p2p.proto.v1.WantAggregationProofsResponse.ProofsEntry 4, // 5: internal.client.p2p.proto.v1.WantSignaturesResponse.SignaturesEntry.value:type_name -> internal.client.p2p.proto.v1.ValidatorSignatureList 0, // 6: internal.client.p2p.proto.v1.WantAggregationProofsResponse.ProofsEntry.value:type_name -> internal.client.p2p.proto.v1.AggregationProof 2, // 7: internal.client.p2p.proto.v1.SymbioticP2PService.WantSignatures:input_type -> internal.client.p2p.proto.v1.WantSignaturesRequest 7, // 8: internal.client.p2p.proto.v1.SymbioticP2PService.WantAggregationProofs:input_type -> internal.client.p2p.proto.v1.WantAggregationProofsRequest 3, // 9: internal.client.p2p.proto.v1.SymbioticP2PService.WantSignatures:output_type -> internal.client.p2p.proto.v1.WantSignaturesResponse 8, // 10: internal.client.p2p.proto.v1.SymbioticP2PService.WantAggregationProofs:output_type -> internal.client.p2p.proto.v1.WantAggregationProofsResponse 9, // [9:11] is the sub-list for method output_type 7, // [7:9] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name 7, // [7:7] is the sub-list for extension extendee 0, // [0:7] is the sub-list for field type_name } ⋮---- 9, // 0: internal.client.p2p.proto.v1.WantSignaturesRequest.want_signatures:type_name -> internal.client.p2p.proto.v1.WantSignaturesRequest.WantSignaturesEntry 10, // 1: internal.client.p2p.proto.v1.WantSignaturesResponse.signatures:type_name -> internal.client.p2p.proto.v1.WantSignaturesResponse.SignaturesEntry 5, // 2: internal.client.p2p.proto.v1.ValidatorSignatureList.signatures:type_name -> internal.client.p2p.proto.v1.ValidatorSignature 6, // 3: internal.client.p2p.proto.v1.ValidatorSignature.signature:type_name -> internal.client.p2p.proto.v1.Signature 11, // 4: internal.client.p2p.proto.v1.WantAggregationProofsResponse.proofs:type_name -> internal.client.p2p.proto.v1.WantAggregationProofsResponse.ProofsEntry 4, // 5: internal.client.p2p.proto.v1.WantSignaturesResponse.SignaturesEntry.value:type_name -> internal.client.p2p.proto.v1.ValidatorSignatureList 0, // 6: internal.client.p2p.proto.v1.WantAggregationProofsResponse.ProofsEntry.value:type_name -> internal.client.p2p.proto.v1.AggregationProof 2, // 7: internal.client.p2p.proto.v1.SymbioticP2PService.WantSignatures:input_type -> internal.client.p2p.proto.v1.WantSignaturesRequest 7, // 8: internal.client.p2p.proto.v1.SymbioticP2PService.WantAggregationProofs:input_type -> internal.client.p2p.proto.v1.WantAggregationProofsRequest 3, // 9: internal.client.p2p.proto.v1.SymbioticP2PService.WantSignatures:output_type -> internal.client.p2p.proto.v1.WantSignaturesResponse 8, // 10: internal.client.p2p.proto.v1.SymbioticP2PService.WantAggregationProofs:output_type -> internal.client.p2p.proto.v1.WantAggregationProofsResponse 9, // [9:11] is the sub-list for method output_type 7, // [7:9] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name 7, // [7:7] is the sub-list for extension extendee 0, // [0:7] is the sub-list for field type_name ⋮---- func init() func file_v1_message_proto_init() ⋮---- type x struct{} ```` ## File: internal/client/p2p/proto/v1/message.proto ````protobuf syntax = "proto3"; package internal.client.p2p.proto.v1; option go_package = "github.com/symbioticfi/relay/internal/client/p2p/proto/v1"; // AggregationProof represents the aggregated signatures message message AggregationProof { uint32 key_tag = 2; uint64 epoch = 3; bytes message_hash = 4; bytes proof = 5; } // P2PMessage represents a peer-to-peer message wrapper message P2PMessage { string sender = 1; int64 timestamp = 2; bytes data = 3; } service SymbioticP2PService { rpc WantSignatures(WantSignaturesRequest) returns (WantSignaturesResponse); rpc WantAggregationProofs(WantAggregationProofsRequest) returns (WantAggregationProofsResponse); } message WantSignaturesRequest { // Map of request id to bitmap of wanted validator indices map want_signatures = 1; // key: hex string of common.Hash, value: roaring bitmap bytes } message WantSignaturesResponse { // Map of request id to list of validator signatures map signatures = 2; // key: hex string of common.Hash } // ValidatorSignatureList contains a list of validator signatures for a specific request message ValidatorSignatureList { repeated ValidatorSignature signatures = 1; } // ValidatorSignature pairs a signature with its validator index message ValidatorSignature { uint32 validator_index = 1; Signature signature = 2; } // Signature represents extended signature data message Signature { bytes message_hash = 1; uint32 key_tag = 2; uint64 epoch = 3; bytes signature = 4; bytes public_key = 5; } message WantAggregationProofsRequest { // List of request ids for which aggregation proofs are needed repeated string request_ids = 1; // hex strings of common.Hash } message WantAggregationProofsResponse { // Map of request ids to aggregation proof map proofs = 1; // key: hex string of common.Hash } ```` ## File: internal/client/p2p/broadcast_signature_aggregated_message.go ````go package p2p ⋮---- import ( "context" "github.com/go-errors/errors" "google.golang.org/protobuf/proto" prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" "google.golang.org/protobuf/proto" ⋮---- prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (s *Service) BroadcastSignatureAggregatedMessage(ctx context.Context, msg symbiotic.AggregationProof) error ```` ## File: internal/client/p2p/broadcast_signature_generated_message.go ````go package p2p ⋮---- import ( "context" "github.com/go-errors/errors" "google.golang.org/protobuf/proto" prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" "google.golang.org/protobuf/proto" ⋮---- prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (s *Service) BroadcastSignatureGeneratedMessage(ctx context.Context, msg symbiotic.Signature) error ```` ## File: internal/client/p2p/discovery_integration_test.go ````go package p2p ⋮---- import ( "context" "testing" "time" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- func TestDiscoveryService_Start_WithDHTEnabled_InitializesDHT(t *testing.T) ⋮---- func TestDiscoveryService_Start_WithDHTDisabled_SkipsDHT(t *testing.T) ⋮---- func TestDiscoveryService_Start_WhenAlreadyStarted_ReturnsError(t *testing.T) ⋮---- func TestDiscoveryService_initDHT_WithClientMode_Success(t *testing.T) ⋮---- func TestDiscoveryService_initDHT_WithBootstrapPeers_ParsesPeers(t *testing.T) ⋮---- func TestDiscoveryService_initMDNS_WhenDisabled_ReturnsNil(t *testing.T) ⋮---- func TestDiscoveryService_initMDNS_WhenEnabled_InitializesMDNS(t *testing.T) ⋮---- func TestDiscoveryService_Close_WithDHTAndMDNS_ClosesAll(t *testing.T) ⋮---- func TestDiscoveryService_HandlePeerFound_ConnectsToPeer(t *testing.T) ⋮---- func TestDiscoveryService_Advertise_WithValidRdiscov_SuccessOrExpectedError(t *testing.T) ⋮---- func TestDiscoveryService_Advertise_WithZeroTTL_CallsAdvertise(t *testing.T) ⋮---- func TestDiscoveryService_GetDiscoveryClient_WhenInitialized_ReturnsClient(t *testing.T) ```` ## File: internal/client/p2p/discovery_test.go ````go package p2p ⋮---- import ( "context" "testing" "time" "github.com/libp2p/go-libp2p" dht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/libp2p/go-libp2p" dht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- func createMockHost(t *testing.T) host.Host ⋮---- func TestDiscoveryService_determineDHTMode_Client(t *testing.T) ⋮---- func TestDiscoveryService_determineDHTMode_Server(t *testing.T) ⋮---- func TestDiscoveryService_determineDHTMode_Auto(t *testing.T) ⋮---- func TestDiscoveryService_determineDHTMode_Empty(t *testing.T) ⋮---- func TestDiscoveryService_determineDHTMode_Invalid(t *testing.T) ⋮---- func TestDiscoveryService_parseBootstrapPeers_EmptyList(t *testing.T) ⋮---- func TestDiscoveryService_parseBootstrapPeers_ValidPeer(t *testing.T) ⋮---- func TestDiscoveryService_parseBootstrapPeers_InvalidPeer(t *testing.T) ⋮---- func TestDiscoveryService_parseBootstrapPeers_SkipsSelfPeer(t *testing.T) ⋮---- func TestDiscoveryService_parseBootstrapPeers_MultiplePeers(t *testing.T) ⋮---- func TestDiscoveryService_GetDiscoveryClient_WhenNotInitialized_ReturnsNil(t *testing.T) ⋮---- func TestNewDiscoveryService_WithValidHost_Success(t *testing.T) ⋮---- func TestNewDiscoveryService_WithNilHost_ReturnsError(t *testing.T) ⋮---- func TestDiscoveryService_Advertise_WhenRdiscovIsNil_ReturnsError(t *testing.T) ⋮---- func TestDiscoveryService_connectToPeer_AlreadyConnected_ReturnsNil(t *testing.T) ⋮---- func TestDiscoveryService_connectToPeer_NotConnected_ConnectsToPeer(t *testing.T) ⋮---- func TestDiscoveryService_connectToPeer_WithTimeout_ReturnsError(t *testing.T) ⋮---- func TestDiscoveryService_Close_WhenNotStarted_ReturnsNil(t *testing.T) ```` ## File: internal/client/p2p/discovery.go ````go package p2p ⋮---- import ( "context" "log/slog" "sync" "time" "github.com/go-errors/errors" dht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p/core/discovery" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/discovery/mdns" drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing" ) ⋮---- "context" "log/slog" "sync" "time" ⋮---- "github.com/go-errors/errors" dht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p/core/discovery" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/discovery/mdns" drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing" ⋮---- // DiscoveryService implements peer discovery functionality allowing both DHT and mDNS. type DiscoveryService struct { cfg Config host host.Host dht *dht.IpfsDHT mdns mdns.Service rdiscov *drouting.RoutingDiscovery mu sync.RWMutex started bool ctx context.Context cancel context.CancelFunc lastAdvertisement time.Time bootstrapPeers []peer.AddrInfo } ⋮---- // DiscoverySvc represents the peer discovery service interface. type DiscoverySvc interface { Start(ctx context.Context) error Close(ctx context.Context) error GetDiscoveryClient(ctx context.Context) *drouting.RoutingDiscovery } ⋮---- const ProtocolPrefix = "/symbiotic" ⋮---- // NewDiscoveryService creates a new discovery service. func NewDiscoveryService(cfg Config) (*DiscoveryService, error) ⋮---- func (s *DiscoveryService) initDHT(ctx context.Context) error ⋮---- func (s *DiscoveryService) determineDHTMode(ctx context.Context) dht.ModeOpt ⋮---- func (s *DiscoveryService) parseBootstrapPeers(ctx context.Context) ([]peer.AddrInfo, error) ⋮---- func (s *DiscoveryService) initMDNS(ctx context.Context) error ⋮---- func (s *DiscoveryService) Start(ctx context.Context) error ⋮---- func (s *DiscoveryService) maintainConnections(ctx context.Context) ⋮---- func (s *DiscoveryService) Close(ctx context.Context) error ⋮---- func (s *DiscoveryService) GetDiscoveryClient(ctx context.Context) *drouting.RoutingDiscovery ⋮---- func (s *DiscoveryService) Advertise(ctx context.Context, topic string) error ⋮---- // HandlePeerFound processes a newly discovered mDNS peer and attempts to connect. func (s *DiscoveryService) HandlePeerFound(peerInfo peer.AddrInfo) ⋮---- // linter suggests to use separate context ⋮---- // Attempt to connect to the discovered peer ⋮---- func (s *DiscoveryService) connectToPeer(ctx context.Context, peerInfo peer.AddrInfo) error ```` ## File: internal/client/p2p/p2p_broadcast_test.go ````go package p2p ⋮---- import ( "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) ⋮---- "context" "testing" ⋮---- "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- func TestService_ID_ReturnsHostID(t *testing.T) ⋮---- func TestService_Broadcast_TopicNotFound_ReturnsError(t *testing.T) ⋮---- func TestService_AddPeer_SkipsSelfConnection(t *testing.T) ⋮---- func TestService_AddPeer_ConnectsToValidPeer(t *testing.T) ```` ## File: internal/client/p2p/p2p_grpc_handler.go ````go package p2p ⋮---- import ( "context" "github.com/go-errors/errors" p2pv1 "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" ⋮---- p2pv1 "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" ⋮---- // syncRequestHandler defines the interface for handling both signature and aggregation proof requests type syncRequestHandler interface { HandleWantSignaturesRequest(ctx context.Context, request entity.WantSignaturesRequest) (entity.WantSignaturesResponse, error) HandleWantAggregationProofsRequest(ctx context.Context, request entity.WantAggregationProofsRequest) (entity.WantAggregationProofsResponse, error) } ⋮---- type GRPCHandler struct { p2pv1.UnimplementedSymbioticP2PServiceServer syncHandler syncRequestHandler } ⋮---- func NewP2PHandler(syncHandler syncRequestHandler) *GRPCHandler ⋮---- // WantSignatures handles incoming signature requests from peers func (h *GRPCHandler) WantSignatures(ctx context.Context, req *p2pv1.WantSignaturesRequest) (*p2pv1.WantSignaturesResponse, error) ⋮---- // WantAggregationProofs handles incoming aggregation proof requests from peers func (h *GRPCHandler) WantAggregationProofs(ctx context.Context, req *p2pv1.WantAggregationProofsRequest) (*p2pv1.WantAggregationProofsResponse, error) ```` ## File: internal/client/p2p/p2p_grpc_send_want_aggregation_proofs_request_test.go ````go package p2p ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestSendWantAggregationProofsRequest_HappyPath(t *testing.T) ⋮---- type mockAggregationProofHandler struct { expectedRequest entity.WantAggregationProofsRequest responseToReturn entity.WantAggregationProofsResponse wasCalled bool receivedRequest entity.WantAggregationProofsRequest } ⋮---- func (m *mockAggregationProofHandler) HandleWantSignaturesRequest(_ context.Context, request entity.WantSignaturesRequest) (entity.WantSignaturesResponse, error) ⋮---- func (m *mockAggregationProofHandler) HandleWantAggregationProofsRequest(_ context.Context, request entity.WantAggregationProofsRequest) (entity.WantAggregationProofsResponse, error) ```` ## File: internal/client/p2p/p2p_grpc_send_want_aggregation_proofs_request.go ````go package p2p ⋮---- import ( "context" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/libp2p/go-libp2p/core/peer" "github.com/samber/lo" prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/libp2p/go-libp2p/core/peer" "github.com/samber/lo" ⋮---- prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // SendWantAggregationProofsRequest sends a synchronous aggregation proof request to a peer func (s *Service) SendWantAggregationProofsRequest(ctx context.Context, request entity.WantAggregationProofsRequest) (entity.WantAggregationProofsResponse, error) ⋮---- // Convert entity request to protobuf ⋮---- // Select a peer for the request ⋮---- // Send request to the selected peer ⋮---- // sendAggregationProofRequestToPeer sends a gRPC aggregation proof request to a specific peer func (s *Service) sendAggregationProofRequestToPeer(ctx context.Context, peerID peer.ID, req *prototypes.WantAggregationProofsRequest) (*prototypes.WantAggregationProofsResponse, error) ⋮---- // Create gRPC connection over libp2p stream ⋮---- // Create gRPC client and send request ⋮---- // entityToProtoAggregationProofRequest converts entity.WantAggregationProofsRequest to protobuf func entityToProtoAggregationProofRequest(req entity.WantAggregationProofsRequest) *prototypes.WantAggregationProofsRequest ⋮---- // protoToEntityAggregationProofResponse converts protobuf WantAggregationProofsResponse to entity func protoToEntityAggregationProofResponse(resp *prototypes.WantAggregationProofsResponse) entity.WantAggregationProofsResponse ⋮---- // Convert aggregation proof ⋮---- // protoToEntityAggregationProofRequest converts protobuf WantAggregationProofsRequest to entity func protoToEntityAggregationProofRequest(req *prototypes.WantAggregationProofsRequest) entity.WantAggregationProofsRequest ⋮---- // entityToProtoAggregationProofResponse converts entity WantAggregationProofsResponse to protobuf func entityToProtoAggregationProofResponse(resp entity.WantAggregationProofsResponse) *prototypes.WantAggregationProofsResponse ```` ## File: internal/client/p2p/p2p_grpc_send_want_signatures_request_test.go ````go package p2p ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestSendWantSignaturesRequest_HappyPath(t *testing.T) ⋮---- // Setup two libp2p hosts (peer1 as client, peer2 as server) ⋮---- // Manually connect the peers by adding addresses to peerstore ⋮---- // Actually connect the peers ⋮---- // Create test data for the request ⋮---- // Create signature bitmaps (requesting signatures from validators 0, 2, 5) ⋮---- // Create expected response data ⋮---- // Setup mock sync request handler for the server ⋮---- // Create server P2P service using NewService constructor ⋮---- SkipMessageSign: true, // Skip message signing for tests ⋮---- // Start the gRPC server ⋮---- // Stop server ⋮---- // Create client P2P service using NewService constructor ⋮---- Handler: NewP2PHandler(mockHandler), // Not used for client but required ⋮---- // Execute the test: send want signatures request ⋮---- // Verify the response ⋮---- // Verify signatures for testHash1 ⋮---- // Find and verify first signature var foundSig1, foundSig2 *entity.ValidatorSignature ⋮---- // Verify signatures for testHash2 ⋮---- // Verify that the mock handler was called with the correct request ⋮---- // mockSyncRequestHandler implements syncRequestHandler for testing type mockSyncRequestHandler struct { expectedRequest entity.WantSignaturesRequest responseToReturn entity.WantSignaturesResponse wasCalled bool receivedRequest entity.WantSignaturesRequest } ⋮---- func (m *mockSyncRequestHandler) HandleWantSignaturesRequest(_ context.Context, request entity.WantSignaturesRequest) (entity.WantSignaturesResponse, error) ⋮---- func (m *mockSyncRequestHandler) HandleWantAggregationProofsRequest(_ context.Context, request entity.WantAggregationProofsRequest) (entity.WantAggregationProofsResponse, error) ⋮---- // Return empty response for tests that don't need aggregation proof functionality ```` ## File: internal/client/p2p/p2p_grpc_send_want_signatures_request.go ````go package p2p ⋮---- import ( "context" "log/slog" "math/rand/v2" "net" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" gostream "github.com/libp2p/go-libp2p-gostream" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/protocol" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" "math/rand/v2" "net" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" gostream "github.com/libp2p/go-libp2p-gostream" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/protocol" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ⋮---- prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const grpcProtocolTag protocol.ID = "/relay/v1/grpc" ⋮---- // SendWantSignaturesRequest sends a synchronous signature request to a peer func (s *Service) SendWantSignaturesRequest(ctx context.Context, request entity.WantSignaturesRequest) (entity.WantSignaturesResponse, error) ⋮---- // Convert entity request to protobuf ⋮---- // Select a peer for the request ⋮---- // Send request to the selected peer ⋮---- // Convert protobuf response to entity ⋮---- // sendRequestToPeer sends a gRPC request to a specific peer func (s *Service) sendRequestToPeer(ctx context.Context, peerID peer.ID, req *prototypes.WantSignaturesRequest) (*prototypes.WantSignaturesResponse, error) ⋮---- // Create gRPC connection over libp2p stream ⋮---- // Create gRPC client and send request ⋮---- // createGRPCConnection creates a gRPC connection to a peer over libp2p func (s *Service) createGRPCConnection(_ context.Context, peerID peer.ID) (*grpc.ClientConn, error) ⋮---- // entityToProtoRequest converts entity.WantSignaturesRequest to protobuf func entityToProtoRequest(req entity.WantSignaturesRequest) (*prototypes.WantSignaturesRequest, error) ⋮---- // Serialize roaring bitmap to bytes ⋮---- // protoToEntityResponse converts protobuf WantSignaturesResponse to entity func protoToEntityResponse(ctx context.Context, resp *prototypes.WantSignaturesResponse) entity.WantSignaturesResponse ⋮---- // Convert validator signatures var validatorSigs []entity.ValidatorSignature ⋮---- // selectPeerForSync selects a single peer for synchronous signature requests func (s *Service) selectPeerForSync() (peer.ID, error) ⋮---- //nolint:gosec // G404: non-cryptographic random selection ⋮---- // protoToEntityRequest converts protobuf WantSignaturesRequest to entity func protoToEntityRequest(req *prototypes.WantSignaturesRequest) (entity.WantSignaturesRequest, error) ⋮---- // Deserialize roaring bitmap from bytes ⋮---- // entityToProtoResponse converts entity WantSignaturesResponse to protobuf func entityToProtoResponse(resp entity.WantSignaturesResponse) *prototypes.WantSignaturesResponse ⋮---- var protoSigs []*prototypes.ValidatorSignature ```` ## File: internal/client/p2p/p2p_grpc_test.go ````go package p2p ⋮---- import ( "context" "net" "testing" "time" "github.com/ethereum/go-ethereum/common" grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry" "github.com/libp2p/go-libp2p" gostream "github.com/libp2p/go-libp2p-gostream" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/libp2p/go-libp2p/core/protocol" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" v2 "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "net" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry" "github.com/libp2p/go-libp2p" gostream "github.com/libp2p/go-libp2p-gostream" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/libp2p/go-libp2p/core/protocol" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ⋮---- v2 "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestP2P_GRPC(t *testing.T) ⋮---- var tag protocol.ID = "/testp2pgrpc" ⋮---- type myHandler struct { v2.UnimplementedSymbioticP2PServiceServer } ⋮---- func (m myHandler) WantSignatures(ctx context.Context, request *v2.WantSignaturesRequest) (*v2.WantSignaturesResponse, error) ⋮---- func (m myHandler) HandleWantSignaturesRequest(ctx context.Context, request entity.WantSignaturesRequest) (entity.WantSignaturesResponse, error) ⋮---- func (m myHandler) HandleWantAggregationProofsRequest(ctx context.Context, request entity.WantAggregationProofsRequest) (entity.WantAggregationProofsResponse, error) ```` ## File: internal/client/p2p/p2p_handle_message_test.go ````go package p2p ⋮---- import ( "context" "testing" "time" "github.com/libp2p/go-libp2p" pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" p2pEntity "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/libp2p/go-libp2p" pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- "google.golang.org/grpc" ⋮---- p2pEntity "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" symbioticCrypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- // TestService_IntegrationSuccessful tests full P2P communication between two services func TestService_IntegrationSuccessful(t *testing.T) ⋮---- // Create two libp2p hosts ⋮---- // Connect the peers ⋮---- time.Sleep(100 * time.Millisecond) // Small delay to ensure the gossip protocol is set up ⋮---- // Wait for connection to establish ⋮---- // Set up message listener on service2 var receivedMsg p2pEntity.P2PMessage[symbiotic.Signature] ⋮---- // Prepare test message ⋮---- // Send the message from service1 ⋮---- // Verify the received message ⋮---- // TestService_IntegrationFailedSignature tests P2P communication with a message that fails signature verification func TestService_IntegrationFailedSignature(t *testing.T) ⋮---- func createTestService(t *testing.T, skipMessageSigning bool, tracer pubsub.EventTracer) *Service ⋮---- type rejectTracer struct { rejectCh chan *pubsub_pb.TraceEvent } ⋮---- func (rt *rejectTracer) Trace(evt *pubsub_pb.TraceEvent) ⋮---- // mockMetrics implements the metrics interface for testing type mockMetrics struct{} ⋮---- func (m *mockMetrics) UnaryServerInterceptor() grpc.UnaryServerInterceptor ⋮---- func (m *mockMetrics) StreamServerInterceptor() grpc.StreamServerInterceptor ⋮---- func (m *mockMetrics) ObserveP2PPeerMessageSent(messageType, status string) ⋮---- func TestService_AggregatedProofIntegrationSuccessful(t *testing.T) ⋮---- var receivedMsg p2pEntity.P2PMessage[symbiotic.AggregationProof] ```` ## File: internal/client/p2p/p2p_handle_message_unit_test.go ````go package p2p ⋮---- import ( "testing" pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" ) ⋮---- "testing" ⋮---- pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" ⋮---- prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" ⋮---- func TestHandleSignatureReadyMessage_WithOversizedPublicKey_ReturnsError(t *testing.T) ⋮---- func TestHandleSignatureReadyMessage_WithOversizedSignature_ReturnsError(t *testing.T) ⋮---- func TestHandleSignatureReadyMessage_WithOversizedMessageHash_ReturnsError(t *testing.T) ⋮---- func TestHandleSignatureReadyMessage_WithInvalidPublicKey_ReturnsError(t *testing.T) ⋮---- func TestHandleAggregatedProofReadyMessage_WithOversizedMessageHash_ReturnsError(t *testing.T) ⋮---- func TestHandleAggregatedProofReadyMessage_WithOversizedProof_ReturnsError(t *testing.T) ⋮---- func TestUnmarshalMessage_WithInvalidP2PMessage_ReturnsError(t *testing.T) ⋮---- var signature prototypes.Signature ⋮---- func TestUnmarshalMessage_WithInvalidInnerMessage_ReturnsError(t *testing.T) ⋮---- func TestExtractSenderInfo_WithInvalidPeerID_ReturnsError(t *testing.T) ```` ## File: internal/client/p2p/p2p_handle_message.go ````go package p2p ⋮---- import ( "github.com/go-errors/errors" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "google.golang.org/protobuf/proto" prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" p2pEntity "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "github.com/go-errors/errors" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "google.golang.org/protobuf/proto" ⋮---- prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" p2pEntity "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (s *Service) handleSignatureReadyMessage(pubSubMsg *pubsub.Message) error ⋮---- var signature prototypes.Signature ⋮---- // Validate the signature message ⋮---- func (s *Service) handleAggregatedProofReadyMessage(pubSubMsg *pubsub.Message) error ⋮---- var signaturesAggregated prototypes.AggregationProof ⋮---- // Validate the signaturesAggregated message ⋮---- func extractSenderInfo(pubSubMsg *pubsub.Message) (p2pEntity.SenderInfo, error) ⋮---- // try to extract public key from sender peer.ID ⋮---- func unmarshalMessage(msg *pubsub.Message, v proto.Message) error ⋮---- var message prototypes.P2PMessage ```` ## File: internal/client/p2p/p2p_test.go ````go package p2p ⋮---- import ( "testing" "github.com/libp2p/go-libp2p" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) ⋮---- "testing" ⋮---- "github.com/libp2p/go-libp2p" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- func TestConfig_Validate_Success(t *testing.T) ⋮---- func TestConfig_Validate_MissingHost(t *testing.T) ⋮---- func TestConfig_Validate_MissingMetrics(t *testing.T) ⋮---- func TestConfig_Validate_MissingHandler(t *testing.T) ⋮---- func TestDefaultDiscoveryConfig_ReturnsValidConfig(t *testing.T) ```` ## File: internal/client/p2p/p2p.go ````go package p2p ⋮---- import ( "context" "log/slog" "time" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" gostream "github.com/libp2p/go-libp2p-gostream" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "google.golang.org/grpc" "google.golang.org/protobuf/proto" prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" p2pEntity "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/server" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" "time" ⋮---- "github.com/go-errors/errors" "github.com/go-playground/validator/v10" gostream "github.com/libp2p/go-libp2p-gostream" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "google.golang.org/grpc" "google.golang.org/protobuf/proto" ⋮---- prototypes "github.com/symbioticfi/relay/internal/client/p2p/proto/v1" p2pEntity "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/server" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( topicPrefix = "/relay/v1" topicSignatureReady = topicPrefix + "/signature/ready" topicAggProofReady = topicPrefix + "/proof/ready" maxP2PMessageSize = 1<<20 + 1024 // 1 MiB + 1 KiB for overhead maxRequestIDSize = 32 maxPubKeySize = 96 maxSignatureSize = 96 maxMsgHashSize = 64 maxProofSize = 1 << 20 ) ⋮---- maxP2PMessageSize = 1<<20 + 1024 // 1 MiB + 1 KiB for overhead ⋮---- type metrics interface { ObserveP2PPeerMessageSent(messageType, status string) UnaryServerInterceptor() grpc.UnaryServerInterceptor StreamServerInterceptor() grpc.StreamServerInterceptor } ⋮---- // DiscoveryConfig contains discovery protocol configuration type DiscoveryConfig struct { // EnableMDNS specifies whether mDNS discovery is enabled. EnableMDNS bool // MDNSServiceName is the mDNS service name. MDNSServiceName string // DHTMode specifies the DHT mode. DHTMode string // BootstrapPeers is the list of bootstrap peers in multiaddr format. BootstrapPeers []string // AdvertiseTTL is the advertise time-to-live duration. AdvertiseTTL time.Duration // AdvertiseServiceName is the advertise service name. AdvertiseServiceName string // AdvertiseInterval is the interval between advertisements. AdvertiseInterval time.Duration // ConnectionTimeout is the timeout for peer connections. ConnectionTimeout time.Duration // MaxDHTReconnectPeerCount is the maximum number of DHT reconnect peers. MaxDHTReconnectPeerCount int // DHTPeerDiscoveryInterval is the interval for DHT peer discovery. Should be smaller than AdvertiseInterval. DHTPeerDiscoveryInterval time.Duration // DHTRoutingTableRefreshInterval is the interval for DHT routing table refresh. Should be greater than DHTPeerDiscoveryInterval. DHTRoutingTableRefreshInterval time.Duration } ⋮---- // EnableMDNS specifies whether mDNS discovery is enabled. ⋮---- // MDNSServiceName is the mDNS service name. ⋮---- // DHTMode specifies the DHT mode. ⋮---- // BootstrapPeers is the list of bootstrap peers in multiaddr format. ⋮---- // AdvertiseTTL is the advertise time-to-live duration. ⋮---- // AdvertiseServiceName is the advertise service name. ⋮---- // AdvertiseInterval is the interval between advertisements. ⋮---- // ConnectionTimeout is the timeout for peer connections. ⋮---- // MaxDHTReconnectPeerCount is the maximum number of DHT reconnect peers. ⋮---- // DHTPeerDiscoveryInterval is the interval for DHT peer discovery. Should be smaller than AdvertiseInterval. ⋮---- // DHTRoutingTableRefreshInterval is the interval for DHT routing table refresh. Should be greater than DHTPeerDiscoveryInterval. ⋮---- func DefaultDiscoveryConfig() DiscoveryConfig ⋮---- AdvertiseTTL: 3 * time.Hour, // max allowed value in kdht package ⋮---- DHTRoutingTableRefreshInterval: 10 * time.Minute, // same as kdht package default ⋮---- type Config struct { Host host.Host `validate:"required"` SkipMessageSign bool Metrics metrics `validate:"required"` Discovery DiscoveryConfig `validate:"required"` EventTracer pubsub.EventTracer Handler prototypes.SymbioticP2PServiceServer `validate:"required"` } ⋮---- func (c Config) Validate() error ⋮---- // Service handles peer-to-peer communication and signature aggregation type Service struct { ctx context.Context host host.Host signatureReceivedHandler *signals.Signal[p2pEntity.P2PMessage[symbiotic.Signature]] signaturesAggregatedHandler *signals.Signal[p2pEntity.P2PMessage[symbiotic.AggregationProof]] metrics metrics topicsMap map[string]*pubsub.Topic p2pGRPCHandler prototypes.SymbioticP2PServiceServer } ⋮---- // NewService creates a new P2P service with the given configuration func NewService(ctx context.Context, cfg Config, signalCfg signals.Config) (*Service, error) ⋮---- func (s *Service) listenForMessages(ctx context.Context, sub *pubsub.Subscription, topic *pubsub.Topic, handler func(msg *pubsub.Message) error) ⋮---- func (s *Service) StartSignatureMessageListener(mh func(ctx context.Context, msg p2pEntity.P2PMessage[symbiotic.Signature]) error) error ⋮---- func (s *Service) StartSignaturesAggregatedMessageListener(mh func(ctx context.Context, msg p2pEntity.P2PMessage[symbiotic.AggregationProof]) error) error ⋮---- func (s *Service) addPeer(pi peer.AddrInfo) error ⋮---- // broadcast sends a message to all connected peers func (s *Service) broadcast(ctx context.Context, topicName string, data []byte) error ⋮---- // Marshal and send the message ⋮---- // Close gracefully stops the service func (s *Service) Close() error ⋮---- func (s *Service) Listen(n network.Network, multiaddr multiaddr.Multiaddr) ⋮---- func (s *Service) ListenClose(n network.Network, multiaddr multiaddr.Multiaddr) ⋮---- func (s *Service) Connected(n network.Network, conn network.Conn) ⋮---- func (s *Service) Disconnected(n network.Network, conn network.Conn) ⋮---- func (s *Service) ID() string ⋮---- func (s *Service) StartGRPCServer(ctx context.Context) error ⋮---- //nolint:contextcheck // the context comes from th stream ⋮---- // Wait for context cancellation or server error ```` ## File: internal/client/repository/badger/proto/v1/badger.pb.go ````go // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.6 // protoc (unknown) // source: v1/badger.proto ⋮---- package v1 ⋮---- import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" unsafe "unsafe" ) ⋮---- protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" unsafe "unsafe" ⋮---- const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ⋮---- // Verify that this generated code is sufficiently up-to-date. ⋮---- // Verify that runtime/protoimpl is sufficiently up-to-date. ⋮---- type Validator struct { state protoimpl.MessageState `protogen:"open.v1"` Operator []byte `protobuf:"bytes,1,opt,name=operator,proto3" json:"operator,omitempty"` VotingPower string `protobuf:"bytes,2,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` IsActive bool `protobuf:"varint,3,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"` ActiveIndex uint32 `protobuf:"varint,4,opt,name=active_index,json=activeIndex,proto3" json:"active_index,omitempty"` Keys []*ValidatorKey `protobuf:"bytes,5,rep,name=keys,proto3" json:"keys,omitempty"` Vaults []*ValidatorVault `protobuf:"bytes,6,rep,name=vaults,proto3" json:"vaults,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- func (x *Validator) Reset() ⋮---- func (x *Validator) String() string ⋮---- func (*Validator) ProtoMessage() ⋮---- func (x *Validator) ProtoReflect() protoreflect.Message ⋮---- // Deprecated: Use Validator.ProtoReflect.Descriptor instead. func (*Validator) Descriptor() ([]byte, []int) ⋮---- func (x *Validator) GetOperator() []byte ⋮---- func (x *Validator) GetVotingPower() string ⋮---- func (x *Validator) GetIsActive() bool ⋮---- func (x *Validator) GetActiveIndex() uint32 ⋮---- func (x *Validator) GetKeys() []*ValidatorKey ⋮---- func (x *Validator) GetVaults() []*ValidatorVault ⋮---- type ValidatorKey struct { state protoimpl.MessageState `protogen:"open.v1"` Tag uint32 `protobuf:"varint,1,opt,name=tag,proto3" json:"tag,omitempty"` Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ValidatorKey.ProtoReflect.Descriptor instead. ⋮---- func (x *ValidatorKey) GetTag() uint32 ⋮---- func (x *ValidatorKey) GetPayload() []byte ⋮---- type ValidatorVault struct { state protoimpl.MessageState `protogen:"open.v1"` ChainId uint64 `protobuf:"varint,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Vault []byte `protobuf:"bytes,2,opt,name=vault,proto3" json:"vault,omitempty"` VotingPower string `protobuf:"bytes,3,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ValidatorVault.ProtoReflect.Descriptor instead. ⋮---- func (x *ValidatorVault) GetChainId() uint64 ⋮---- func (x *ValidatorVault) GetVault() []byte ⋮---- type ValidatorSetHeader struct { state protoimpl.MessageState `protogen:"open.v1"` Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` RequiredKeyTag uint32 `protobuf:"varint,2,opt,name=required_key_tag,json=requiredKeyTag,proto3" json:"required_key_tag,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` CaptureTimestamp uint64 `protobuf:"varint,4,opt,name=capture_timestamp,json=captureTimestamp,proto3" json:"capture_timestamp,omitempty"` QuorumThreshold string `protobuf:"bytes,5,opt,name=quorum_threshold,json=quorumThreshold,proto3" json:"quorum_threshold,omitempty"` TotalVotingPower string `protobuf:"bytes,6,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` ValidatorsSszMroot []byte `protobuf:"bytes,7,opt,name=validators_ssz_mroot,json=validatorsSszMroot,proto3" json:"validators_ssz_mroot,omitempty"` AggregatorIndices []byte `protobuf:"bytes,8,opt,name=aggregator_indices,json=aggregatorIndices,proto3" json:"aggregator_indices,omitempty"` CommitterIndices []byte `protobuf:"bytes,9,opt,name=committer_indices,json=committerIndices,proto3" json:"committer_indices,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ValidatorSetHeader.ProtoReflect.Descriptor instead. ⋮---- func (x *ValidatorSetHeader) GetVersion() uint32 ⋮---- func (x *ValidatorSetHeader) GetRequiredKeyTag() uint32 ⋮---- func (x *ValidatorSetHeader) GetEpoch() uint64 ⋮---- func (x *ValidatorSetHeader) GetCaptureTimestamp() uint64 ⋮---- func (x *ValidatorSetHeader) GetQuorumThreshold() string ⋮---- func (x *ValidatorSetHeader) GetTotalVotingPower() string ⋮---- func (x *ValidatorSetHeader) GetValidatorsSszMroot() []byte ⋮---- func (x *ValidatorSetHeader) GetAggregatorIndices() []byte ⋮---- func (x *ValidatorSetHeader) GetCommitterIndices() []byte ⋮---- type ValidatorSetMetadata struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId []byte `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` ExtraData []*ExtraData `protobuf:"bytes,3,rep,name=extra_data,json=extraData,proto3" json:"extra_data,omitempty"` CommitmentData []byte `protobuf:"bytes,4,opt,name=commitment_data,json=commitmentData,proto3" json:"commitment_data,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ValidatorSetMetadata.ProtoReflect.Descriptor instead. ⋮---- func (x *ValidatorSetMetadata) GetRequestId() []byte ⋮---- func (x *ValidatorSetMetadata) GetExtraData() []*ExtraData ⋮---- func (x *ValidatorSetMetadata) GetCommitmentData() []byte ⋮---- type ExtraData struct { state protoimpl.MessageState `protogen:"open.v1"` Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ExtraData.ProtoReflect.Descriptor instead. ⋮---- func (x *ExtraData) GetKey() []byte ⋮---- func (x *ExtraData) GetValue() []byte ⋮---- type AggregationProof struct { state protoimpl.MessageState `protogen:"open.v1"` MessageHash []byte `protobuf:"bytes,1,opt,name=message_hash,json=messageHash,proto3" json:"message_hash,omitempty"` KeyTag uint32 `protobuf:"varint,2,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` Proof []byte `protobuf:"bytes,4,opt,name=proof,proto3" json:"proof,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use AggregationProof.ProtoReflect.Descriptor instead. ⋮---- func (x *AggregationProof) GetMessageHash() []byte ⋮---- func (x *AggregationProof) GetKeyTag() uint32 ⋮---- func (x *AggregationProof) GetProof() []byte ⋮---- type Signature struct { state protoimpl.MessageState `protogen:"open.v1"` MessageHash []byte `protobuf:"bytes,1,opt,name=message_hash,json=messageHash,proto3" json:"message_hash,omitempty"` KeyTag uint32 `protobuf:"varint,2,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` RawPublicKey []byte `protobuf:"bytes,5,opt,name=raw_public_key,json=rawPublicKey,proto3" json:"raw_public_key,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use Signature.ProtoReflect.Descriptor instead. ⋮---- func (x *Signature) GetSignature() []byte ⋮---- func (x *Signature) GetRawPublicKey() []byte ⋮---- type SignatureRequest struct { state protoimpl.MessageState `protogen:"open.v1"` KeyTag uint32 `protobuf:"varint,1,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` RequiredEpoch uint64 `protobuf:"varint,2,opt,name=required_epoch,json=requiredEpoch,proto3" json:"required_epoch,omitempty"` Message []byte `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use SignatureRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *SignatureRequest) GetRequiredEpoch() uint64 ⋮---- func (x *SignatureRequest) GetMessage() []byte ⋮---- type SignatureMap struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId []byte `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` SignedValidatorsBitmap []byte `protobuf:"bytes,3,opt,name=signed_validators_bitmap,json=signedValidatorsBitmap,proto3" json:"signed_validators_bitmap,omitempty"` CurrentVotingPower string `protobuf:"bytes,4,opt,name=current_voting_power,json=currentVotingPower,proto3" json:"current_voting_power,omitempty"` TotalValidators uint32 `protobuf:"varint,5,opt,name=total_validators,json=totalValidators,proto3" json:"total_validators,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use SignatureMap.ProtoReflect.Descriptor instead. ⋮---- func (x *SignatureMap) GetSignedValidatorsBitmap() []byte ⋮---- func (x *SignatureMap) GetCurrentVotingPower() string ⋮---- func (x *SignatureMap) GetTotalValidators() uint32 ⋮---- type NetworkConfig struct { state protoimpl.MessageState `protogen:"open.v1"` VotingPowerProviders []*CrossChainAddress `protobuf:"bytes,1,rep,name=voting_power_providers,json=votingPowerProviders,proto3" json:"voting_power_providers,omitempty"` KeysProvider *CrossChainAddress `protobuf:"bytes,2,opt,name=keys_provider,json=keysProvider,proto3" json:"keys_provider,omitempty"` Settlements []*CrossChainAddress `protobuf:"bytes,3,rep,name=settlements,proto3" json:"settlements,omitempty"` VerificationType uint32 `protobuf:"varint,4,opt,name=verification_type,json=verificationType,proto3" json:"verification_type,omitempty"` MaxVotingPower string `protobuf:"bytes,5,opt,name=max_voting_power,json=maxVotingPower,proto3" json:"max_voting_power,omitempty"` MinInclusionVotingPower string `protobuf:"bytes,6,opt,name=min_inclusion_voting_power,json=minInclusionVotingPower,proto3" json:"min_inclusion_voting_power,omitempty"` MaxValidatorsCount string `protobuf:"bytes,7,opt,name=max_validators_count,json=maxValidatorsCount,proto3" json:"max_validators_count,omitempty"` RequiredKeyTags []uint32 `protobuf:"varint,8,rep,packed,name=required_key_tags,json=requiredKeyTags,proto3" json:"required_key_tags,omitempty"` RequiredHeaderKeyTag uint32 `protobuf:"varint,9,opt,name=required_header_key_tag,json=requiredHeaderKeyTag,proto3" json:"required_header_key_tag,omitempty"` QuorumThresholds []*QuorumThreshold `protobuf:"bytes,10,rep,name=quorum_thresholds,json=quorumThresholds,proto3" json:"quorum_thresholds,omitempty"` NumCommitters uint64 `protobuf:"varint,11,opt,name=num_committers,json=numCommitters,proto3" json:"num_committers,omitempty"` NumAggregators uint64 `protobuf:"varint,12,opt,name=num_aggregators,json=numAggregators,proto3" json:"num_aggregators,omitempty"` CommitterSlotDuration uint64 `protobuf:"varint,13,opt,name=committer_slot_duration,json=committerSlotDuration,proto3" json:"committer_slot_duration,omitempty"` EpochDuration uint64 `protobuf:"varint,14,opt,name=epoch_duration,json=epochDuration,proto3" json:"epoch_duration,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use NetworkConfig.ProtoReflect.Descriptor instead. ⋮---- func (x *NetworkConfig) GetVotingPowerProviders() []*CrossChainAddress ⋮---- func (x *NetworkConfig) GetKeysProvider() *CrossChainAddress ⋮---- func (x *NetworkConfig) GetSettlements() []*CrossChainAddress ⋮---- func (x *NetworkConfig) GetVerificationType() uint32 ⋮---- func (x *NetworkConfig) GetMaxVotingPower() string ⋮---- func (x *NetworkConfig) GetMinInclusionVotingPower() string ⋮---- func (x *NetworkConfig) GetMaxValidatorsCount() string ⋮---- func (x *NetworkConfig) GetRequiredKeyTags() []uint32 ⋮---- func (x *NetworkConfig) GetRequiredHeaderKeyTag() uint32 ⋮---- func (x *NetworkConfig) GetQuorumThresholds() []*QuorumThreshold ⋮---- func (x *NetworkConfig) GetNumCommitters() uint64 ⋮---- func (x *NetworkConfig) GetNumAggregators() uint64 ⋮---- func (x *NetworkConfig) GetCommitterSlotDuration() uint64 ⋮---- func (x *NetworkConfig) GetEpochDuration() uint64 ⋮---- type CrossChainAddress struct { state protoimpl.MessageState `protogen:"open.v1"` Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` ChainId uint64 `protobuf:"varint,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use CrossChainAddress.ProtoReflect.Descriptor instead. ⋮---- func (x *CrossChainAddress) GetAddress() []byte ⋮---- type QuorumThreshold struct { state protoimpl.MessageState `protogen:"open.v1"` KeyTag uint32 `protobuf:"varint,1,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` QuorumThreshold string `protobuf:"bytes,2,opt,name=quorum_threshold,json=quorumThreshold,proto3" json:"quorum_threshold,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use QuorumThreshold.ProtoReflect.Descriptor instead. ⋮---- var File_v1_badger_proto protoreflect.FileDescriptor ⋮---- const file_v1_badger_proto_rawDesc = "" + "\n" + "\x0fv1/badger.proto\x12*internal.client.repository.badger.proto.v1\"\xac\x02\n" + "\tValidator\x12\x1a\n" + "\boperator\x18\x01 \x01(\fR\boperator\x12!\n" + "\fvoting_power\x18\x02 \x01(\tR\vvotingPower\x12\x1b\n" + "\tis_active\x18\x03 \x01(\bR\bisActive\x12!\n" + "\factive_index\x18\x04 \x01(\rR\vactiveIndex\x12L\n" + "\x04keys\x18\x05 \x03(\v28.internal.client.repository.badger.proto.v1.ValidatorKeyR\x04keys\x12R\n" + "\x06vaults\x18\x06 \x03(\v2:.internal.client.repository.badger.proto.v1.ValidatorVaultR\x06vaults\":\n" + "\fValidatorKey\x12\x10\n" + "\x03tag\x18\x01 \x01(\rR\x03tag\x12\x18\n" + "\apayload\x18\x02 \x01(\fR\apayload\"d\n" + "\x0eValidatorVault\x12\x19\n" + "\bchain_id\x18\x01 \x01(\x04R\achainId\x12\x14\n" + "\x05vault\x18\x02 \x01(\fR\x05vault\x12!\n" + "\fvoting_power\x18\x03 \x01(\tR\vvotingPower\"\x82\x03\n" + "\x12ValidatorSetHeader\x12\x18\n" + "\aversion\x18\x01 \x01(\rR\aversion\x12(\n" + "\x10required_key_tag\x18\x02 \x01(\rR\x0erequiredKeyTag\x12\x14\n" + "\x05epoch\x18\x03 \x01(\x04R\x05epoch\x12+\n" + "\x11capture_timestamp\x18\x04 \x01(\x04R\x10captureTimestamp\x12)\n" + "\x10quorum_threshold\x18\x05 \x01(\tR\x0fquorumThreshold\x12,\n" + "\x12total_voting_power\x18\x06 \x01(\tR\x10totalVotingPower\x120\n" + "\x14validators_ssz_mroot\x18\a \x01(\fR\x12validatorsSszMroot\x12-\n" + "\x12aggregator_indices\x18\b \x01(\fR\x11aggregatorIndices\x12+\n" + "\x11committer_indices\x18\t \x01(\fR\x10committerIndices\"\xca\x01\n" + "\x14ValidatorSetMetadata\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\fR\trequestId\x12\x14\n" + "\x05epoch\x18\x02 \x01(\x04R\x05epoch\x12T\n" + "\n" + "extra_data\x18\x03 \x03(\v25.internal.client.repository.badger.proto.v1.ExtraDataR\textraData\x12'\n" + "\x0fcommitment_data\x18\x04 \x01(\fR\x0ecommitmentData\"3\n" + "\tExtraData\x12\x10\n" + "\x03key\x18\x01 \x01(\fR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\fR\x05value\"z\n" + "\x10AggregationProof\x12!\n" + "\fmessage_hash\x18\x01 \x01(\fR\vmessageHash\x12\x17\n" + "\akey_tag\x18\x02 \x01(\rR\x06keyTag\x12\x14\n" + "\x05epoch\x18\x03 \x01(\x04R\x05epoch\x12\x14\n" + "\x05proof\x18\x04 \x01(\fR\x05proof\"\xa1\x01\n" + "\tSignature\x12!\n" + "\fmessage_hash\x18\x01 \x01(\fR\vmessageHash\x12\x17\n" + "\akey_tag\x18\x02 \x01(\rR\x06keyTag\x12\x14\n" + "\x05epoch\x18\x03 \x01(\x04R\x05epoch\x12\x1c\n" + "\tsignature\x18\x04 \x01(\fR\tsignature\x12$\n" + "\x0eraw_public_key\x18\x05 \x01(\fR\frawPublicKey\"l\n" + "\x10SignatureRequest\x12\x17\n" + "\akey_tag\x18\x01 \x01(\rR\x06keyTag\x12%\n" + "\x0erequired_epoch\x18\x02 \x01(\x04R\rrequiredEpoch\x12\x18\n" + "\amessage\x18\x03 \x01(\fR\amessage\"\xda\x01\n" + "\fSignatureMap\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\fR\trequestId\x12\x14\n" + "\x05epoch\x18\x02 \x01(\x04R\x05epoch\x128\n" + "\x18signed_validators_bitmap\x18\x03 \x01(\fR\x16signedValidatorsBitmap\x120\n" + "\x14current_voting_power\x18\x04 \x01(\tR\x12currentVotingPower\x12)\n" + "\x10total_validators\x18\x05 \x01(\rR\x0ftotalValidators\"\x8b\a\n" + "\rNetworkConfig\x12s\n" + "\x16voting_power_providers\x18\x01 \x03(\v2=.internal.client.repository.badger.proto.v1.CrossChainAddressR\x14votingPowerProviders\x12b\n" + "\rkeys_provider\x18\x02 \x01(\v2=.internal.client.repository.badger.proto.v1.CrossChainAddressR\fkeysProvider\x12_\n" + "\vsettlements\x18\x03 \x03(\v2=.internal.client.repository.badger.proto.v1.CrossChainAddressR\vsettlements\x12+\n" + "\x11verification_type\x18\x04 \x01(\rR\x10verificationType\x12(\n" + "\x10max_voting_power\x18\x05 \x01(\tR\x0emaxVotingPower\x12;\n" + "\x1amin_inclusion_voting_power\x18\x06 \x01(\tR\x17minInclusionVotingPower\x120\n" + "\x14max_validators_count\x18\a \x01(\tR\x12maxValidatorsCount\x12*\n" + "\x11required_key_tags\x18\b \x03(\rR\x0frequiredKeyTags\x125\n" + "\x17required_header_key_tag\x18\t \x01(\rR\x14requiredHeaderKeyTag\x12h\n" + "\x11quorum_thresholds\x18\n" + " \x03(\v2;.internal.client.repository.badger.proto.v1.QuorumThresholdR\x10quorumThresholds\x12%\n" + "\x0enum_committers\x18\v \x01(\x04R\rnumCommitters\x12'\n" + "\x0fnum_aggregators\x18\f \x01(\x04R\x0enumAggregators\x126\n" + "\x17committer_slot_duration\x18\r \x01(\x04R\x15committerSlotDuration\x12%\n" + "\x0eepoch_duration\x18\x0e \x01(\x04R\repochDuration\"H\n" + "\x11CrossChainAddress\x12\x18\n" + "\aaddress\x18\x01 \x01(\fR\aaddress\x12\x19\n" + "\bchain_id\x18\x02 \x01(\x04R\achainId\"U\n" + "\x0fQuorumThreshold\x12\x17\n" + "\akey_tag\x18\x01 \x01(\rR\x06keyTag\x12)\n" + "\x10quorum_threshold\x18\x02 \x01(\tR\x0fquorumThresholdB\xd5\x02\n" + ".com.internal.client.repository.badger.proto.v1B\vBadgerProtoP\x01ZGgithub.com/symbioticfi/relay/internal/client/repository/badger/proto/v1\xa2\x02\x05ICRBP\xaa\x02*Internal.Client.Repository.Badger.Proto.V1\xca\x02*Internal\\Client\\Repository\\Badger\\Proto\\V1\xe2\x026Internal\\Client\\Repository\\Badger\\Proto\\V1\\GPBMetadata\xea\x02/Internal::Client::Repository::Badger::Proto::V1b\x06proto3" ⋮---- var ( file_v1_badger_proto_rawDescOnce sync.Once file_v1_badger_proto_rawDescData []byte ) ⋮---- func file_v1_badger_proto_rawDescGZIP() []byte ⋮---- var file_v1_badger_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_v1_badger_proto_goTypes = []any{ (*Validator)(nil), // 0: internal.client.repository.badger.proto.v1.Validator (*ValidatorKey)(nil), // 1: internal.client.repository.badger.proto.v1.ValidatorKey (*ValidatorVault)(nil), // 2: internal.client.repository.badger.proto.v1.ValidatorVault (*ValidatorSetHeader)(nil), // 3: internal.client.repository.badger.proto.v1.ValidatorSetHeader (*ValidatorSetMetadata)(nil), // 4: internal.client.repository.badger.proto.v1.ValidatorSetMetadata (*ExtraData)(nil), // 5: internal.client.repository.badger.proto.v1.ExtraData (*AggregationProof)(nil), // 6: internal.client.repository.badger.proto.v1.AggregationProof (*Signature)(nil), // 7: internal.client.repository.badger.proto.v1.Signature (*SignatureRequest)(nil), // 8: internal.client.repository.badger.proto.v1.SignatureRequest (*SignatureMap)(nil), // 9: internal.client.repository.badger.proto.v1.SignatureMap (*NetworkConfig)(nil), // 10: internal.client.repository.badger.proto.v1.NetworkConfig (*CrossChainAddress)(nil), // 11: internal.client.repository.badger.proto.v1.CrossChainAddress (*QuorumThreshold)(nil), // 12: internal.client.repository.badger.proto.v1.QuorumThreshold } ⋮---- (*Validator)(nil), // 0: internal.client.repository.badger.proto.v1.Validator (*ValidatorKey)(nil), // 1: internal.client.repository.badger.proto.v1.ValidatorKey (*ValidatorVault)(nil), // 2: internal.client.repository.badger.proto.v1.ValidatorVault (*ValidatorSetHeader)(nil), // 3: internal.client.repository.badger.proto.v1.ValidatorSetHeader (*ValidatorSetMetadata)(nil), // 4: internal.client.repository.badger.proto.v1.ValidatorSetMetadata (*ExtraData)(nil), // 5: internal.client.repository.badger.proto.v1.ExtraData (*AggregationProof)(nil), // 6: internal.client.repository.badger.proto.v1.AggregationProof (*Signature)(nil), // 7: internal.client.repository.badger.proto.v1.Signature (*SignatureRequest)(nil), // 8: internal.client.repository.badger.proto.v1.SignatureRequest (*SignatureMap)(nil), // 9: internal.client.repository.badger.proto.v1.SignatureMap (*NetworkConfig)(nil), // 10: internal.client.repository.badger.proto.v1.NetworkConfig (*CrossChainAddress)(nil), // 11: internal.client.repository.badger.proto.v1.CrossChainAddress (*QuorumThreshold)(nil), // 12: internal.client.repository.badger.proto.v1.QuorumThreshold ⋮---- var file_v1_badger_proto_depIdxs = []int32{ 1, // 0: internal.client.repository.badger.proto.v1.Validator.keys:type_name -> internal.client.repository.badger.proto.v1.ValidatorKey 2, // 1: internal.client.repository.badger.proto.v1.Validator.vaults:type_name -> internal.client.repository.badger.proto.v1.ValidatorVault 5, // 2: internal.client.repository.badger.proto.v1.ValidatorSetMetadata.extra_data:type_name -> internal.client.repository.badger.proto.v1.ExtraData 11, // 3: internal.client.repository.badger.proto.v1.NetworkConfig.voting_power_providers:type_name -> internal.client.repository.badger.proto.v1.CrossChainAddress 11, // 4: internal.client.repository.badger.proto.v1.NetworkConfig.keys_provider:type_name -> internal.client.repository.badger.proto.v1.CrossChainAddress 11, // 5: internal.client.repository.badger.proto.v1.NetworkConfig.settlements:type_name -> internal.client.repository.badger.proto.v1.CrossChainAddress 12, // 6: internal.client.repository.badger.proto.v1.NetworkConfig.quorum_thresholds:type_name -> internal.client.repository.badger.proto.v1.QuorumThreshold 7, // [7:7] is the sub-list for method output_type 7, // [7:7] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name 7, // [7:7] is the sub-list for extension extendee 0, // [0:7] is the sub-list for field type_name } ⋮---- 1, // 0: internal.client.repository.badger.proto.v1.Validator.keys:type_name -> internal.client.repository.badger.proto.v1.ValidatorKey 2, // 1: internal.client.repository.badger.proto.v1.Validator.vaults:type_name -> internal.client.repository.badger.proto.v1.ValidatorVault 5, // 2: internal.client.repository.badger.proto.v1.ValidatorSetMetadata.extra_data:type_name -> internal.client.repository.badger.proto.v1.ExtraData 11, // 3: internal.client.repository.badger.proto.v1.NetworkConfig.voting_power_providers:type_name -> internal.client.repository.badger.proto.v1.CrossChainAddress 11, // 4: internal.client.repository.badger.proto.v1.NetworkConfig.keys_provider:type_name -> internal.client.repository.badger.proto.v1.CrossChainAddress 11, // 5: internal.client.repository.badger.proto.v1.NetworkConfig.settlements:type_name -> internal.client.repository.badger.proto.v1.CrossChainAddress 12, // 6: internal.client.repository.badger.proto.v1.NetworkConfig.quorum_thresholds:type_name -> internal.client.repository.badger.proto.v1.QuorumThreshold 7, // [7:7] is the sub-list for method output_type 7, // [7:7] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name 7, // [7:7] is the sub-list for extension extendee 0, // [0:7] is the sub-list for field type_name ⋮---- func init() func file_v1_badger_proto_init() ⋮---- type x struct{} ```` ## File: internal/client/repository/badger/proto/v1/badger.proto ````protobuf syntax = "proto3"; package internal.client.repository.badger.proto.v1; option go_package = "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1"; message Validator { bytes operator = 1; string voting_power = 2; bool is_active = 3; uint32 active_index = 4; repeated ValidatorKey keys = 5; repeated ValidatorVault vaults = 6; } message ValidatorKey { uint32 tag = 1; bytes payload = 2; } message ValidatorVault { uint64 chain_id = 1; bytes vault = 2; string voting_power = 3; } message ValidatorSetHeader { uint32 version = 1; uint32 required_key_tag = 2; uint64 epoch = 3; uint64 capture_timestamp = 4; string quorum_threshold = 5; string total_voting_power = 6; bytes validators_ssz_mroot = 7; bytes aggregator_indices = 8; bytes committer_indices = 9; } message ValidatorSetMetadata { bytes request_id = 1; uint64 epoch = 2; repeated ExtraData extra_data = 3; bytes commitment_data = 4; } message ExtraData { bytes key = 1; bytes value = 2; } message AggregationProof { bytes message_hash = 1; uint32 key_tag = 2; uint64 epoch = 3; bytes proof = 4; } message Signature { bytes message_hash = 1; uint32 key_tag = 2; uint64 epoch = 3; bytes signature = 4; bytes raw_public_key = 5; } message SignatureRequest { uint32 key_tag = 1; uint64 required_epoch = 2; bytes message = 3; } message SignatureMap { bytes request_id = 1; uint64 epoch = 2; bytes signed_validators_bitmap = 3; string current_voting_power = 4; uint32 total_validators = 5; } message NetworkConfig { repeated CrossChainAddress voting_power_providers = 1; CrossChainAddress keys_provider = 2; repeated CrossChainAddress settlements = 3; uint32 verification_type = 4; string max_voting_power = 5; string min_inclusion_voting_power = 6; string max_validators_count = 7; repeated uint32 required_key_tags = 8; uint32 required_header_key_tag = 9; repeated QuorumThreshold quorum_thresholds = 10; uint64 num_committers = 11; uint64 num_aggregators = 12; uint64 committer_slot_duration = 13; uint64 epoch_duration = 14; } message CrossChainAddress { bytes address = 1; uint64 chain_id = 2; } message QuorumThreshold { uint32 key_tag = 1; string quorum_threshold = 2; } ```` ## File: internal/client/repository/badger/badger_repository_add_proof.go ````go package badger ⋮---- import ( "context" "github.com/dgraph-io/badger/v4" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (r *Repository) SaveProof(ctx context.Context, aggregationProof symbiotic.AggregationProof) error ⋮---- // Remove from pending collection ⋮---- // If ErrEntityNotFound or ErrTxConflict, it means it was already processed or is being processed, so we can ignore it ```` ## File: internal/client/repository/badger/badger_repository_add_signature.go ````go package badger ⋮---- import ( "context" "log/slog" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" ⋮---- "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (r *Repository) SaveSignature(ctx context.Context, signature symbiotic.Signature, validator symbiotic.Validator, activeIndex uint32) error ⋮---- var ( signatureMap entity.SignatureMap err error ) ⋮---- // Get the total number of active validators for this epoch ⋮---- // outside previous transaction, check if we can remove from pending collection ⋮---- // Blindly save to pending aggregation proof collection // syncer will remove it from collection once proof is found ⋮---- // ignore ErrEntityAlreadyExist and ErrTxConflict - it means it's already there or being processed ⋮---- // for non aggregation keys, we wait for all validators to sign and then remove // the pending aggregation marker to stop syncing signatures for this request ⋮---- // Save to pending aggregation proof collection, to sync for missing signatures // syncer will remove it from collection once all signatures are found ```` ## File: internal/client/repository/badger/badger_repository_aggregation_proof_pending_test.go ````go package badger ⋮---- import ( "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestBadgerRepository_SaveAggregationProofPending(t *testing.T) ⋮---- func TestBadgerRepository_RemoveAggregationProofPending(t *testing.T) ⋮---- // First save ⋮---- // Then remove ⋮---- // Try to remove again should fail ⋮---- // Save multiple entries ⋮---- // Remove one specific entry ⋮---- // Verify others still exist by trying to save them again (should fail) ⋮---- // But the removed one should be gone - we can save it again ⋮---- func TestBadgerRepository_GetSignatureRequestsWithoutAggregationProof(t *testing.T) ⋮---- // Create multiple signature requests var requests []symbiotic.Signature ⋮---- // Save signature request ⋮---- // Get first page (limit 3) ⋮---- // Get second page using last hash from first page ⋮---- require.Len(t, secondPage, 2) // Remaining 2 requests ⋮---- // Verify no overlap between pages ⋮---- // Verify all original requests are found across both pages ⋮---- // Create one valid signature request ⋮---- // Save signature request ⋮---- // Create a pending aggregation proof marker without corresponding signature request ⋮---- // Should only return the valid request, skipping the orphan ⋮---- // Query epoch1 should only return req1 ⋮---- // Query epoch2 should only return req2 ⋮---- func TestBadgerRepository_AggregationProofPendingIntegration(t *testing.T) ⋮---- // Save signature request ⋮---- // Now it should appear in pending list ⋮---- // Remove from pending ⋮---- // Should no longer appear in pending list ```` ## File: internal/client/repository/badger/badger_repository_aggregation_proof_test.go ````go package badger ⋮---- import ( "testing" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "testing" ⋮---- "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestBadgerRepository_AggregationProof(t *testing.T) ⋮---- func TestBadgerRepository_GetAggregationProofsStartingFromEpoch(t *testing.T) ⋮---- // Create three aggregation proofs with epochs 1, 2, 3 ⋮---- // Save all three aggregation proofs ⋮---- // Query starting from epoch 2 ⋮---- // Should return exactly 2 proofs (epochs 2 and 3) ⋮---- // Verify epochs are 2 and 3 ⋮---- // Query starting from epoch 1 - should return all 3 ⋮---- // Query starting from epoch 3 - should return only epoch 3 ⋮---- func TestBadgerRepository_GetAggregationProofsByEpoch(t *testing.T) ⋮---- func randomAggregationProof(t *testing.T) symbiotic.AggregationProof ```` ## File: internal/client/repository/badger/badger_repository_aggregation_proof.go ````go package badger ⋮---- import ( "bytes" "context" "fmt" "log/slog" "strings" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "bytes" "context" "fmt" "log/slog" "strings" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func keyAggregationProof(requestID common.Hash) []byte ⋮---- func keyAggregationProofPending(epoch symbiotic.Epoch, requestID common.Hash) []byte ⋮---- func keyAggregationProofPendingEpochPrefix(epoch symbiotic.Epoch) []byte ⋮---- func (r *Repository) saveAggregationProof(ctx context.Context, requestID common.Hash, ap symbiotic.AggregationProof) error ⋮---- func (r *Repository) GetAggregationProof(ctx context.Context, requestID common.Hash) (symbiotic.AggregationProof, error) ⋮---- var ap symbiotic.AggregationProof ⋮---- func (r *Repository) GetAggregationProofsStartingFromEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.AggregationProof, error) ⋮---- var proofs []symbiotic.AggregationProof ⋮---- func (r *Repository) GetAggregationProofsByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.AggregationProof, error) ⋮---- func getAggregationProofByEpochFromItem(txn *badger.Txn, it *badger.Iterator) (symbiotic.AggregationProof, error) ⋮---- func aggregationProofToBytes(ap symbiotic.AggregationProof) ([]byte, error) ⋮---- func bytesToAggregationProof(value []byte) (symbiotic.AggregationProof, error) ⋮---- func (r *Repository) saveAggregationProofPending(ctx context.Context, requestID common.Hash, epoch symbiotic.Epoch) error ⋮---- // Store just a marker (empty value) - we don't need the full request data here ⋮---- func (r *Repository) RemoveAggregationProofPending(ctx context.Context, epoch symbiotic.Epoch, requestID common.Hash) error ⋮---- // Check if exists before removing ⋮---- func (r *Repository) GetSignatureRequestsWithoutAggregationProof(ctx context.Context, epoch symbiotic.Epoch, limit int, lastHash common.Hash) ([]symbiotic.SignatureRequestWithID, error) ⋮---- var requests []symbiotic.SignatureRequestWithID ⋮---- // Iterate through pending aggregation proof markers ⋮---- opts.PrefetchValues = false // We don't need the values, just the keys ⋮---- // Subsequent pages: seek to the record after lastHash ⋮---- // If we're seeking from a specific hash and positioned exactly on that key, skip it (already returned in previous page) ⋮---- // Stop if we've reached the limit ⋮---- // Extract request id from the pending key: "aggregation_proof_pending:epoch:request_id" ⋮---- // Find the hash part after the second colon ⋮---- // Get the actual signature request ⋮---- // This shouldn't happen - pending marker exists but signature request doesn't // Skip this entry and continue ```` ## File: internal/client/repository/badger/badger_repository_network_config_test.go ````go package badger ⋮---- import ( "math/big" "testing" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" "testing" ⋮---- "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestBadgerRepository_NetworkConfig(t *testing.T) ⋮---- func randomNetworkConfig(t *testing.T) symbiotic.NetworkConfig ```` ## File: internal/client/repository/badger/badger_repository_network_config.go ````go package badger ⋮---- import ( "context" "fmt" "math/big" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "fmt" "math/big" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func keyNetworkConfig(epoch symbiotic.Epoch) []byte ⋮---- func (r *Repository) SaveConfig(ctx context.Context, config symbiotic.NetworkConfig, epoch symbiotic.Epoch) error ⋮---- func (r *Repository) GetConfigByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) ⋮---- var config symbiotic.NetworkConfig ⋮---- func networkConfigToBytes(config symbiotic.NetworkConfig) ([]byte, error) ⋮---- func bytesToNetworkConfig(data []byte) (symbiotic.NetworkConfig, error) ```` ## File: internal/client/repository/badger/badger_repository_proof_commits_test.go ````go package badger ⋮---- import ( "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestBadgerRepository_SaveProofCommitPending(t *testing.T) ⋮---- func TestBadgerRepository_RemoveProofCommitPending(t *testing.T) ⋮---- // First save ⋮---- // Then remove ⋮---- // Try to remove again should fail ⋮---- // Save multiple entries ⋮---- // Remove one specific entry ⋮---- // Verify others still exist by trying to save them again (should fail) ⋮---- // But the removed one should be gone - we can save it again ⋮---- func TestBadgerRepository_GetPendingProofCommitsSinceEpoch(t *testing.T) ⋮---- // Save commits in different epochs ⋮---- // Get commits since epoch 100 ⋮---- // Should return commits for epochs 100 and 150, not 50 ⋮---- // Create commits with same epoch but different hashes to test hash sorting ⋮---- // Save in reverse order to test sorting ⋮---- // Verify epoch ordering (ascending) ⋮---- // Verify hash ordering within same epoch ⋮---- // Create multiple commits ⋮---- // Test limit = 3 ⋮---- // Test limit = 0 (should return all) ⋮---- // Test limit > available (should return all available) ⋮---- // Query from epoch 701 should return epochs 701 and 702 ⋮---- // This test verifies that the function handles malformed keys in the database // We can't directly insert malformed keys through the public API, but the function // should be robust against them. This test mainly verifies no panic occurs. ```` ## File: internal/client/repository/badger/badger_repository_proof_commits.go ````go package badger ⋮---- import ( "bytes" "context" "math/big" "sort" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "bytes" "context" "math/big" "sort" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( aggregationProofCommitPrefix = "aggregation_proof_commit:" ) ⋮---- func keyAggregationProofCommited(epoch symbiotic.Epoch) []byte ⋮---- func (r *Repository) SaveProofCommitPending(ctx context.Context, epoch symbiotic.Epoch, requestID common.Hash) error ⋮---- func (r *Repository) RemoveProofCommitPending(ctx context.Context, epoch symbiotic.Epoch) error ⋮---- // Check if exists before removing ⋮---- func (r *Repository) GetPendingProofCommitsSinceEpoch(ctx context.Context, epoch symbiotic.Epoch, limit int) ([]symbiotic.ProofCommitKey, error) ⋮---- var requests []symbiotic.ProofCommitKey ⋮---- // Step 1: Collect all keys with their parsed epochs and hashes var keys []symbiotic.ProofCommitKey ⋮---- // Use broader prefix to capture all epochs // Key format: "aggregation_proof_commit:epoch:hash" ⋮---- // Iterate through all aggregation proof commit keys ⋮---- continue // Skip invalid keys ⋮---- // Parse the epoch ⋮---- // Skip if this epoch is less than our target epoch ⋮---- continue // Skip invalid request IDs ⋮---- return nil // No keys found ⋮---- // Step 2: Sort keys by epoch (ascending) and then by hash for deterministic ordering ⋮---- // Step 3: limit response ```` ## File: internal/client/repository/badger/badger_repository_proto_test.go ````go package badger ⋮---- import ( "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func TestValidatorProtoConversion(t *testing.T) ⋮---- func TestValidatorProtoConversion_EmptyArrays(t *testing.T) ⋮---- func TestNetworkConfigProtoConversion(t *testing.T) ⋮---- func TestValidatorSetHeaderProtoConversion(t *testing.T) ⋮---- func TestValidatorSetMetadataProtoConversion(t *testing.T) ⋮---- func TestSignatureMapProtoConversion(t *testing.T) ⋮---- func TestSignatureProtoConversion(t *testing.T) ⋮---- KeyTag: symbiotic.KeyTag(4), // 4 is BLS (upper nibble = 0) ⋮---- KeyTag: symbiotic.KeyTag(16), // 16 is ECDSA (upper nibble = 1) ⋮---- func TestSignatureRequestProtoConversion(t *testing.T) ⋮---- func TestAggregationProofProtoConversion(t *testing.T) ⋮---- func TestBigIntEdgeCases(t *testing.T) ```` ## File: internal/client/repository/badger/badger_repository_signature_map_test.go ````go package badger ⋮---- import ( "context" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- // randomRequestID generates a valid request id for testing func randomRequestID(t *testing.T) common.Hash ⋮---- // randomSignatureMap creates a SignatureMap with test data func randomSignatureMap(t *testing.T, requestID common.Hash) entity.SignatureMap ⋮---- // assertSignatureMapsEqual performs deep equality check on SignatureMaps func assertSignatureMapsEqual(t *testing.T, expected, actual entity.SignatureMap) ⋮---- func TestBadgerRepository_SignatureMap(t *testing.T) ⋮---- // Verify data was saved correctly ⋮---- // Save initial signature map ⋮---- // Update with modified data ⋮---- // Verify updated data ⋮---- // Save two different signature maps ⋮---- // Retrieve first signature map ⋮---- // Retrieve second signature map ⋮---- // Create multiple signature maps ⋮---- // Verify all can be retrieved correctly ⋮---- func TestSignatureMapSerialization(t *testing.T) ⋮---- // Serialize ⋮---- // Deserialize ⋮---- // Verify round-trip preservation ⋮---- // Create SignatureMap with large big.Int values ⋮---- Epoch: 18446744073709551615, // Max uint64 ⋮---- // Serialize and deserialize ⋮---- // Test roaring bitmap with specific indexes bitmap := entity.NewBitmapOf(0) // Only validator at index 0 is present ⋮---- // Verify bitmap contains expected validator index ⋮---- func TestSignatureMapTransactions(t *testing.T) ⋮---- // Update within transaction ⋮---- // Get within same transaction - should work ⋮---- // Verify data persisted after transaction ⋮---- // Transaction that will rollback due to error ⋮---- // Verify data exists within transaction ⋮---- // Return error to trigger rollback ⋮---- // Verify data was not persisted due to rollback ⋮---- // Setup existing data ⋮---- // Read existing data ⋮---- // Write new data ⋮---- // Read newly written data within same transaction ⋮---- // Verify both datasets exist after transaction ⋮---- func TestSignatureMapKeyGeneration(t *testing.T) ⋮---- func TestSignatureMapEdgeCases(t *testing.T) ⋮---- RequestID: common.Hash{}, // Zero hash ⋮---- // Test single validator scenario ⋮---- SignedValidatorsBitmap: entity.NewBitmapOf(0), // Single validator at index 0 ⋮---- // Create signature map with many validators ⋮---- // Add even indexes (50 validators present out of 100) ```` ## File: internal/client/repository/badger/badger_repository_signature_map.go ````go package badger ⋮---- import ( "context" "math/big" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func keySignatureMap(requestID common.Hash) []byte ⋮---- func (r *Repository) UpdateSignatureMap(ctx context.Context, vm entity.SignatureMap) error ⋮---- func (r *Repository) GetSignatureMap(ctx context.Context, requestID common.Hash) (entity.SignatureMap, error) ⋮---- var vm entity.SignatureMap ⋮---- // Create a new read-only transaction ⋮---- var err error ⋮---- func (r *Repository) getSignatureMap(ctx context.Context, requestID common.Hash) (entity.SignatureMap, error) ⋮---- func signatureMapToBytes(vm entity.SignatureMap) ([]byte, error) ⋮---- func bytesToSignatureMap(data []byte) (entity.SignatureMap, error) ```` ## File: internal/client/repository/badger/badger_repository_signature_request_test.go ````go package badger ⋮---- import ( "sort" "strconv" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "sort" "strconv" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // signatureRequestID computes the RequestID for a SignatureRequest func signatureRequestID(t *testing.T, req symbiotic.SignatureRequest) common.Hash ⋮---- func TestBadgerRepository_SignatureRequest(t *testing.T) ⋮---- type reqWithTargetID struct { req symbiotic.SignatureRequest hash common.Hash } ⋮---- func TestBadgerRepository_GetSignatureRequestsByEpoch(t *testing.T) ⋮---- // Sort requests by hash (lexicographic order) to match expected retrieval order ⋮---- // Verify they are in correct order ⋮---- // Verify first 3 requests ⋮---- // Get first page (2 items) ⋮---- // Get second page using cursor ⋮---- // Get third page using cursor ⋮---- // Get fourth page (should be empty) ⋮---- // Use a hash that doesn't exist in this epoch ⋮---- // Should return results after the cursor position in lexicographic order ⋮---- // This test validates that when a cursor hash falls between stored keys, // we don't skip the first valid item after the seek (off-by-one bug) // Get the first two requests to determine a cursor that falls between them ⋮---- // Create a cursor hash that falls lexicographically between the first two stored hashes ⋮---- // Create a hash that's lexicographically between first and second var betweenHash common.Hash ⋮---- // Increment the last byte to create a hash between first and second ⋮---- // Verify the hash is actually between the two stored hashes ⋮---- // Query with this between-hash cursor - should start from secondHash (not skip it) ⋮---- // Should return all items starting from the second item (no off-by-one skip) require.Len(t, results, 4) // Should have 4 remaining items (total 5 - first 1) ⋮---- // Verify the sequence is correct ⋮---- expectedIndex := i + 1 // Skip first item, start from second ⋮---- func TestBadgerRepository_GetSignatureRequestsByEpoch_MultipleEpochs(t *testing.T) ⋮---- // Create requests for epoch1 ⋮---- // Create requests for epoch2 ⋮---- // Query epoch1 should return only epoch1 requests ⋮---- // Query epoch2 should return only epoch2 requests ⋮---- func randomSignatureRequest(t *testing.T) symbiotic.SignatureRequest ⋮---- func randomSignatureRequestForEpoch(t *testing.T, epoch symbiotic.Epoch) symbiotic.SignatureRequest ⋮---- func randomSignatureExtendedForEpoch(t *testing.T, epoch symbiotic.Epoch) symbiotic.Signature ⋮---- func TestBadgerRepository_GetSignatureRequestIDsByEpoch(t *testing.T) ⋮---- // Create 5 signature requests for the same epoch ⋮---- // Sort expected IDs by hex string (lexicographic order) ⋮---- // Verify they are in correct lexicographic order ⋮---- // Create requests for epoch2 ⋮---- // Query epoch1 should return only epoch1 IDs ⋮---- // Query epoch2 should return only epoch2 IDs ⋮---- // Verify no overlap between epochs ⋮---- func TestBadgerRepository_GetSignatureRequestsWithIDByEpoch(t *testing.T) ⋮---- // Verify they are in correct order and have correct request IDs ⋮---- // Query epoch1 should return only epoch1 requests ⋮---- // Verify all results are for epoch1 ⋮---- // Query epoch2 should return only epoch2 requests ⋮---- // Verify all results are for epoch2 ⋮---- // Create a single request with known values ⋮---- // Retrieve it ⋮---- // Verify the request ID matches what we saved ```` ## File: internal/client/repository/badger/badger_repository_signature_request.go ````go package badger ⋮---- import ( "bytes" "context" "fmt" "strings" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "bytes" "context" "fmt" "strings" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( keySignatureRequestPendingPrefix = "signature_pending:" ) ⋮---- func keySignatureRequest(epoch symbiotic.Epoch, requestID common.Hash) []byte ⋮---- func keySignatureRequestEpochPrefix(epoch symbiotic.Epoch) []byte ⋮---- func keyRequestIDIndex(requestID common.Hash) []byte ⋮---- func keySignatureRequestPending(epoch symbiotic.Epoch, requestID common.Hash) []byte ⋮---- // extractRequestIDFromKey extracts the request ID from a signature request key // Key format: "signature_request:epoch:hash" func extractRequestIDFromKey(key []byte) (common.Hash, error) ⋮---- // saveSignatureRequestToKey saves a signature request to a specific key func (r *Repository) saveSignatureRequestToKey(ctx context.Context, req symbiotic.SignatureRequest, key []byte) error ⋮---- // Store the record ⋮---- func (r *Repository) SaveSignatureRequest(ctx context.Context, requestID common.Hash, req symbiotic.SignatureRequest) error ⋮---- // Save pending signature for all key tags because we should attempt // to sync signatures from all signers even when keytag is non aggregation ⋮---- func (r *Repository) saveSignatureRequest(ctx context.Context, requestID common.Hash, req symbiotic.SignatureRequest) error ⋮---- func (r *Repository) saveSignaturePending(ctx context.Context, requestID common.Hash, req symbiotic.SignatureRequest) error ⋮---- // Store just a marker (empty value) - we don't need the full request data here ⋮---- func (r *Repository) RemoveSignaturePending(ctx context.Context, epoch symbiotic.Epoch, requestID common.Hash) error ⋮---- // Remove from pending collection ⋮---- func signatureRequestToBytes(req symbiotic.SignatureRequest) ([]byte, error) ⋮---- func bytesToSignatureRequest(data []byte) (symbiotic.SignatureRequest, error) ⋮---- func (r *Repository) GetSignatureRequest(ctx context.Context, requestID common.Hash) (symbiotic.SignatureRequest, error) ⋮---- var req symbiotic.SignatureRequest ⋮---- // Get primary key from hash index ⋮---- // Get actual data using primary key ⋮---- // getSignatureRequestsByEpochWithKeys is a generic method for retrieving signature requests by epoch // using provided prefix and key generation function func (r *Repository) getSignatureRequestsByEpochWithKeys( ctx context.Context, epoch symbiotic.Epoch, limit int, lastHash common.Hash, prefix []byte, keyFunc func(symbiotic.Epoch, common.Hash) []byte, ) ([]symbiotic.SignatureRequest, error) ⋮---- var requests []symbiotic.SignatureRequest ⋮---- // Subsequent pages: seek to the record after lastHash ⋮---- // If we're seeking from a specific hash and positioned exactly on that key, skip it (already returned in previous page) ⋮---- // Stop if we've reached the limit ⋮---- // GetSignatureRequestsWithIDByEpoch gets all signature requests with their request IDs for a given epoch func (r *Repository) GetSignatureRequestsWithIDByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]entity.SignatureRequestWithID, error) ⋮---- var requests []entity.SignatureRequestWithID ⋮---- // Extract request ID from key ⋮---- // GetSignatureRequestsByEpoch gets signature requests for a given epoch with pagination func (r *Repository) GetSignatureRequestsByEpoch(ctx context.Context, epoch symbiotic.Epoch, limit int, lastHash common.Hash) ([]symbiotic.SignatureRequest, error) ⋮---- func (r *Repository) GetSignatureRequestIDsByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]common.Hash, error) ⋮---- var requestIDs []common.Hash ⋮---- // Iterate through signature request keys without fetching values ⋮---- opts.PrefetchValues = false // Don't fetch values - we only need keys ⋮---- func (r *Repository) GetSignaturePending(ctx context.Context, limit int) ([]common.Hash, error) ⋮---- var requests []common.Hash ⋮---- // Iterate through pending signature markers ⋮---- // Extract request id from the pending key: "signature_pending:epoch:hash" ⋮---- // Find the hash part after the second colon ```` ## File: internal/client/repository/badger/badger_repository_signature_test.go ````go package badger ⋮---- import ( "context" "testing" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestBadgerRepository_Signature(t *testing.T) ⋮---- require.Len(t, signatures, 3) // sig1 from first test + sig1 and sig2 from this test ⋮---- // Verify we can retrieve each signature by index ⋮---- func TestBadgerRepository_SignatureOrdering(t *testing.T) ⋮---- // Test numeric ordering with indices that would be wrong in lexicographic string order ⋮---- expectedOrder := []uint32{2, 9, 11, 100, 1000} // Expected numeric order ⋮---- // Save signatures with test indices ⋮---- sigCopy.PublicKey = priv.PublicKey() // Different public key for each ⋮---- // Retrieve all signatures and verify they are returned in numeric order ⋮---- // Verify each signature can be retrieved by its expected index ⋮---- // Verify this is the signature we expect (by checking the public key byte) ⋮---- // The signature returned by GetAllSignatures should match ⋮---- func TestBadgerRepository_GetSignaturesStartingFromEpoch(t *testing.T) ⋮---- // Create three signatures with epochs 1, 2, 3 ⋮---- // Save all three signatures ⋮---- // Query starting from epoch 2 ⋮---- // Should return exactly 2 signatures (epochs 2 and 3) ⋮---- // Verify epochs are 2 and 3 ⋮---- // Query starting from epoch 1 - should return all 3 ⋮---- // Query starting from epoch 3 - should return only epoch 3 ⋮---- func TestBadgerRepository_GetSignaturesByEpoch(t *testing.T) ```` ## File: internal/client/repository/badger/badger_repository_signature.go ````go package badger ⋮---- import ( "context" "fmt" "log/slog" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "fmt" "log/slog" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func keySignature(requestID common.Hash, validatorIndex uint32) []byte ⋮---- func keySignatureRequestIDPrefix(requestID common.Hash) []byte ⋮---- func (r *Repository) saveSignature( ctx context.Context, validatorIndex uint32, sig symbiotic.Signature, ) error ⋮---- func (r *Repository) GetAllSignatures(ctx context.Context, requestID common.Hash) ([]symbiotic.Signature, error) ⋮---- var signatures []symbiotic.Signature ⋮---- var err error ⋮---- func (r *Repository) GetSignatureByIndex(ctx context.Context, requestID common.Hash, validatorIndex uint32) (symbiotic.Signature, error) ⋮---- var signature symbiotic.Signature ⋮---- func (r *Repository) GetSignaturesStartingFromEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.Signature, error) ⋮---- func (r *Repository) GetSignaturesByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.Signature, error) ⋮---- func (r *Repository) getSignaturesByEpochFromItem(txn *badger.Txn, it *badger.Iterator) ([]symbiotic.Signature, error) ⋮---- func gatAllSignatures(txn *badger.Txn, requestID common.Hash) ([]symbiotic.Signature, error) ⋮---- func signatureToBytes(sig symbiotic.Signature) ([]byte, error) ⋮---- func bytesToSignature(value []byte) (symbiotic.Signature, error) ```` ## File: internal/client/repository/badger/badger_repository_test.go ````go package badger ⋮---- import ( "crypto/rand" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "crypto/rand" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func randomBytes(t *testing.T, n int) []byte ⋮---- func randomAddr(t *testing.T) symbiotic.CrossChainAddress ⋮---- func randomBigInt(t *testing.T) *big.Int ⋮---- func TestKeyRequestIDEpoch(t *testing.T) ⋮---- epoch: ^symbiotic.Epoch(0), // max uint64 ⋮---- func TestExtractRequestIDFromEpochKey_InvalidKeys(t *testing.T) ⋮---- func TestKeyRequestIDEpochPrefix(t *testing.T) ⋮---- func TestKeyRequestIDEpochAll(t *testing.T) ```` ## File: internal/client/repository/badger/badger_repository_transaction_test.go ````go package badger ⋮---- import ( "context" "testing" "github.com/dgraph-io/badger/v4" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) ⋮---- "context" "testing" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- func TestRepository_DoUpdateInTx(t *testing.T) ⋮---- var executedInTx bool ⋮---- // Verify we have a transaction in the context ⋮---- // Perform a simple write operation ⋮---- // Verify the data was actually committed ⋮---- // Write some data ⋮---- // Return an error to trigger rollback ⋮---- // Verify the data was not committed due to rollback ⋮---- var outerTxn, innerTxn *badger.Txn ⋮---- // Nested transaction should reuse the same transaction ⋮---- // Should be the same transaction object ⋮---- // Write data using the nested context ⋮---- // Verify the nested write was committed ⋮---- // Write multiple keys in the same transaction ⋮---- // Verify all data was committed atomically ⋮---- // Attempt to perform write operation in view transaction // This should fail because view transactions are read-only ⋮---- // BadgerDB returns ErrReadOnlyTxn when trying to write in a read-only transaction ⋮---- // First create a key to attempt to delete ⋮---- // Now try to delete it in a view transaction ⋮---- // Attempt to delete in view transaction ⋮---- // Verify the key still exists (delete didn't work) ```` ## File: internal/client/repository/badger/badger_repository_transaction.go ````go package badger ⋮---- import ( "context" "sync" "sync/atomic" "time" "github.com/dgraph-io/badger/v4" "github.com/go-errors/errors" "github.com/samber/lo" "github.com/symbioticfi/relay/internal/entity" ) ⋮---- "context" "sync" "sync/atomic" "time" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/go-errors/errors" "github.com/samber/lo" ⋮---- "github.com/symbioticfi/relay/internal/entity" ⋮---- type ctxTxnKey struct{} ⋮---- var badgerTxnKey ctxTxnKey ⋮---- type ctxQueryNameKey struct{} ⋮---- var ctxQueryName ctxQueryNameKey ⋮---- // mutexWithUseTime wraps a mutex with a timestamp of last access type mutexWithUseTime struct { mutex sync.Mutex lastAccessNs atomic.Int64 // Unix nanoseconds } ⋮---- lastAccessNs atomic.Int64 // Unix nanoseconds ⋮---- func (m *mutexWithUseTime) lock() ⋮---- func (m *mutexWithUseTime) unlock() ⋮---- func (m *mutexWithUseTime) lastAccess() time.Time ⋮---- func (m *mutexWithUseTime) tryLock() bool ⋮---- func (r *Repository) doUpdateInTxWithLock(ctx context.Context, name string, f func(ctx context.Context) error, lockMap *sync.Map, key any) error ⋮---- func (r *Repository) doUpdateInTx(ctx context.Context, name string, f func(ctx context.Context) error) error ⋮---- func (r *Repository) doViewInTx(ctx context.Context, name string, f func(ctx context.Context) error) error ⋮---- func getTxn(ctx context.Context) *badger.Txn ⋮---- func (r *Repository) withName(ctx context.Context, name string) context.Context ⋮---- func nameFromCtx(ctx context.Context) string ```` ## File: internal/client/repository/badger/badger_repository_validator_set_test.go ````go package badger ⋮---- import ( "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestRepository_ValidatorSet(t *testing.T) ⋮---- // Create two validator sets with different epochs ⋮---- // Test saving validator sets ⋮---- // Save newer epoch first ⋮---- // Save older epoch ⋮---- // Try to save the same epoch again ⋮---- // Test getting validator set by epoch ⋮---- // Get newer epoch ⋮---- // Get older epoch ⋮---- // Get non-existent epoch ⋮---- // Test getting latest validator set via epoch lookup ⋮---- // Latest should be vs1 (epoch 2) even though we saved it first ⋮---- // Test getting latest validator set epoch ⋮---- // Latest epoch should be vs1's epoch (2) even though we saved it first ⋮---- // Test getting validator set header by epoch ⋮---- // Get header for newer epoch ⋮---- // Verify header matches expected values from validator set ⋮---- // Get header for older epoch ⋮---- // Get non-existent epoch header ⋮---- // Test getting latest validator set header ⋮---- // Latest header should be from vs1 (epoch 2) ⋮---- // Test getting individual validators by key ⋮---- // Test with vs1 (epoch 2) ⋮---- // Get validator by key should return the correct validator ⋮---- // Test with vs2 (epoch 1) ⋮---- // Test non-existent validator ⋮---- // Test non-existent epoch ⋮---- func TestRepository_ValidatorSet_EmptyRepository(t *testing.T) ⋮---- func TestRepository_GetOldestValidatorSetEpoch(t *testing.T) ⋮---- func TestRepository_ValidatorSet_EpochOrdering(t *testing.T) ⋮---- // Create validator sets with different epochs in non-chronological order ⋮---- // Save them in random order require.NoError(t, repo.SaveValidatorSet(t.Context(), vs2)) // epoch 1 require.NoError(t, repo.SaveValidatorSet(t.Context(), vs4)) // epoch 3 require.NoError(t, repo.SaveValidatorSet(t.Context(), vs3)) // epoch 10 require.NoError(t, repo.SaveValidatorSet(t.Context(), vs1)) // epoch 5 ⋮---- assert.Equal(t, vs3, latest) // epoch 10 should be latest ⋮---- assert.Equal(t, vs3.Epoch, latestEpoch) // epoch 10 should be latest ⋮---- func TestRepository_ValidatorSet_ValidatorIndexing(t *testing.T) ⋮---- // Create a validator set with multiple validators having multiple keys ⋮---- // Should be able to find validator by any of their keys ⋮---- wrongKeyTag := key.Tag + 100 // Use a different key tag ⋮---- // Should not find validator with wrong key tag but same payload ⋮---- func TestRepository_ValidatorSet_MultiKeyStorageProblem(t *testing.T) ⋮---- // Create a validator with multiple keys to test storage duplication ⋮---- // Modify the first validator to have 3 different keys ⋮---- // Retrieve the validator set and check if deduplication works correctly ⋮---- // The validator should appear only once despite having multiple keys ⋮---- // Find our multi-key validator in the retrieved set var foundValidator *symbiotic.Validator ⋮---- // Verify the validator has all its keys ⋮---- func TestRepository_LatestSignedValidatorSetEpoch(t *testing.T) ⋮---- // Create validator sets with different epochs ⋮---- // Save the validator sets first (required for referential integrity) ⋮---- // Save latest signed epoch for vs1 (epoch 1) ⋮---- // Get latest signed epoch - should be vs1.Epoch (1) ⋮---- // Save latest signed epoch for vs3 (epoch 3) - should overwrite ⋮---- // Get latest signed epoch - should now be vs3.Epoch (3) ⋮---- // Save latest signed epoch for vs2 (epoch 5) - should overwrite again ⋮---- // Get latest signed epoch - should now be vs2.Epoch (5) ⋮---- // At this point: // - Latest validator set epoch should be 5 (highest saved epoch) // - Latest signed validator set epoch should be 5 (from previous test) ⋮---- // Now save a signed epoch that's lower than the latest validator set err = repo.SaveLatestSignedValidatorSetEpoch(t.Context(), vs1) // epoch 1 ⋮---- // Latest validator set epoch should remain 5 ⋮---- // But latest signed epoch should now be 1 ⋮---- func TestRepository_LatestSignedValidatorSetEpoch_EmptyRepository(t *testing.T) ⋮---- // This should work - the implementation doesn't enforce referential integrity ⋮---- // Should be able to retrieve it ⋮---- func TestRepository_LatestSignedValidatorSetEpoch_Ordering(t *testing.T) ⋮---- // Save signed epochs in a specific order and verify each one testOrder := []int{2, 0, 4, 1, 5, 3} // Indices into validatorSets array ⋮---- // Verify it was saved correctly ⋮---- // Final latest signed epoch should be from the last saved (index 3 = epoch 5) ⋮---- // But latest validator set epoch should be the highest saved epoch (15) ⋮---- func TestRepository_ValidatorSet_ActiveIndex(t *testing.T) ⋮---- // Create validator set with mixed active/inactive validators ⋮---- // Modify validators to have specific active/inactive states and addresses // Note: validators must be sorted by operator address ascending ⋮---- IsActive: true, // Should get active index 0 (first when sorted by address) ⋮---- IsActive: false, // Should get active index 0 (inactive) - positioned between two active validators ⋮---- IsActive: true, // Should get active index 1 (second active validator, despite inactive validator in between) ⋮---- // Save validator set ⋮---- // Test first active validator (0x0000... should be index 0) ⋮---- // Test second active validator (0x3333... should be index 1, even though inactive 0x2222... is between them) ⋮---- // Test inactive validator ⋮---- func TestRepository_FirstUncommittedValidatorSetEpoch(t *testing.T) ⋮---- // Save first uncommitted epoch ⋮---- // Get first uncommitted epoch ⋮---- // Update to a different epoch ⋮---- // Verify it was updated ⋮---- func TestRepository_FirstUncommittedValidatorSetEpoch_EmptyRepository(t *testing.T) ⋮---- // Should return 0 and no error when not set (based on implementation) ⋮---- func TestRepository_GetValidatorSetsByEpoch(t *testing.T) ⋮---- // Create three validator sets with epochs 1, 2, 3 ⋮---- // Save all three validator sets ⋮---- // Query starting from epoch 2 ⋮---- // Should return exactly 2 validator sets (epochs 2 and 3) ⋮---- // First result should be epoch 2 ⋮---- // Second result should be epoch 3 ⋮---- // Query starting from epoch 1 - should return all 3 ⋮---- // Query starting from epoch 3 - should return only epoch 3 ⋮---- // Query starting from epoch 10 (doesn't exist) - should return empty ⋮---- func setupTestRepository(t *testing.T) *Repository ⋮---- func randomValidatorSet(t *testing.T, epoch symbiotic.Epoch) symbiotic.ValidatorSet ```` ## File: internal/client/repository/badger/badger_repository_validator_set.go ````go package badger ⋮---- import ( "context" "encoding/binary" "fmt" "math/big" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/samber/lo" pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "encoding/binary" "fmt" "math/big" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/samber/lo" ⋮---- pb "github.com/symbioticfi/relay/internal/client/repository/badger/proto/v1" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( latestValidatorSetEpochKey = "latest_validator_set_epoch" latestSignedValidatorSetEpochKey = "latest_signed_validator_set_epoch" firstUncommittedValidatorSetEpoch = "first_uncommitted_validator_set_epoch" ) ⋮---- // keyValidatorSetHeader returns key for validator set header // Format: "validator_set_header:" + epoch.Bytes() // Using epoch.Bytes() ensures proper lexicographic sorting func keyValidatorSetHeader(epoch symbiotic.Epoch) []byte ⋮---- // keyValidatorSetHeaderPrefix returns prefix for all validator set headers func keyValidatorSetHeaderPrefix() []byte ⋮---- func keyValidatorByOperator(epoch symbiotic.Epoch, operator common.Address) []byte ⋮---- func keyValidatorKeyLookup(epoch symbiotic.Epoch, keyTag symbiotic.KeyTag, publicKeyHash common.Hash) []byte ⋮---- func keyValidatorSetStatus(epoch symbiotic.Epoch) []byte ⋮---- func keyValidatorSetMetadata(epoch symbiotic.Epoch) []byte ⋮---- func (r *Repository) SaveValidatorSetMetadata(ctx context.Context, data symbiotic.ValidatorSetMetadata) error ⋮---- func (r *Repository) GetValidatorSetMetadata(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSetMetadata, error) ⋮---- var metadata symbiotic.ValidatorSetMetadata ⋮---- func (r *Repository) SaveValidatorSet(ctx context.Context, valset symbiotic.ValidatorSet) error ⋮---- // Check if this epoch already exists by checking the header ⋮---- // Save the validator set header for its epoch ⋮---- // Check if this is a newer epoch than the latest one ⋮---- // Update latest validator set epoch only if this is a newer epoch ⋮---- // Save individual validators and their key indexes ⋮---- // Save the validator data once ⋮---- // Create an index for each key that points to the validator's operator address ⋮---- // Store the total active validator count for this epoch ⋮---- func (r *Repository) SaveLatestSignedValidatorSetEpoch(ctx context.Context, valset symbiotic.ValidatorSet) error ⋮---- func (r *Repository) SaveFirstUncommittedValidatorSetEpoch(ctx context.Context, epoch symbiotic.Epoch) error ⋮---- func (r *Repository) UpdateValidatorSetStatusAndRemovePendingProof(ctx context.Context, valset symbiotic.ValidatorSet) error ⋮---- func (r *Repository) UpdateValidatorSetStatus(ctx context.Context, valset symbiotic.ValidatorSet) error ⋮---- func (r *Repository) GetValidatorSetHeaderByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSetHeader, error) ⋮---- var header symbiotic.ValidatorSetHeader ⋮---- func (r *Repository) getAllValidatorsByEpoch(txn *badger.Txn, epoch symbiotic.Epoch) (symbiotic.Validators, error) ⋮---- var validators symbiotic.Validators ⋮---- func (r *Repository) GetValidatorSetsStartingFromEpoch(ctx context.Context, startEpoch symbiotic.Epoch) ([]symbiotic.ValidatorSet, error) ⋮---- var validatorSets []symbiotic.ValidatorSet ⋮---- // Create iterator starting from startEpoch ⋮---- func (r *Repository) GetValidatorSetByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) ⋮---- var vs symbiotic.ValidatorSet ⋮---- // Get the validator set header ⋮---- // Get all validators for this epoch ⋮---- // Extract bitmap indices from header data ⋮---- // Build the validator set from header + validators ⋮---- func (r *Repository) GetLatestValidatorSetHeader(ctx context.Context) (symbiotic.ValidatorSetHeader, error) ⋮---- // Get the latest epoch ⋮---- // Get the validator set header for that epoch in the same transaction ⋮---- func (r *Repository) GetLatestValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) ⋮---- var epoch symbiotic.Epoch ⋮---- func keyActiveValidatorCount(epoch symbiotic.Epoch) []byte ⋮---- func (r *Repository) GetActiveValidatorCountByEpoch(ctx context.Context, epoch symbiotic.Epoch) (uint32, error) ⋮---- var count uint32 ⋮---- func (r *Repository) GetOldestValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) ⋮---- func (r *Repository) GetLatestSignedValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) ⋮---- func (r *Repository) GetFirstUncommittedValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) ⋮---- func (r *Repository) GetValidatorByKey(ctx context.Context, epoch symbiotic.Epoch, keyTag symbiotic.KeyTag, publicKey []byte) (symbiotic.Validator, uint32, error) ⋮---- var validator symbiotic.Validator var activeIndex uint32 ⋮---- // First, find the operator address from the key lookup table ⋮---- // Now, retrieve the full validator data ⋮---- // This would indicate data inconsistency ⋮---- func validatorToBytes(validator symbiotic.Validator, activeIndex uint32) ([]byte, error) ⋮---- func bytesToValidator(data []byte) (symbiotic.Validator, uint32, error) ⋮---- func validatorSetHeaderToBytes(valset symbiotic.ValidatorSet) ([]byte, error) ⋮---- var aggIndices, commIndices []byte ⋮---- func bytesToValidatorSetHeader(data []byte) (symbiotic.ValidatorSetHeader, error) ⋮---- func extractAdditionalInfoFromHeaderData(data []byte) (aggIndices []uint32, commIndices []uint32, err error) ⋮---- func validatorSetMetadataToBytes(data symbiotic.ValidatorSetMetadata) ([]byte, error) ⋮---- func bytesToValidatorSetMetadata(data []byte) (symbiotic.ValidatorSetMetadata, error) ```` ## File: internal/client/repository/badger/badger_repository.go ````go package badger ⋮---- import ( "log/slog" "sync" "time" "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/protobuf/proto" ) ⋮---- "log/slog" "sync" "time" ⋮---- "github.com/dgraph-io/badger/v4" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/protobuf/proto" ⋮---- type Config struct { Dir string `validate:"required"` Metrics metrics `validate:"required"` MutexCleanupInterval time.Duration // How often to run mutex cleanup (e.g., 1 hour). Zero disables cleanup. MutexCleanupStaleTimeout time.Duration // Remove mutexes not used for this duration, default 1 hour. } ⋮---- MutexCleanupInterval time.Duration // How often to run mutex cleanup (e.g., 1 hour). Zero disables cleanup. MutexCleanupStaleTimeout time.Duration // Remove mutexes not used for this duration, default 1 hour. ⋮---- func (c Config) Validate() error ⋮---- type metrics interface { ObserveRepoQueryDuration(queryName string, status string, d time.Duration) ObserveRepoQueryTotalDuration(queryName string, status string, d time.Duration) } ⋮---- type Repository struct { db *badger.DB metrics metrics signatureMutexMap sync.Map // map[requestId]*mutexWithUseTime proofsMutexMap sync.Map // map[requestId]*mutexWithUseTime valsetMutexMap sync.Map // map[epoch]*mutexWithUseTime cleanupStop chan struct{} ⋮---- signatureMutexMap sync.Map // map[requestId]*mutexWithUseTime proofsMutexMap sync.Map // map[requestId]*mutexWithUseTime valsetMutexMap sync.Map // map[epoch]*mutexWithUseTime ⋮---- func New(cfg Config) (*Repository, error) ⋮---- // Start mutex cleanup goroutine if configured ⋮---- func (r *Repository) Close() error ⋮---- // Stop the mutex cleanup goroutine before closing the database ⋮---- type doNothingLog struct{} ⋮---- func (l doNothingLog) Errorf(s string, args ...interface func (l doNothingLog) Warningf(s string, args ...interface func (l doNothingLog) Infof(s string, args ...interface func (l doNothingLog) Debugf(s string, args ...interface ⋮---- type DoNothingMetrics struct { } ⋮---- func (m DoNothingMetrics) ObserveRepoQueryDuration(queryName string, status string, d time.Duration) func (m DoNothingMetrics) ObserveRepoQueryTotalDuration(queryName string, status string, d time.Duration) ⋮---- func marshalProto(msg proto.Message) ([]byte, error) ⋮---- func unmarshalProto(data []byte, msg proto.Message) error ⋮---- // startMutexCleanup starts a background goroutine that periodically cleans up stale mutexes func (r *Repository) startMutexCleanup(interval, staleTimeout time.Duration) ⋮---- // If interval is 0, cleanup is disabled ⋮---- // stopMutexCleanup stops the background cleanup goroutine func (r *Repository) stopMutexCleanup() ⋮---- // cleanupStaleMutexes removes mutexes that haven't been used for longer than cleanupStaleAfter func (r *Repository) cleanupStaleMutexes(staleTimeout time.Duration) ⋮---- // Default stale timeout to 1 hour if not set ⋮---- // cleanupMutexMap removes stale mutexes from a single sync.Map using double-check pattern func cleanupMutexMap(mutexMap *sync.Map, staleThreshold time.Time) int ⋮---- var count int ⋮---- // First check: if recently accessed, skip ⋮---- // Try to acquire the lock to ensure it's not in use ⋮---- // Double-check last access time after acquiring lock // This handles the race where updateAccess() was called between the first check and TryLock ⋮---- // Safe to delete now ⋮---- var errCorruptedRequestIDEpochLink = errors.New("corrupted request id epoch link") ⋮---- func keyRequestIDEpoch(epoch symbiotic.Epoch, requestID common.Hash) []byte ⋮---- func keyRequestIDEpochPrefix(epoch symbiotic.Epoch) []byte ⋮---- func keyRequestIDEpochAll() []byte ⋮---- const ( epochLen = 8 hashLen = 32 ) ⋮---- // extractRequestIDFromEpochKey extracts request ID from the epoch key link // Key format: "request_id_epoch" (16 bytes) + epoch (8 bytes) + requestID (32 bytes) func extractRequestIDFromEpochKey(key []byte) (common.Hash, error) ```` ## File: internal/client/repository/badger/cached_repository_test.go ````go package badger ⋮---- import ( "context" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestCachedRepository_NetworkConfig(t *testing.T) ⋮---- // Create temporary directory for test ⋮---- // Create base repository ⋮---- // Create cached repository ⋮---- // Create test network config ⋮---- // Test cache miss - config doesn't exist ⋮---- // Save config ⋮---- // Test cache hit - should retrieve from cache ⋮---- // Test cache hit again - should still work ⋮---- func TestCachedRepository_InheritedMethods(t *testing.T) ⋮---- // Test that inherited methods work (non-cached methods) // This tests that embedding is working correctly ⋮---- func TestCachedRepository_ValidatorSet(t *testing.T) ⋮---- // Create test validator set ⋮---- // Test cache miss - validator set doesn't exist ⋮---- // Save validator set ```` ## File: internal/client/repository/badger/cached_repository.go ````go package badger ⋮---- import ( "context" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/client/repository/cache" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/client/repository/cache" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type CachedConfig struct { NetworkConfigCacheSize int ValidatorSetCacheSize int } ⋮---- type CachedRepository struct { *Repository networkConfigCache cache.Cache[symbiotic.Epoch, symbiotic.NetworkConfig] validatorSetCache cache.Cache[symbiotic.Epoch, symbiotic.ValidatorSet] validatorSetMetadataCache cache.Cache[symbiotic.Epoch, symbiotic.ValidatorSetMetadata] } ⋮---- func NewCached(repo *Repository, cfg CachedConfig) (*CachedRepository, error) ⋮---- func (r *CachedRepository) GetConfigByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) ⋮---- // Try cache first ⋮---- // Cache miss - load from underlying repository ⋮---- // Store in cache for future use ⋮---- func (r *CachedRepository) SaveConfig(ctx context.Context, config symbiotic.NetworkConfig, epoch symbiotic.Epoch) error ⋮---- // Cache the newly saved config ⋮---- func (r *CachedRepository) GetValidatorSetByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) ⋮---- func (r *CachedRepository) GetValidatorSetMetadata(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSetMetadata, error) ⋮---- func (r *CachedRepository) SaveValidatorSet(ctx context.Context, validatorSet symbiotic.ValidatorSet) error ⋮---- // Cache the newly saved validator set ⋮---- func (r *CachedRepository) SaveValidatorSetMetadata(ctx context.Context, validatorSetMetadata symbiotic.ValidatorSetMetadata) error ```` ## File: internal/client/repository/cache/generic_cache.go ````go package cache ⋮---- import ( "github.com/elastic/go-freelru" "github.com/go-errors/errors" ) ⋮---- "github.com/elastic/go-freelru" "github.com/go-errors/errors" ⋮---- // Cache provides a generic LRU cache interface type Cache[K comparable, V any] interface { Get(key K) (V, bool) Add(key K, value V) } ⋮---- // Config holds cache configuration type Config struct { Size int } ⋮---- // lruCache implements Cache using freelru type lruCache[K comparable, V any] struct { cache *freelru.ShardedLRU[K, V] } ⋮---- // NewCache creates a new generic LRU cache func NewCache[K comparable, V any](cfg Config, hashFunc func(K) uint32) (Cache[K, V], error) ⋮---- cfg.Size = 50 // default cache size ⋮---- func (c *lruCache[K, V]) Get(key K) (V, bool) ⋮---- func (c *lruCache[K, V]) Add(key K, value V) ```` ## File: internal/entity/entity_aggregation_proof_sync_test.go ````go package entity ⋮---- import ( "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestAggregationProofSync_Integration(t *testing.T) ⋮---- // Step 1: Create request for missing aggregation proofs ⋮---- // Step 2: Create response with available proofs (only 2 out of 3) ⋮---- // hash3 is missing - peer doesn't have it ⋮---- // Step 3: Process response and track stats ⋮---- // Simulate processing each requested hash ⋮---- // Proof found and processed successfully _ = proof // Use the proof ⋮---- // Proof not found in response - no error, just missing // This is normal behavior when peers don't have all proofs ⋮---- // Step 4: Simulate some processing errors for remaining proof stats.VerificationFailCount = 1 // hash3 had verification error ```` ## File: internal/entity/entity_error.go ````go package entity ⋮---- type StringError string ⋮---- func (e StringError) Error() string ⋮---- const ( ErrEntityNotFound = StringError("entity not found") ```` ## File: internal/entity/entity_signature_map_test.go ````go package entity ⋮---- import ( "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestSignatureMap_SetValidatorPresent(t *testing.T) ⋮---- // Setup common test data ⋮---- vm := NewSignatureMap(requestID, symbiotic.Epoch(epoch), 2) // 2 total validators for setup ⋮---- // Verify validator index is marked as present ⋮---- // Verify voting power is updated expectedVotingPower := symbiotic.ToVotingPower(big.NewInt(100)) // activeValidator1's voting power ⋮---- // Set first validator present (index 0) ⋮---- // Set second validator present (index 1) ⋮---- // Verify both validator indexes are marked as present ⋮---- // Verify total voting power is cumulative expectedVotingPower := symbiotic.ToVotingPower(big.NewInt(300)) // 100 + 200 ⋮---- // Set validator index present first time ⋮---- // Try to set the same validator index present again ⋮---- // Verify voting power is not double-counted expectedVotingPower := symbiotic.ToVotingPower(big.NewInt(100)) // Should still be 100, not 200 ⋮---- func TestSignatureMap_ThresholdReached(t *testing.T) ⋮---- func TestSignatureMap_IntegrationScenarios(t *testing.T) ⋮---- // Setup validators with different voting powers ⋮---- // Total active voting power: 750 // Set quorum threshold to 67% (approximately 500) ⋮---- vm := NewSignatureMap(requestID, symbiotic.Epoch(epoch), 4) // 4 total validators ⋮---- // Verify initial state ⋮---- // Add first validator (100) - threshold not reached ⋮---- // Add second validator (100 + 200 = 300) - threshold not reached ⋮---- // Add third validator (300 + 300 = 600) - threshold reached! ⋮---- // Add fourth validator (600 + 150 = 750) - threshold still reached ⋮---- IsActive: false, // Inactive - not available for signatures ⋮---- // Total active voting power: 300 (only first two validators) // Set high quorum threshold that can't be reached ⋮---- // Add all available active validators (first two are active) ⋮---- // Even with all active validators, threshold should not be reached ⋮---- // Total active voting power: 500 // Set quorum threshold to 100% ⋮---- // Add first validator - threshold not reached ⋮---- // Add second validator - threshold exactly reached ⋮---- func TestSignatureMap_GetMissingValidators(t *testing.T) ⋮---- // All validators should be missing ⋮---- // Set validators 0 and 2 as present ⋮---- // Only validators 1 and 3 should be missing ⋮---- // Set all validators as present ⋮---- // No validators should be missing ⋮---- // Single validator should be missing ⋮---- // After setting present ⋮---- func TestBitmapFromBytes(t *testing.T) ⋮---- // Create a bitmap with some values ⋮---- // Serialize to bytes ⋮---- // Deserialize from bytes ⋮---- // Verify the restored bitmap has the same values ⋮---- // Create empty bitmap ⋮---- // Verify the restored bitmap is empty ⋮---- // Test with invalid byte sequence ⋮---- // Create bitmap with large indices ⋮---- // Verify all large indices are preserved ⋮---- // Test multiple roundtrips to ensure consistency ⋮---- // Serialize ⋮---- // Deserialize ⋮---- // Verify equality ⋮---- // Use restored for next iteration ```` ## File: internal/entity/entity_signature_map.go ````go package entity ⋮---- import ( "math/big" "github.com/RoaringBitmap/roaring/v2" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" ⋮---- "github.com/RoaringBitmap/roaring/v2" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type SignatureMap struct { RequestID common.Hash Epoch symbiotic.Epoch SignedValidatorsBitmap Bitmap CurrentVotingPower symbiotic.VotingPower TotalValidators uint32 } ⋮---- func NewSignatureMap(requestID common.Hash, epoch symbiotic.Epoch, totalValidators uint32) SignatureMap ⋮---- func (vm *SignatureMap) SetValidatorPresent(activeIndex uint32, votingPower symbiotic.VotingPower) error ⋮---- func (vm *SignatureMap) ThresholdReached(quorumThreshold symbiotic.VotingPower) bool ⋮---- func (vm *SignatureMap) GetMissingValidators() Bitmap ⋮---- type Bitmap struct { *roaring.Bitmap } ⋮---- func NewBitmap() Bitmap ⋮---- func NewBitmapOf(dat ...uint32) Bitmap ⋮---- func BitmapFromBytes(b []byte) (Bitmap, error) ```` ## File: internal/entity/entity_signature_request.go ````go package entity ⋮---- import ( "github.com/ethereum/go-ethereum/common" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "github.com/ethereum/go-ethereum/common" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // SignatureRequestWithID represents a signature request with its request ID type SignatureRequestWithID struct { RequestID common.Hash SignatureRequest symbiotic.SignatureRequest } ```` ## File: internal/entity/entity_signature_sync.go ````go package entity ⋮---- import ( "github.com/ethereum/go-ethereum/common" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "github.com/ethereum/go-ethereum/common" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // WantSignaturesRequest represents a request to resync signatures for a specific epoch. // Contains missing validator indices for each incomplete signature request. type WantSignaturesRequest struct { WantSignatures map[common.Hash]Bitmap // requestID -> missing validator indices bitmap } ⋮---- WantSignatures map[common.Hash]Bitmap // requestID -> missing validator indices bitmap ⋮---- // WantSignaturesResponse contains signatures grouped by Request id. // Each signature includes the validator index for consistent mapping. type WantSignaturesResponse struct { Signatures map[common.Hash][]ValidatorSignature } ⋮---- // ValidatorSignature pairs a signature with its validator index in the active validator set. // The validator index corresponds to the position in ValidatorSet.Validators.GetActiveValidators(). type ValidatorSignature struct { ValidatorIndex uint32 // Index in active validator set Signature symbiotic.Signature // The actual signature data } ⋮---- ValidatorIndex uint32 // Index in active validator set Signature symbiotic.Signature // The actual signature data ⋮---- // SignatureProcessingStats contains detailed statistics for processing received signatures type SignatureProcessingStats struct { ProcessedCount int // Successfully processed signatures UnrequestedSignatureCount int // Signatures for validators we didn't request UnrequestedHashCount int // Signatures for hashes we didn't request SignatureRequestFailCount int // Failed to get signature request ProcessingFailCount int // Failed to process signature AlreadyExistCount int // Signature already exists (ErrEntityAlreadyExist) } ⋮---- ProcessedCount int // Successfully processed signatures UnrequestedSignatureCount int // Signatures for validators we didn't request UnrequestedHashCount int // Signatures for hashes we didn't request SignatureRequestFailCount int // Failed to get signature request ProcessingFailCount int // Failed to process signature AlreadyExistCount int // Signature already exists (ErrEntityAlreadyExist) ⋮---- // TotalErrors returns the total number of errors encountered func (s SignatureProcessingStats) TotalErrors() int ⋮---- // WantAggregationProofsRequest represents a request to resync aggregation proofs for specific signature requests. // Contains request ids for which aggregation proofs are needed. type WantAggregationProofsRequest struct { RequestIDs []common.Hash // requestID list for missing aggregation proofs } ⋮---- RequestIDs []common.Hash // requestID list for missing aggregation proofs ⋮---- // WantAggregationProofsResponse contains aggregation proofs grouped by request id. // Each aggregation proof corresponds to a complete signature aggregation for a request. type WantAggregationProofsResponse struct { Proofs map[common.Hash]symbiotic.AggregationProof // requestID -> aggregation proof } ⋮---- Proofs map[common.Hash]symbiotic.AggregationProof // requestID -> aggregation proof ⋮---- // AggregationProofProcessingStats contains detailed statistics for processing received aggregation proofs type AggregationProofProcessingStats struct { ProcessedCount int // Successfully processed aggregation proofs UnrequestedProofCount int // Proofs for hashes we didn't request VerificationFailCount int // Failed to verify aggregation proof ProcessingFailCount int // Failed to process aggregation proof AlreadyExistCount int // Aggregation proof already exists (ErrEntityAlreadyExist) } ⋮---- ProcessedCount int // Successfully processed aggregation proofs UnrequestedProofCount int // Proofs for hashes we didn't request VerificationFailCount int // Failed to verify aggregation proof ProcessingFailCount int // Failed to process aggregation proof AlreadyExistCount int // Aggregation proof already exists (ErrEntityAlreadyExist) ```` ## File: internal/entity/p2p_entity.go ````go package entity ⋮---- type SenderInfo struct { // Sender is a p2p peer id Sender string PublicKey []byte } ⋮---- // Sender is a p2p peer id ⋮---- // P2PMessage is a generic message structure for P2P communication, containing SenderInfo and a message of type T. type P2PMessage[T any] struct { SenderInfo SenderInfo Message T } ```` ## File: internal/gen/api/v1/api_grpc.pb.go ````go // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 // - protoc (unknown) // source: v1/api.proto ⋮---- package v1 ⋮---- import ( context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ) ⋮---- context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ⋮---- // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. // Requires gRPC-Go v1.64.0 or later. const _ = grpc.SupportPackageIsVersion9 ⋮---- const ( SymbioticAPIService_SignMessage_FullMethodName = "/api.proto.v1.SymbioticAPIService/SignMessage" SymbioticAPIService_GetAggregationProof_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetAggregationProof" SymbioticAPIService_GetAggregationProofsByEpoch_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetAggregationProofsByEpoch" SymbioticAPIService_GetCurrentEpoch_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetCurrentEpoch" SymbioticAPIService_GetSignatures_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetSignatures" SymbioticAPIService_GetSignaturesByEpoch_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetSignaturesByEpoch" SymbioticAPIService_GetSignatureRequestIDsByEpoch_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetSignatureRequestIDsByEpoch" SymbioticAPIService_GetSignatureRequestsByEpoch_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetSignatureRequestsByEpoch" SymbioticAPIService_GetSignatureRequest_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetSignatureRequest" SymbioticAPIService_GetAggregationStatus_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetAggregationStatus" SymbioticAPIService_GetValidatorSet_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetValidatorSet" SymbioticAPIService_GetValidatorByAddress_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetValidatorByAddress" SymbioticAPIService_GetValidatorByKey_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetValidatorByKey" SymbioticAPIService_GetLocalValidator_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetLocalValidator" SymbioticAPIService_GetValidatorSetHeader_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetValidatorSetHeader" SymbioticAPIService_GetLastCommitted_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetLastCommitted" SymbioticAPIService_GetLastAllCommitted_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetLastAllCommitted" SymbioticAPIService_GetValidatorSetMetadata_FullMethodName = "/api.proto.v1.SymbioticAPIService/GetValidatorSetMetadata" SymbioticAPIService_ListenSignatures_FullMethodName = "/api.proto.v1.SymbioticAPIService/ListenSignatures" SymbioticAPIService_ListenProofs_FullMethodName = "/api.proto.v1.SymbioticAPIService/ListenProofs" SymbioticAPIService_ListenValidatorSet_FullMethodName = "/api.proto.v1.SymbioticAPIService/ListenValidatorSet" ) ⋮---- // SymbioticAPIServiceClient is the client API for SymbioticAPIService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. ⋮---- // SymbioticAPI provides access to the Symbiotic relay functions type SymbioticAPIServiceClient interface { // Sign a message SignMessage(ctx context.Context, in *SignMessageRequest, opts ...grpc.CallOption) (*SignMessageResponse, error) // Get aggregation proof GetAggregationProof(ctx context.Context, in *GetAggregationProofRequest, opts ...grpc.CallOption) (*GetAggregationProofResponse, error) // Get aggregation proofs by epoch GetAggregationProofsByEpoch(ctx context.Context, in *GetAggregationProofsByEpochRequest, opts ...grpc.CallOption) (*GetAggregationProofsByEpochResponse, error) // Get current epoch GetCurrentEpoch(ctx context.Context, in *GetCurrentEpochRequest, opts ...grpc.CallOption) (*GetCurrentEpochResponse, error) // Get signature by request id GetSignatures(ctx context.Context, in *GetSignaturesRequest, opts ...grpc.CallOption) (*GetSignaturesResponse, error) // Get signature by epoch GetSignaturesByEpoch(ctx context.Context, in *GetSignaturesByEpochRequest, opts ...grpc.CallOption) (*GetSignaturesByEpochResponse, error) // Get all signature request IDs by epoch GetSignatureRequestIDsByEpoch(ctx context.Context, in *GetSignatureRequestIDsByEpochRequest, opts ...grpc.CallOption) (*GetSignatureRequestIDsByEpochResponse, error) // Get all signature requests by epoch GetSignatureRequestsByEpoch(ctx context.Context, in *GetSignatureRequestsByEpochRequest, opts ...grpc.CallOption) (*GetSignatureRequestsByEpochResponse, error) // Get signature request by request id GetSignatureRequest(ctx context.Context, in *GetSignatureRequestRequest, opts ...grpc.CallOption) (*GetSignatureRequestResponse, error) // Get aggregation status, can be sent only to aggregator nodes GetAggregationStatus(ctx context.Context, in *GetAggregationStatusRequest, opts ...grpc.CallOption) (*GetAggregationStatusResponse, error) // Get current validator set GetValidatorSet(ctx context.Context, in *GetValidatorSetRequest, opts ...grpc.CallOption) (*GetValidatorSetResponse, error) // Get validator by address GetValidatorByAddress(ctx context.Context, in *GetValidatorByAddressRequest, opts ...grpc.CallOption) (*GetValidatorByAddressResponse, error) // Get validator by key GetValidatorByKey(ctx context.Context, in *GetValidatorByKeyRequest, opts ...grpc.CallOption) (*GetValidatorByKeyResponse, error) // Get local validator GetLocalValidator(ctx context.Context, in *GetLocalValidatorRequest, opts ...grpc.CallOption) (*GetLocalValidatorResponse, error) // Get validator set header GetValidatorSetHeader(ctx context.Context, in *GetValidatorSetHeaderRequest, opts ...grpc.CallOption) (*GetValidatorSetHeaderResponse, error) // Get last committed epoch for a specific settlement chain GetLastCommitted(ctx context.Context, in *GetLastCommittedRequest, opts ...grpc.CallOption) (*GetLastCommittedResponse, error) // Get last committed epochs for all settlement chains GetLastAllCommitted(ctx context.Context, in *GetLastAllCommittedRequest, opts ...grpc.CallOption) (*GetLastAllCommittedResponse, error) // Get validator set metadata like extra data and request id to fetch aggregation and signature requests GetValidatorSetMetadata(ctx context.Context, in *GetValidatorSetMetadataRequest, opts ...grpc.CallOption) (*GetValidatorSetMetadataResponse, error) // Stream signatures in real-time. If start_epoch is provided, sends historical data first ListenSignatures(ctx context.Context, in *ListenSignaturesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ListenSignaturesResponse], error) // Stream aggregation proofs in real-time. If start_epoch is provided, sends historical data first ListenProofs(ctx context.Context, in *ListenProofsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ListenProofsResponse], error) // Stream validator set changes in real-time. If start_epoch is provided, sends historical data first ListenValidatorSet(ctx context.Context, in *ListenValidatorSetRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ListenValidatorSetResponse], error) } ⋮---- // Sign a message ⋮---- // Get aggregation proof ⋮---- // Get aggregation proofs by epoch ⋮---- // Get current epoch ⋮---- // Get signature by request id ⋮---- // Get signature by epoch ⋮---- // Get all signature request IDs by epoch ⋮---- // Get all signature requests by epoch ⋮---- // Get signature request by request id ⋮---- // Get aggregation status, can be sent only to aggregator nodes ⋮---- // Get current validator set ⋮---- // Get validator by address ⋮---- // Get validator by key ⋮---- // Get local validator ⋮---- // Get validator set header ⋮---- // Get last committed epoch for a specific settlement chain ⋮---- // Get last committed epochs for all settlement chains ⋮---- // Get validator set metadata like extra data and request id to fetch aggregation and signature requests ⋮---- // Stream signatures in real-time. If start_epoch is provided, sends historical data first ⋮---- // Stream aggregation proofs in real-time. If start_epoch is provided, sends historical data first ⋮---- // Stream validator set changes in real-time. If start_epoch is provided, sends historical data first ⋮---- type symbioticAPIServiceClient struct { cc grpc.ClientConnInterface } ⋮---- func NewSymbioticAPIServiceClient(cc grpc.ClientConnInterface) SymbioticAPIServiceClient ⋮---- func (c *symbioticAPIServiceClient) SignMessage(ctx context.Context, in *SignMessageRequest, opts ...grpc.CallOption) (*SignMessageResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetAggregationProof(ctx context.Context, in *GetAggregationProofRequest, opts ...grpc.CallOption) (*GetAggregationProofResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetAggregationProofsByEpoch(ctx context.Context, in *GetAggregationProofsByEpochRequest, opts ...grpc.CallOption) (*GetAggregationProofsByEpochResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetCurrentEpoch(ctx context.Context, in *GetCurrentEpochRequest, opts ...grpc.CallOption) (*GetCurrentEpochResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetSignatures(ctx context.Context, in *GetSignaturesRequest, opts ...grpc.CallOption) (*GetSignaturesResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetSignaturesByEpoch(ctx context.Context, in *GetSignaturesByEpochRequest, opts ...grpc.CallOption) (*GetSignaturesByEpochResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetSignatureRequestIDsByEpoch(ctx context.Context, in *GetSignatureRequestIDsByEpochRequest, opts ...grpc.CallOption) (*GetSignatureRequestIDsByEpochResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetSignatureRequestsByEpoch(ctx context.Context, in *GetSignatureRequestsByEpochRequest, opts ...grpc.CallOption) (*GetSignatureRequestsByEpochResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetSignatureRequest(ctx context.Context, in *GetSignatureRequestRequest, opts ...grpc.CallOption) (*GetSignatureRequestResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetAggregationStatus(ctx context.Context, in *GetAggregationStatusRequest, opts ...grpc.CallOption) (*GetAggregationStatusResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetValidatorSet(ctx context.Context, in *GetValidatorSetRequest, opts ...grpc.CallOption) (*GetValidatorSetResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetValidatorByAddress(ctx context.Context, in *GetValidatorByAddressRequest, opts ...grpc.CallOption) (*GetValidatorByAddressResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetValidatorByKey(ctx context.Context, in *GetValidatorByKeyRequest, opts ...grpc.CallOption) (*GetValidatorByKeyResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetLocalValidator(ctx context.Context, in *GetLocalValidatorRequest, opts ...grpc.CallOption) (*GetLocalValidatorResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetValidatorSetHeader(ctx context.Context, in *GetValidatorSetHeaderRequest, opts ...grpc.CallOption) (*GetValidatorSetHeaderResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetLastCommitted(ctx context.Context, in *GetLastCommittedRequest, opts ...grpc.CallOption) (*GetLastCommittedResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetLastAllCommitted(ctx context.Context, in *GetLastAllCommittedRequest, opts ...grpc.CallOption) (*GetLastAllCommittedResponse, error) ⋮---- func (c *symbioticAPIServiceClient) GetValidatorSetMetadata(ctx context.Context, in *GetValidatorSetMetadataRequest, opts ...grpc.CallOption) (*GetValidatorSetMetadataResponse, error) ⋮---- func (c *symbioticAPIServiceClient) ListenSignatures(ctx context.Context, in *ListenSignaturesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ListenSignaturesResponse], error) ⋮---- // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. ⋮---- func (c *symbioticAPIServiceClient) ListenProofs(ctx context.Context, in *ListenProofsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ListenProofsResponse], error) ⋮---- func (c *symbioticAPIServiceClient) ListenValidatorSet(ctx context.Context, in *ListenValidatorSetRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ListenValidatorSetResponse], error) ⋮---- // SymbioticAPIServiceServer is the server API for SymbioticAPIService service. // All implementations must embed UnimplementedSymbioticAPIServiceServer // for forward compatibility. ⋮---- type SymbioticAPIServiceServer interface { // Sign a message SignMessage(context.Context, *SignMessageRequest) (*SignMessageResponse, error) // Get aggregation proof GetAggregationProof(context.Context, *GetAggregationProofRequest) (*GetAggregationProofResponse, error) // Get aggregation proofs by epoch GetAggregationProofsByEpoch(context.Context, *GetAggregationProofsByEpochRequest) (*GetAggregationProofsByEpochResponse, error) // Get current epoch GetCurrentEpoch(context.Context, *GetCurrentEpochRequest) (*GetCurrentEpochResponse, error) // Get signature by request id GetSignatures(context.Context, *GetSignaturesRequest) (*GetSignaturesResponse, error) // Get signature by epoch GetSignaturesByEpoch(context.Context, *GetSignaturesByEpochRequest) (*GetSignaturesByEpochResponse, error) // Get all signature request IDs by epoch GetSignatureRequestIDsByEpoch(context.Context, *GetSignatureRequestIDsByEpochRequest) (*GetSignatureRequestIDsByEpochResponse, error) // Get all signature requests by epoch GetSignatureRequestsByEpoch(context.Context, *GetSignatureRequestsByEpochRequest) (*GetSignatureRequestsByEpochResponse, error) // Get signature request by request id GetSignatureRequest(context.Context, *GetSignatureRequestRequest) (*GetSignatureRequestResponse, error) // Get aggregation status, can be sent only to aggregator nodes GetAggregationStatus(context.Context, *GetAggregationStatusRequest) (*GetAggregationStatusResponse, error) // Get current validator set GetValidatorSet(context.Context, *GetValidatorSetRequest) (*GetValidatorSetResponse, error) // Get validator by address GetValidatorByAddress(context.Context, *GetValidatorByAddressRequest) (*GetValidatorByAddressResponse, error) // Get validator by key GetValidatorByKey(context.Context, *GetValidatorByKeyRequest) (*GetValidatorByKeyResponse, error) // Get local validator GetLocalValidator(context.Context, *GetLocalValidatorRequest) (*GetLocalValidatorResponse, error) // Get validator set header GetValidatorSetHeader(context.Context, *GetValidatorSetHeaderRequest) (*GetValidatorSetHeaderResponse, error) // Get last committed epoch for a specific settlement chain GetLastCommitted(context.Context, *GetLastCommittedRequest) (*GetLastCommittedResponse, error) // Get last committed epochs for all settlement chains GetLastAllCommitted(context.Context, *GetLastAllCommittedRequest) (*GetLastAllCommittedResponse, error) // Get validator set metadata like extra data and request id to fetch aggregation and signature requests GetValidatorSetMetadata(context.Context, *GetValidatorSetMetadataRequest) (*GetValidatorSetMetadataResponse, error) // Stream signatures in real-time. If start_epoch is provided, sends historical data first ListenSignatures(*ListenSignaturesRequest, grpc.ServerStreamingServer[ListenSignaturesResponse]) error // Stream aggregation proofs in real-time. If start_epoch is provided, sends historical data first ListenProofs(*ListenProofsRequest, grpc.ServerStreamingServer[ListenProofsResponse]) error // Stream validator set changes in real-time. If start_epoch is provided, sends historical data first ListenValidatorSet(*ListenValidatorSetRequest, grpc.ServerStreamingServer[ListenValidatorSetResponse]) error mustEmbedUnimplementedSymbioticAPIServiceServer() } ⋮---- // UnimplementedSymbioticAPIServiceServer must be embedded to have // forward compatible implementations. ⋮---- // NOTE: this should be embedded by value instead of pointer to avoid a nil // pointer dereference when methods are called. type UnimplementedSymbioticAPIServiceServer struct{} ⋮---- func (UnimplementedSymbioticAPIServiceServer) mustEmbedUnimplementedSymbioticAPIServiceServer() func (UnimplementedSymbioticAPIServiceServer) testEmbeddedByValue() ⋮---- // UnsafeSymbioticAPIServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to SymbioticAPIServiceServer will // result in compilation errors. type UnsafeSymbioticAPIServiceServer interface { mustEmbedUnimplementedSymbioticAPIServiceServer() } ⋮---- func RegisterSymbioticAPIServiceServer(s grpc.ServiceRegistrar, srv SymbioticAPIServiceServer) ⋮---- // If the following call pancis, it indicates UnimplementedSymbioticAPIServiceServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. ⋮---- func _SymbioticAPIService_SignMessage_Handler(srv interface ⋮---- func _SymbioticAPIService_GetAggregationProof_Handler(srv interface ⋮---- func _SymbioticAPIService_GetAggregationProofsByEpoch_Handler(srv interface ⋮---- func _SymbioticAPIService_GetCurrentEpoch_Handler(srv interface ⋮---- func _SymbioticAPIService_GetSignatures_Handler(srv interface ⋮---- func _SymbioticAPIService_GetSignaturesByEpoch_Handler(srv interface ⋮---- func _SymbioticAPIService_GetSignatureRequestIDsByEpoch_Handler(srv interface ⋮---- func _SymbioticAPIService_GetSignatureRequestsByEpoch_Handler(srv interface ⋮---- func _SymbioticAPIService_GetSignatureRequest_Handler(srv interface ⋮---- func _SymbioticAPIService_GetAggregationStatus_Handler(srv interface ⋮---- func _SymbioticAPIService_GetValidatorSet_Handler(srv interface ⋮---- func _SymbioticAPIService_GetValidatorByAddress_Handler(srv interface ⋮---- func _SymbioticAPIService_GetValidatorByKey_Handler(srv interface ⋮---- func _SymbioticAPIService_GetLocalValidator_Handler(srv interface ⋮---- func _SymbioticAPIService_GetValidatorSetHeader_Handler(srv interface ⋮---- func _SymbioticAPIService_GetLastCommitted_Handler(srv interface ⋮---- func _SymbioticAPIService_GetLastAllCommitted_Handler(srv interface ⋮---- func _SymbioticAPIService_GetValidatorSetMetadata_Handler(srv interface ⋮---- func _SymbioticAPIService_ListenSignatures_Handler(srv interface ⋮---- func _SymbioticAPIService_ListenProofs_Handler(srv interface ⋮---- func _SymbioticAPIService_ListenValidatorSet_Handler(srv interface ⋮---- // SymbioticAPIService_ServiceDesc is the grpc.ServiceDesc for SymbioticAPIService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var SymbioticAPIService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "api.proto.v1.SymbioticAPIService", HandlerType: (*SymbioticAPIServiceServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "SignMessage", Handler: _SymbioticAPIService_SignMessage_Handler, }, { MethodName: "GetAggregationProof", Handler: _SymbioticAPIService_GetAggregationProof_Handler, }, { MethodName: "GetAggregationProofsByEpoch", Handler: _SymbioticAPIService_GetAggregationProofsByEpoch_Handler, }, { MethodName: "GetCurrentEpoch", Handler: _SymbioticAPIService_GetCurrentEpoch_Handler, }, { MethodName: "GetSignatures", Handler: _SymbioticAPIService_GetSignatures_Handler, }, { MethodName: "GetSignaturesByEpoch", Handler: _SymbioticAPIService_GetSignaturesByEpoch_Handler, }, { MethodName: "GetSignatureRequestIDsByEpoch", Handler: _SymbioticAPIService_GetSignatureRequestIDsByEpoch_Handler, }, { MethodName: "GetSignatureRequestsByEpoch", Handler: _SymbioticAPIService_GetSignatureRequestsByEpoch_Handler, }, { MethodName: "GetSignatureRequest", Handler: _SymbioticAPIService_GetSignatureRequest_Handler, }, { MethodName: "GetAggregationStatus", Handler: _SymbioticAPIService_GetAggregationStatus_Handler, }, { MethodName: "GetValidatorSet", Handler: _SymbioticAPIService_GetValidatorSet_Handler, }, { MethodName: "GetValidatorByAddress", Handler: _SymbioticAPIService_GetValidatorByAddress_Handler, }, { MethodName: "GetValidatorByKey", Handler: _SymbioticAPIService_GetValidatorByKey_Handler, }, { MethodName: "GetLocalValidator", Handler: _SymbioticAPIService_GetLocalValidator_Handler, }, { MethodName: "GetValidatorSetHeader", Handler: _SymbioticAPIService_GetValidatorSetHeader_Handler, }, { MethodName: "GetLastCommitted", Handler: _SymbioticAPIService_GetLastCommitted_Handler, }, { MethodName: "GetLastAllCommitted", Handler: _SymbioticAPIService_GetLastAllCommitted_Handler, }, { MethodName: "GetValidatorSetMetadata", Handler: _SymbioticAPIService_GetValidatorSetMetadata_Handler, }, }, Streams: []grpc.StreamDesc{ { StreamName: "ListenSignatures", Handler: _SymbioticAPIService_ListenSignatures_Handler, ServerStreams: true, }, { StreamName: "ListenProofs", Handler: _SymbioticAPIService_ListenProofs_Handler, ServerStreams: true, }, { StreamName: "ListenValidatorSet", Handler: _SymbioticAPIService_ListenValidatorSet_Handler, ServerStreams: true, }, }, Metadata: "v1/api.proto", } ```` ## File: internal/gen/api/v1/api.pb.go ````go // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.6 // protoc (unknown) // source: v1/api.proto ⋮---- package v1 ⋮---- import ( _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" unsafe "unsafe" ) ⋮---- _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" unsafe "unsafe" ⋮---- const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) ⋮---- // Verify that this generated code is sufficiently up-to-date. ⋮---- // Verify that runtime/protoimpl is sufficiently up-to-date. ⋮---- // Validator set status enumeration type ValidatorSetStatus int32 ⋮---- const ( // Default/unknown status ValidatorSetStatus_VALIDATOR_SET_STATUS_UNSPECIFIED ValidatorSetStatus = 0 // Derived status ValidatorSetStatus_VALIDATOR_SET_STATUS_DERIVED ValidatorSetStatus = 1 // Aggregated status ValidatorSetStatus_VALIDATOR_SET_STATUS_AGGREGATED ValidatorSetStatus = 2 // Committed status ValidatorSetStatus_VALIDATOR_SET_STATUS_COMMITTED ValidatorSetStatus = 3 // Missed status ValidatorSetStatus_VALIDATOR_SET_STATUS_MISSED ValidatorSetStatus = 4 ) ⋮---- // Default/unknown status ⋮---- // Derived status ⋮---- // Aggregated status ⋮---- // Committed status ⋮---- // Missed status ⋮---- // Enum value maps for ValidatorSetStatus. var ( ValidatorSetStatus_name = map[int32]string{ 0: "VALIDATOR_SET_STATUS_UNSPECIFIED", 1: "VALIDATOR_SET_STATUS_DERIVED", 2: "VALIDATOR_SET_STATUS_AGGREGATED", 3: "VALIDATOR_SET_STATUS_COMMITTED", 4: "VALIDATOR_SET_STATUS_MISSED", } ValidatorSetStatus_value = map[string]int32{ "VALIDATOR_SET_STATUS_UNSPECIFIED": 0, "VALIDATOR_SET_STATUS_DERIVED": 1, "VALIDATOR_SET_STATUS_AGGREGATED": 2, "VALIDATOR_SET_STATUS_COMMITTED": 3, "VALIDATOR_SET_STATUS_MISSED": 4, } ) ⋮---- func (x ValidatorSetStatus) Enum() *ValidatorSetStatus ⋮---- func (x ValidatorSetStatus) String() string ⋮---- func (ValidatorSetStatus) Descriptor() protoreflect.EnumDescriptor ⋮---- func (ValidatorSetStatus) Type() protoreflect.EnumType ⋮---- func (x ValidatorSetStatus) Number() protoreflect.EnumNumber ⋮---- // Deprecated: Use ValidatorSetStatus.Descriptor instead. func (ValidatorSetStatus) EnumDescriptor() ([]byte, []int) ⋮---- // Signing process status enumeration type SigningStatus int32 ⋮---- const ( // Default/unknown status SigningStatus_SIGNING_STATUS_UNSPECIFIED SigningStatus = 0 // Request has been created and is waiting for signatures SigningStatus_SIGNING_STATUS_PENDING SigningStatus = 1 // Signing process completed successfully with proof SigningStatus_SIGNING_STATUS_COMPLETED SigningStatus = 2 // Signing process failed SigningStatus_SIGNING_STATUS_FAILED SigningStatus = 3 // Signing request timed out SigningStatus_SIGNING_STATUS_TIMEOUT SigningStatus = 4 ) ⋮---- // Request has been created and is waiting for signatures ⋮---- // Signing process completed successfully with proof ⋮---- // Signing process failed ⋮---- // Signing request timed out ⋮---- // Enum value maps for SigningStatus. var ( SigningStatus_name = map[int32]string{ 0: "SIGNING_STATUS_UNSPECIFIED", 1: "SIGNING_STATUS_PENDING", 2: "SIGNING_STATUS_COMPLETED", 3: "SIGNING_STATUS_FAILED", 4: "SIGNING_STATUS_TIMEOUT", } SigningStatus_value = map[string]int32{ "SIGNING_STATUS_UNSPECIFIED": 0, "SIGNING_STATUS_PENDING": 1, "SIGNING_STATUS_COMPLETED": 2, "SIGNING_STATUS_FAILED": 3, "SIGNING_STATUS_TIMEOUT": 4, } ) ⋮---- // Deprecated: Use SigningStatus.Descriptor instead. ⋮---- // Error code enumeration type ErrorCode int32 ⋮---- const ( // Default/unknown error ErrorCode_ERROR_CODE_UNSPECIFIED ErrorCode = 0 // No data found ErrorCode_ERROR_CODE_NO_DATA ErrorCode = 1 // Internal server error ErrorCode_ERROR_CODE_INTERNAL ErrorCode = 2 // Not an aggregator node ErrorCode_ERROR_CODE_NOT_AGGREGATOR ErrorCode = 3 ) ⋮---- // Default/unknown error ⋮---- // No data found ⋮---- // Internal server error ⋮---- // Not an aggregator node ⋮---- // Enum value maps for ErrorCode. var ( ErrorCode_name = map[int32]string{ 0: "ERROR_CODE_UNSPECIFIED", 1: "ERROR_CODE_NO_DATA", 2: "ERROR_CODE_INTERNAL", 3: "ERROR_CODE_NOT_AGGREGATOR", } ErrorCode_value = map[string]int32{ "ERROR_CODE_UNSPECIFIED": 0, "ERROR_CODE_NO_DATA": 1, "ERROR_CODE_INTERNAL": 2, "ERROR_CODE_NOT_AGGREGATOR": 3, } ) ⋮---- // Deprecated: Use ErrorCode.Descriptor instead. ⋮---- // Request message for signing a message type SignMessageRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Key tag identifier (0-127) KeyTag uint32 `protobuf:"varint,1,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` // Message to be signed Message []byte `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // Required epoch (optional, if not provided latest committed epoch will be used) RequiredEpoch *uint64 `protobuf:"varint,3,opt,name=required_epoch,json=requiredEpoch,proto3,oneof" json:"required_epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Key tag identifier (0-127) ⋮---- // Message to be signed ⋮---- // Required epoch (optional, if not provided latest committed epoch will be used) ⋮---- func (x *SignMessageRequest) Reset() ⋮---- func (*SignMessageRequest) ProtoMessage() ⋮---- func (x *SignMessageRequest) ProtoReflect() protoreflect.Message ⋮---- // Deprecated: Use SignMessageRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *SignMessageRequest) GetKeyTag() uint32 ⋮---- func (x *SignMessageRequest) GetMessage() []byte ⋮---- func (x *SignMessageRequest) GetRequiredEpoch() uint64 ⋮---- // Response message for sign message request type SignMessageResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Hash of the signature request RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` // Epoch number Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Hash of the signature request ⋮---- // Epoch number ⋮---- // Deprecated: Use SignMessageResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *SignMessageResponse) GetRequestId() string ⋮---- func (x *SignMessageResponse) GetEpoch() uint64 ⋮---- // Request message for listening to signatures stream type ListenSignaturesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Optional: start epoch. If provided, stream will first send all historical signatures starting from this epoch, then continue with real-time updates // If not provided, only signatures generated after stream creation will be sent StartEpoch *uint64 `protobuf:"varint,1,opt,name=start_epoch,json=startEpoch,proto3,oneof" json:"start_epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Optional: start epoch. If provided, stream will first send all historical signatures starting from this epoch, then continue with real-time updates // If not provided, only signatures generated after stream creation will be sent ⋮---- // Deprecated: Use ListenSignaturesRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *ListenSignaturesRequest) GetStartEpoch() uint64 ⋮---- // Response message for signatures stream type ListenSignaturesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Id of the signature request RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` // Epoch number Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` // Signature data Signature *Signature `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Id of the signature request ⋮---- // Signature data ⋮---- // Deprecated: Use ListenSignaturesResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *ListenSignaturesResponse) GetSignature() *Signature ⋮---- // Request message for listening to aggregation proofs stream type ListenProofsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Optional: start epoch. If provided, stream will first send all historical proofs starting from this epoch, then continue with real-time updates // If not provided, only proofs generated after stream creation will be sent StartEpoch *uint64 `protobuf:"varint,1,opt,name=start_epoch,json=startEpoch,proto3,oneof" json:"start_epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Optional: start epoch. If provided, stream will first send all historical proofs starting from this epoch, then continue with real-time updates // If not provided, only proofs generated after stream creation will be sent ⋮---- // Deprecated: Use ListenProofsRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for aggregation proofs stream type ListenProofsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Id of the request RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` // Epoch number Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` // Final aggregation proof AggregationProof *AggregationProof `protobuf:"bytes,3,opt,name=aggregation_proof,json=aggregationProof,proto3" json:"aggregation_proof,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Id of the request ⋮---- // Final aggregation proof ⋮---- // Deprecated: Use ListenProofsResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *ListenProofsResponse) GetAggregationProof() *AggregationProof ⋮---- // Request message for listening to validator set changes stream type ListenValidatorSetRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Optional: start epoch. If provided, stream will first send all historical validator sets starting from this epoch, then continue with real-time updates // If not provided, only validator sets generated after stream creation will be sent StartEpoch *uint64 `protobuf:"varint,1,opt,name=start_epoch,json=startEpoch,proto3,oneof" json:"start_epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Optional: start epoch. If provided, stream will first send all historical validator sets starting from this epoch, then continue with real-time updates // If not provided, only validator sets generated after stream creation will be sent ⋮---- // Deprecated: Use ListenValidatorSetRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for validator set changes stream type ListenValidatorSetResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // The validator set ValidatorSet *ValidatorSet `protobuf:"bytes,1,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // The validator set ⋮---- // Deprecated: Use ListenValidatorSetResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *ListenValidatorSetResponse) GetValidatorSet() *ValidatorSet ⋮---- // Request message for getting aggregation proof type GetAggregationProofRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetAggregationProofRequest.ProtoReflect.Descriptor instead. ⋮---- type GetAggregationProofsByEpochRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetAggregationProofsByEpochRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting current epoch type GetCurrentEpochRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetCurrentEpochRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting signatures type GetSignaturesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetSignaturesRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting signatures by epoch type GetSignaturesByEpochRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetSignaturesByEpochRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting signatures type GetSignaturesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // List of signatures Signatures []*Signature `protobuf:"bytes,1,rep,name=signatures,proto3" json:"signatures,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // List of signatures ⋮---- // Deprecated: Use GetSignaturesResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetSignaturesResponse) GetSignatures() []*Signature ⋮---- // Response message for getting signatures by epoch type GetSignaturesByEpochResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // List of signatures Signatures []*Signature `protobuf:"bytes,1,rep,name=signatures,proto3" json:"signatures,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetSignaturesByEpochResponse.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting all signature request IDs by epoch type GetSignatureRequestIDsByEpochRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetSignatureRequestIDsByEpochRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting all signature request IDs by epoch type GetSignatureRequestIDsByEpochResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // List of all signature request IDs for the epoch RequestIds []string `protobuf:"bytes,1,rep,name=request_ids,json=requestIds,proto3" json:"request_ids,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // List of all signature request IDs for the epoch ⋮---- // Deprecated: Use GetSignatureRequestIDsByEpochResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetSignatureRequestIDsByEpochResponse) GetRequestIds() []string ⋮---- // Request message for getting all signature requests by epoch type GetSignatureRequestsByEpochRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetSignatureRequestsByEpochRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting all signature requests by epoch type GetSignatureRequestsByEpochResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // List of all signature requests for the epoch SignatureRequests []*SignatureRequest `protobuf:"bytes,1,rep,name=signature_requests,json=signatureRequests,proto3" json:"signature_requests,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // List of all signature requests for the epoch ⋮---- // Deprecated: Use GetSignatureRequestsByEpochResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetSignatureRequestsByEpochResponse) GetSignatureRequests() []*SignatureRequest ⋮---- // Request message for getting signature request type GetSignatureRequestRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetSignatureRequestRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting aggregation status type GetAggregationStatusRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetAggregationStatusRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting validator set type GetValidatorSetRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number (optional, if not provided current epoch will be used) Epoch *uint64 `protobuf:"varint,1,opt,name=epoch,proto3,oneof" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Epoch number (optional, if not provided current epoch will be used) ⋮---- // Deprecated: Use GetValidatorSetRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting validator by address type GetValidatorByAddressRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number (optional, if not provided current epoch will be used) Epoch *uint64 `protobuf:"varint,1,opt,name=epoch,proto3,oneof" json:"epoch,omitempty"` // Validator address (required) Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Validator address (required) ⋮---- // Deprecated: Use GetValidatorByAddressRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *GetValidatorByAddressRequest) GetAddress() string ⋮---- // Request message for getting validator by key type GetValidatorByKeyRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number (optional, if not provided current epoch will be used) Epoch *uint64 `protobuf:"varint,1,opt,name=epoch,proto3,oneof" json:"epoch,omitempty"` // Validator key tag (required) KeyTag uint32 `protobuf:"varint,2,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` // Validator on chain (public) key (required) OnChainKey []byte `protobuf:"bytes,3,opt,name=on_chain_key,json=onChainKey,proto3" json:"on_chain_key,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Validator key tag (required) ⋮---- // Validator on chain (public) key (required) ⋮---- // Deprecated: Use GetValidatorByKeyRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *GetValidatorByKeyRequest) GetOnChainKey() []byte ⋮---- // Request message for getting local validator type GetLocalValidatorRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number (optional, if not provided current epoch will be used) Epoch *uint64 `protobuf:"varint,1,opt,name=epoch,proto3,oneof" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetLocalValidatorRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting validator set header type GetValidatorSetHeaderRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number (optional, if not provided current epoch will be used) Epoch *uint64 `protobuf:"varint,1,opt,name=epoch,proto3,oneof" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetValidatorSetHeaderRequest.ProtoReflect.Descriptor instead. ⋮---- // Request message for getting validator set metadata type GetValidatorSetMetadataRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number (optional, if not provided current epoch will be used) Epoch *uint64 `protobuf:"varint,1,opt,name=epoch,proto3,oneof" json:"epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetValidatorSetMetadataRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting current epoch type GetCurrentEpochResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Epoch number Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Epoch start time StartTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Epoch start time ⋮---- // Deprecated: Use GetCurrentEpochResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetCurrentEpochResponse) GetStartTime() *timestamppb.Timestamp ⋮---- // SignatureRequest represents a signature request type SignatureRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Request ID RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` // Key tag identifier (0-127) KeyTag uint32 `protobuf:"varint,2,opt,name=key_tag,json=keyTag,proto3" json:"key_tag,omitempty"` // Message to be signed Message []byte `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` // Required epoch RequiredEpoch uint64 `protobuf:"varint,4,opt,name=required_epoch,json=requiredEpoch,proto3" json:"required_epoch,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Request ID ⋮---- // Required epoch ⋮---- // Deprecated: Use SignatureRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting signature request type GetSignatureRequestResponse struct { state protoimpl.MessageState `protogen:"open.v1"` SignatureRequest *SignatureRequest `protobuf:"bytes,1,opt,name=signature_request,json=signatureRequest,proto3" json:"signature_request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetSignatureRequestResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetSignatureRequestResponse) GetSignatureRequest() *SignatureRequest ⋮---- // Response message for getting aggregation proof type GetAggregationProofResponse struct { state protoimpl.MessageState `protogen:"open.v1"` AggregationProof *AggregationProof `protobuf:"bytes,1,opt,name=aggregation_proof,json=aggregationProof,proto3" json:"aggregation_proof,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetAggregationProofResponse.ProtoReflect.Descriptor instead. ⋮---- type GetAggregationProofsByEpochResponse struct { state protoimpl.MessageState `protogen:"open.v1"` AggregationProofs []*AggregationProof `protobuf:"bytes,1,rep,name=aggregation_proofs,json=aggregationProofs,proto3" json:"aggregation_proofs,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetAggregationProofsByEpochResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetAggregationProofsByEpochResponse) GetAggregationProofs() []*AggregationProof ⋮---- type AggregationProof struct { state protoimpl.MessageState `protogen:"open.v1"` // Message hash MessageHash []byte `protobuf:"bytes,2,opt,name=message_hash,json=messageHash,proto3" json:"message_hash,omitempty"` // Proof data Proof []byte `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"` // Request ID RequestId string `protobuf:"bytes,4,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Message hash ⋮---- // Proof data ⋮---- // Deprecated: Use AggregationProof.ProtoReflect.Descriptor instead. ⋮---- func (x *AggregationProof) GetMessageHash() []byte ⋮---- func (x *AggregationProof) GetProof() []byte ⋮---- // Response message for getting aggregation status type GetAggregationStatusResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Current voting power of the aggregator (big integer as string) CurrentVotingPower string `protobuf:"bytes,1,opt,name=current_voting_power,json=currentVotingPower,proto3" json:"current_voting_power,omitempty"` // List of operator addresses that signed the request SignerOperators []string `protobuf:"bytes,2,rep,name=signer_operators,json=signerOperators,proto3" json:"signer_operators,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Current voting power of the aggregator (big integer as string) ⋮---- // List of operator addresses that signed the request ⋮---- // Deprecated: Use GetAggregationStatusResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetAggregationStatusResponse) GetCurrentVotingPower() string ⋮---- func (x *GetAggregationStatusResponse) GetSignerOperators() []string ⋮---- // Digital signature type Signature struct { state protoimpl.MessageState `protogen:"open.v1"` // Signature data Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` // Message hash MessageHash []byte `protobuf:"bytes,2,opt,name=message_hash,json=messageHash,proto3" json:"message_hash,omitempty"` // Public key PublicKey []byte `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Request ID RequestId string `protobuf:"bytes,4,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Public key ⋮---- // Deprecated: Use Signature.ProtoReflect.Descriptor instead. ⋮---- func (x *Signature) GetPublicKey() []byte ⋮---- // Response message for getting validator set type GetValidatorSetResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // The validator set ValidatorSet *ValidatorSet `protobuf:"bytes,1,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetValidatorSetResponse.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting validator by address type GetValidatorByAddressResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // The validator Validator *Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // The validator ⋮---- // Deprecated: Use GetValidatorByAddressResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetValidatorByAddressResponse) GetValidator() *Validator ⋮---- // Response message for getting validator by key type GetValidatorByKeyResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // The validator Validator *Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetValidatorByKeyResponse.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting local validator type GetLocalValidatorResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // The validator Validator *Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetLocalValidatorResponse.ProtoReflect.Descriptor instead. ⋮---- type ExtraData struct { state protoimpl.MessageState `protogen:"open.v1"` Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use ExtraData.ProtoReflect.Descriptor instead. ⋮---- func (x *ExtraData) GetKey() []byte ⋮---- func (x *ExtraData) GetValue() []byte ⋮---- // Response message for getting validator set header type GetValidatorSetMetadataResponse struct { state protoimpl.MessageState `protogen:"open.v1"` ExtraData []*ExtraData `protobuf:"bytes,1,rep,name=extra_data,json=extraData,proto3" json:"extra_data,omitempty"` CommitmentData []byte `protobuf:"bytes,2,opt,name=commitment_data,json=commitmentData,proto3" json:"commitment_data,omitempty"` RequestId string `protobuf:"bytes,3,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetValidatorSetMetadataResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetValidatorSetMetadataResponse) GetExtraData() []*ExtraData ⋮---- func (x *GetValidatorSetMetadataResponse) GetCommitmentData() []byte ⋮---- type GetValidatorSetHeaderResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Version of the validator set Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Key tag required to commit next validator set RequiredKeyTag uint32 `protobuf:"varint,2,opt,name=required_key_tag,json=requiredKeyTag,proto3" json:"required_key_tag,omitempty"` // Validator set epoch Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` // Epoch capture timestamp CaptureTimestamp *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=capture_timestamp,json=captureTimestamp,proto3" json:"capture_timestamp,omitempty"` // Quorum threshold (big integer as string) QuorumThreshold string `protobuf:"bytes,5,opt,name=quorum_threshold,json=quorumThreshold,proto3" json:"quorum_threshold,omitempty"` // Total voting power (big integer as string) TotalVotingPower string `protobuf:"bytes,6,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` // Validators SSZ Merkle root (hex string) ValidatorsSszMroot string `protobuf:"bytes,7,opt,name=validators_ssz_mroot,json=validatorsSszMroot,proto3" json:"validators_ssz_mroot,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Version of the validator set ⋮---- // Key tag required to commit next validator set ⋮---- // Validator set epoch ⋮---- // Epoch capture timestamp ⋮---- // Quorum threshold (big integer as string) ⋮---- // Total voting power (big integer as string) ⋮---- // Validators SSZ Merkle root (hex string) ⋮---- // Deprecated: Use GetValidatorSetHeaderResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetValidatorSetHeaderResponse) GetVersion() uint32 ⋮---- func (x *GetValidatorSetHeaderResponse) GetRequiredKeyTag() uint32 ⋮---- func (x *GetValidatorSetHeaderResponse) GetCaptureTimestamp() *timestamppb.Timestamp ⋮---- func (x *GetValidatorSetHeaderResponse) GetQuorumThreshold() string ⋮---- func (x *GetValidatorSetHeaderResponse) GetTotalVotingPower() string ⋮---- func (x *GetValidatorSetHeaderResponse) GetValidatorsSszMroot() string ⋮---- // Validator information type Validator struct { state protoimpl.MessageState `protogen:"open.v1"` // Operator address (hex string) Operator string `protobuf:"bytes,1,opt,name=operator,proto3" json:"operator,omitempty"` // Voting power of the validator (big integer as string) VotingPower string `protobuf:"bytes,2,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` // Indicates if the validator is active IsActive bool `protobuf:"varint,3,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"` // List of cryptographic keys Keys []*Key `protobuf:"bytes,4,rep,name=keys,proto3" json:"keys,omitempty"` // List of validator vaults Vaults []*ValidatorVault `protobuf:"bytes,5,rep,name=vaults,proto3" json:"vaults,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Operator address (hex string) ⋮---- // Voting power of the validator (big integer as string) ⋮---- // Indicates if the validator is active ⋮---- // List of cryptographic keys ⋮---- // List of validator vaults ⋮---- // Deprecated: Use Validator.ProtoReflect.Descriptor instead. ⋮---- func (x *Validator) GetOperator() string ⋮---- func (x *Validator) GetVotingPower() string ⋮---- func (x *Validator) GetIsActive() bool ⋮---- func (x *Validator) GetKeys() []*Key ⋮---- func (x *Validator) GetVaults() []*ValidatorVault ⋮---- // Cryptographic key type Key struct { state protoimpl.MessageState `protogen:"open.v1"` // Key tag identifier (0-127) Tag uint32 `protobuf:"varint,1,opt,name=tag,proto3" json:"tag,omitempty"` // Key payload Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Key payload ⋮---- // Deprecated: Use Key.ProtoReflect.Descriptor instead. ⋮---- func (x *Key) GetTag() uint32 ⋮---- func (x *Key) GetPayload() []byte ⋮---- // Validator vault information type ValidatorVault struct { state protoimpl.MessageState `protogen:"open.v1"` // Chain identifier ChainId uint64 `protobuf:"varint,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` // Vault address Vault string `protobuf:"bytes,2,opt,name=vault,proto3" json:"vault,omitempty"` // Voting power for this vault (big integer as string) VotingPower string `protobuf:"bytes,3,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Chain identifier ⋮---- // Vault address ⋮---- // Voting power for this vault (big integer as string) ⋮---- // Deprecated: Use ValidatorVault.ProtoReflect.Descriptor instead. ⋮---- func (x *ValidatorVault) GetChainId() uint64 ⋮---- func (x *ValidatorVault) GetVault() string ⋮---- // Request message for getting last committed epoch for a specific settlement chain type GetLastCommittedRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Settlement chain ID SettlementChainId uint64 `protobuf:"varint,1,opt,name=settlement_chain_id,json=settlementChainId,proto3" json:"settlement_chain_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Settlement chain ID ⋮---- // Deprecated: Use GetLastCommittedRequest.ProtoReflect.Descriptor instead. ⋮---- func (x *GetLastCommittedRequest) GetSettlementChainId() uint64 ⋮---- // Response message for getting last committed epoch type GetLastCommittedResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Settlement chain ID SettlementChainId uint64 `protobuf:"varint,1,opt,name=settlement_chain_id,json=settlementChainId,proto3" json:"settlement_chain_id,omitempty"` EpochInfo *ChainEpochInfo `protobuf:"bytes,2,opt,name=epoch_info,json=epochInfo,proto3" json:"epoch_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetLastCommittedResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetLastCommittedResponse) GetEpochInfo() *ChainEpochInfo ⋮---- // Request message for getting last committed epochs for all chains type GetLastAllCommittedRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Deprecated: Use GetLastAllCommittedRequest.ProtoReflect.Descriptor instead. ⋮---- // Response message for getting all last committed epochs type GetLastAllCommittedResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // List of settlement chains with their last committed epochs EpochInfos map[uint64]*ChainEpochInfo `protobuf:"bytes,1,rep,name=epoch_infos,json=epochInfos,proto3" json:"epoch_infos,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Suggested epoch info for signatures, it is the minimum commited epoch among all chains SuggestedEpochInfo *ChainEpochInfo `protobuf:"bytes,2,opt,name=suggested_epoch_info,json=suggestedEpochInfo,proto3" json:"suggested_epoch_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // List of settlement chains with their last committed epochs ⋮---- // Suggested epoch info for signatures, it is the minimum commited epoch among all chains ⋮---- // Deprecated: Use GetLastAllCommittedResponse.ProtoReflect.Descriptor instead. ⋮---- func (x *GetLastAllCommittedResponse) GetEpochInfos() map[uint64]*ChainEpochInfo ⋮---- func (x *GetLastAllCommittedResponse) GetSuggestedEpochInfo() *ChainEpochInfo ⋮---- // Settlement chain with its last committed epoch type ChainEpochInfo struct { state protoimpl.MessageState `protogen:"open.v1"` // Last committed epoch for this chain LastCommittedEpoch uint64 `protobuf:"varint,1,opt,name=last_committed_epoch,json=lastCommittedEpoch,proto3" json:"last_committed_epoch,omitempty"` // Epoch start time StartTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Last committed epoch for this chain ⋮---- // Deprecated: Use ChainEpochInfo.ProtoReflect.Descriptor instead. ⋮---- func (x *ChainEpochInfo) GetLastCommittedEpoch() uint64 ⋮---- type ValidatorSet struct { state protoimpl.MessageState `protogen:"open.v1"` // Version of the validator set Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Key tag required to commit next validator set RequiredKeyTag uint32 `protobuf:"varint,2,opt,name=required_key_tag,json=requiredKeyTag,proto3" json:"required_key_tag,omitempty"` // Validator set epoch Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` // Epoch capture timestamp CaptureTimestamp *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=capture_timestamp,json=captureTimestamp,proto3" json:"capture_timestamp,omitempty"` // Quorum threshold (big integer as string) QuorumThreshold string `protobuf:"bytes,5,opt,name=quorum_threshold,json=quorumThreshold,proto3" json:"quorum_threshold,omitempty"` // Status of validator set header Status ValidatorSetStatus `protobuf:"varint,6,opt,name=status,proto3,enum=api.proto.v1.ValidatorSetStatus" json:"status,omitempty"` // List of validators Validators []*Validator `protobuf:"bytes,7,rep,name=validators,proto3" json:"validators,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ⋮---- // Status of validator set header ⋮---- // List of validators ⋮---- // Deprecated: Use ValidatorSet.ProtoReflect.Descriptor instead. ⋮---- func (x *ValidatorSet) GetStatus() ValidatorSetStatus ⋮---- func (x *ValidatorSet) GetValidators() []*Validator ⋮---- var File_v1_api_proto protoreflect.FileDescriptor ⋮---- const file_v1_api_proto_rawDesc = "" + "\n" + "\fv1/api.proto\x12\fapi.proto.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1cgoogle/api/annotations.proto\"\x86\x01\n" + "\x12SignMessageRequest\x12\x17\n" + "\akey_tag\x18\x01 \x01(\rR\x06keyTag\x12\x18\n" + "\amessage\x18\x02 \x01(\fR\amessage\x12*\n" + "\x0erequired_epoch\x18\x03 \x01(\x04H\x00R\rrequiredEpoch\x88\x01\x01B\x11\n" + "\x0f_required_epoch\"J\n" + "\x13SignMessageResponse\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x14\n" + "\x05epoch\x18\x02 \x01(\x04R\x05epoch\"O\n" + "\x17ListenSignaturesRequest\x12$\n" + "\vstart_epoch\x18\x01 \x01(\x04H\x00R\n" + "startEpoch\x88\x01\x01B\x0e\n" + "\f_start_epoch\"\x86\x01\n" + "\x18ListenSignaturesResponse\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x14\n" + "\x05epoch\x18\x02 \x01(\x04R\x05epoch\x125\n" + "\tsignature\x18\x03 \x01(\v2\x17.api.proto.v1.SignatureR\tsignature\"K\n" + "\x13ListenProofsRequest\x12$\n" + "\vstart_epoch\x18\x01 \x01(\x04H\x00R\n" + "startEpoch\x88\x01\x01B\x0e\n" + "\f_start_epoch\"\x98\x01\n" + "\x14ListenProofsResponse\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x14\n" + "\x05epoch\x18\x02 \x01(\x04R\x05epoch\x12K\n" + "\x11aggregation_proof\x18\x03 \x01(\v2\x1e.api.proto.v1.AggregationProofR\x10aggregationProof\"Q\n" + "\x19ListenValidatorSetRequest\x12$\n" + "\vstart_epoch\x18\x01 \x01(\x04H\x00R\n" + "startEpoch\x88\x01\x01B\x0e\n" + "\f_start_epoch\"]\n" + "\x1aListenValidatorSetResponse\x12?\n" + "\rvalidator_set\x18\x01 \x01(\v2\x1a.api.proto.v1.ValidatorSetR\fvalidatorSet\";\n" + "\x1aGetAggregationProofRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\":\n" + "\"GetAggregationProofsByEpochRequest\x12\x14\n" + "\x05epoch\x18\x01 \x01(\x04R\x05epoch\"\x18\n" + "\x16GetCurrentEpochRequest\"5\n" + "\x14GetSignaturesRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\"3\n" + "\x1bGetSignaturesByEpochRequest\x12\x14\n" + "\x05epoch\x18\x01 \x01(\x04R\x05epoch\"P\n" + "\x15GetSignaturesResponse\x127\n" + "\n" + "signatures\x18\x01 \x03(\v2\x17.api.proto.v1.SignatureR\n" + "signatures\"W\n" + "\x1cGetSignaturesByEpochResponse\x127\n" + "\n" + "signatures\x18\x01 \x03(\v2\x17.api.proto.v1.SignatureR\n" + "signatures\"<\n" + "$GetSignatureRequestIDsByEpochRequest\x12\x14\n" + "\x05epoch\x18\x01 \x01(\x04R\x05epoch\"H\n" + "%GetSignatureRequestIDsByEpochResponse\x12\x1f\n" + "\vrequest_ids\x18\x01 \x03(\tR\n" + "requestIds\":\n" + "\"GetSignatureRequestsByEpochRequest\x12\x14\n" + "\x05epoch\x18\x01 \x01(\x04R\x05epoch\"t\n" + "#GetSignatureRequestsByEpochResponse\x12M\n" + "\x12signature_requests\x18\x01 \x03(\v2\x1e.api.proto.v1.SignatureRequestR\x11signatureRequests\";\n" + "\x1aGetSignatureRequestRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\"<\n" + "\x1bGetAggregationStatusRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\"=\n" + "\x16GetValidatorSetRequest\x12\x19\n" + "\x05epoch\x18\x01 \x01(\x04H\x00R\x05epoch\x88\x01\x01B\b\n" + "\x06_epoch\"]\n" + "\x1cGetValidatorByAddressRequest\x12\x19\n" + "\x05epoch\x18\x01 \x01(\x04H\x00R\x05epoch\x88\x01\x01\x12\x18\n" + "\aaddress\x18\x02 \x01(\tR\aaddressB\b\n" + "\x06_epoch\"z\n" + "\x18GetValidatorByKeyRequest\x12\x19\n" + "\x05epoch\x18\x01 \x01(\x04H\x00R\x05epoch\x88\x01\x01\x12\x17\n" + "\akey_tag\x18\x02 \x01(\rR\x06keyTag\x12 \n" + "\fon_chain_key\x18\x03 \x01(\fR\n" + "onChainKeyB\b\n" + "\x06_epoch\"?\n" + "\x18GetLocalValidatorRequest\x12\x19\n" + "\x05epoch\x18\x01 \x01(\x04H\x00R\x05epoch\x88\x01\x01B\b\n" + "\x06_epoch\"C\n" + "\x1cGetValidatorSetHeaderRequest\x12\x19\n" + "\x05epoch\x18\x01 \x01(\x04H\x00R\x05epoch\x88\x01\x01B\b\n" + "\x06_epoch\"E\n" + "\x1eGetValidatorSetMetadataRequest\x12\x19\n" + "\x05epoch\x18\x01 \x01(\x04H\x00R\x05epoch\x88\x01\x01B\b\n" + "\x06_epoch\"j\n" + "\x17GetCurrentEpochResponse\x12\x14\n" + "\x05epoch\x18\x01 \x01(\x04R\x05epoch\x129\n" + "\n" + "start_time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\tstartTime\"\x8b\x01\n" + "\x10SignatureRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x17\n" + "\akey_tag\x18\x02 \x01(\rR\x06keyTag\x12\x18\n" + "\amessage\x18\x03 \x01(\fR\amessage\x12%\n" + "\x0erequired_epoch\x18\x04 \x01(\x04R\rrequiredEpoch\"j\n" + "\x1bGetSignatureRequestResponse\x12K\n" + "\x11signature_request\x18\x01 \x01(\v2\x1e.api.proto.v1.SignatureRequestR\x10signatureRequest\"j\n" + "\x1bGetAggregationProofResponse\x12K\n" + "\x11aggregation_proof\x18\x01 \x01(\v2\x1e.api.proto.v1.AggregationProofR\x10aggregationProof\"t\n" + "#GetAggregationProofsByEpochResponse\x12M\n" + "\x12aggregation_proofs\x18\x01 \x03(\v2\x1e.api.proto.v1.AggregationProofR\x11aggregationProofs\"j\n" + "\x10AggregationProof\x12!\n" + "\fmessage_hash\x18\x02 \x01(\fR\vmessageHash\x12\x14\n" + "\x05proof\x18\x03 \x01(\fR\x05proof\x12\x1d\n" + "\n" + "request_id\x18\x04 \x01(\tR\trequestId\"{\n" + "\x1cGetAggregationStatusResponse\x120\n" + "\x14current_voting_power\x18\x01 \x01(\tR\x12currentVotingPower\x12)\n" + "\x10signer_operators\x18\x02 \x03(\tR\x0fsignerOperators\"\x8a\x01\n" + "\tSignature\x12\x1c\n" + "\tsignature\x18\x01 \x01(\fR\tsignature\x12!\n" + "\fmessage_hash\x18\x02 \x01(\fR\vmessageHash\x12\x1d\n" + "\n" + "public_key\x18\x03 \x01(\fR\tpublicKey\x12\x1d\n" + "\n" + "request_id\x18\x04 \x01(\tR\trequestId\"Z\n" + "\x17GetValidatorSetResponse\x12?\n" + "\rvalidator_set\x18\x01 \x01(\v2\x1a.api.proto.v1.ValidatorSetR\fvalidatorSet\"V\n" + "\x1dGetValidatorByAddressResponse\x125\n" + "\tvalidator\x18\x01 \x01(\v2\x17.api.proto.v1.ValidatorR\tvalidator\"R\n" + "\x19GetValidatorByKeyResponse\x125\n" + "\tvalidator\x18\x01 \x01(\v2\x17.api.proto.v1.ValidatorR\tvalidator\"R\n" + "\x19GetLocalValidatorResponse\x125\n" + "\tvalidator\x18\x01 \x01(\v2\x17.api.proto.v1.ValidatorR\tvalidator\"3\n" + "\tExtraData\x12\x10\n" + "\x03key\x18\x01 \x01(\fR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\fR\x05value\"\xa1\x01\n" + "\x1fGetValidatorSetMetadataResponse\x126\n" + "\n" + "extra_data\x18\x01 \x03(\v2\x17.api.proto.v1.ExtraDataR\textraData\x12'\n" + "\x0fcommitment_data\x18\x02 \x01(\fR\x0ecommitmentData\x12\x1d\n" + "\n" + "request_id\x18\x03 \x01(\tR\trequestId\"\xcd\x02\n" + "\x1dGetValidatorSetHeaderResponse\x12\x18\n" + "\aversion\x18\x01 \x01(\rR\aversion\x12(\n" + "\x10required_key_tag\x18\x02 \x01(\rR\x0erequiredKeyTag\x12\x14\n" + "\x05epoch\x18\x03 \x01(\x04R\x05epoch\x12G\n" + "\x11capture_timestamp\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\x10captureTimestamp\x12)\n" + "\x10quorum_threshold\x18\x05 \x01(\tR\x0fquorumThreshold\x12,\n" + "\x12total_voting_power\x18\x06 \x01(\tR\x10totalVotingPower\x120\n" + "\x14validators_ssz_mroot\x18\a \x01(\tR\x12validatorsSszMroot\"\xc4\x01\n" + "\tValidator\x12\x1a\n" + "\boperator\x18\x01 \x01(\tR\boperator\x12!\n" + "\fvoting_power\x18\x02 \x01(\tR\vvotingPower\x12\x1b\n" + "\tis_active\x18\x03 \x01(\bR\bisActive\x12%\n" + "\x04keys\x18\x04 \x03(\v2\x11.api.proto.v1.KeyR\x04keys\x124\n" + "\x06vaults\x18\x05 \x03(\v2\x1c.api.proto.v1.ValidatorVaultR\x06vaults\"1\n" + "\x03Key\x12\x10\n" + "\x03tag\x18\x01 \x01(\rR\x03tag\x12\x18\n" + "\apayload\x18\x02 \x01(\fR\apayload\"d\n" + "\x0eValidatorVault\x12\x19\n" + "\bchain_id\x18\x01 \x01(\x04R\achainId\x12\x14\n" + "\x05vault\x18\x02 \x01(\tR\x05vault\x12!\n" + "\fvoting_power\x18\x03 \x01(\tR\vvotingPower\"I\n" + "\x17GetLastCommittedRequest\x12.\n" + "\x13settlement_chain_id\x18\x01 \x01(\x04R\x11settlementChainId\"\x87\x01\n" + "\x18GetLastCommittedResponse\x12.\n" + "\x13settlement_chain_id\x18\x01 \x01(\x04R\x11settlementChainId\x12;\n" + "\n" + "epoch_info\x18\x02 \x01(\v2\x1c.api.proto.v1.ChainEpochInfoR\tepochInfo\"\x1c\n" + "\x1aGetLastAllCommittedRequest\"\xa6\x02\n" + "\x1bGetLastAllCommittedResponse\x12Z\n" + "\vepoch_infos\x18\x01 \x03(\v29.api.proto.v1.GetLastAllCommittedResponse.EpochInfosEntryR\n" + "epochInfos\x12N\n" + "\x14suggested_epoch_info\x18\x02 \x01(\v2\x1c.api.proto.v1.ChainEpochInfoR\x12suggestedEpochInfo\x1a[\n" + "\x0fEpochInfosEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\x04R\x03key\x122\n" + "\x05value\x18\x02 \x01(\v2\x1c.api.proto.v1.ChainEpochInfoR\x05value:\x028\x01\"}\n" + "\x0eChainEpochInfo\x120\n" + "\x14last_committed_epoch\x18\x01 \x01(\x04R\x12lastCommittedEpoch\x129\n" + "\n" + "start_time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\tstartTime\"\xcf\x02\n" + "\fValidatorSet\x12\x18\n" + "\aversion\x18\x01 \x01(\rR\aversion\x12(\n" + "\x10required_key_tag\x18\x02 \x01(\rR\x0erequiredKeyTag\x12\x14\n" + "\x05epoch\x18\x03 \x01(\x04R\x05epoch\x12G\n" + "\x11capture_timestamp\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\x10captureTimestamp\x12)\n" + "\x10quorum_threshold\x18\x05 \x01(\tR\x0fquorumThreshold\x128\n" + "\x06status\x18\x06 \x01(\x0e2 .api.proto.v1.ValidatorSetStatusR\x06status\x127\n" + "\n" + "validators\x18\a \x03(\v2\x17.api.proto.v1.ValidatorR\n" + "validators*\xc6\x01\n" + "\x12ValidatorSetStatus\x12$\n" + " VALIDATOR_SET_STATUS_UNSPECIFIED\x10\x00\x12 \n" + "\x1cVALIDATOR_SET_STATUS_DERIVED\x10\x01\x12#\n" + "\x1fVALIDATOR_SET_STATUS_AGGREGATED\x10\x02\x12\"\n" + "\x1eVALIDATOR_SET_STATUS_COMMITTED\x10\x03\x12\x1f\n" + "\x1bVALIDATOR_SET_STATUS_MISSED\x10\x04*\xa0\x01\n" + "\rSigningStatus\x12\x1e\n" + "\x1aSIGNING_STATUS_UNSPECIFIED\x10\x00\x12\x1a\n" + "\x16SIGNING_STATUS_PENDING\x10\x01\x12\x1c\n" + "\x18SIGNING_STATUS_COMPLETED\x10\x02\x12\x19\n" + "\x15SIGNING_STATUS_FAILED\x10\x03\x12\x1a\n" + "\x16SIGNING_STATUS_TIMEOUT\x10\x04*w\n" + "\tErrorCode\x12\x1a\n" + "\x16ERROR_CODE_UNSPECIFIED\x10\x00\x12\x16\n" + "\x12ERROR_CODE_NO_DATA\x10\x01\x12\x17\n" + "\x13ERROR_CODE_INTERNAL\x10\x02\x12\x1d\n" + "\x19ERROR_CODE_NOT_AGGREGATOR\x10\x032\x8d\x18\n" + "\x13SymbioticAPIService\x12g\n" + "\vSignMessage\x12 .api.proto.v1.SignMessageRequest\x1a!.api.proto.v1.SignMessageResponse\"\x13\x82\xd3\xe4\x93\x02\r:\x01*\"\b/v1/sign\x12\x96\x01\n" + "\x13GetAggregationProof\x12(.api.proto.v1.GetAggregationProofRequest\x1a).api.proto.v1.GetAggregationProofResponse\"*\x82\xd3\xe4\x93\x02$\x12\"/v1/aggregation/proof/{request_id}\x12\xb0\x01\n" + "\x1bGetAggregationProofsByEpoch\x120.api.proto.v1.GetAggregationProofsByEpochRequest\x1a1.api.proto.v1.GetAggregationProofsByEpochResponse\",\x82\xd3\xe4\x93\x02&\x12$/v1/aggregation/proofs/epoch/{epoch}\x12y\n" + "\x0fGetCurrentEpoch\x12$.api.proto.v1.GetCurrentEpochRequest\x1a%.api.proto.v1.GetCurrentEpochResponse\"\x19\x82\xd3\xe4\x93\x02\x13\x12\x11/v1/epoch/current\x12}\n" + "\rGetSignatures\x12\".api.proto.v1.GetSignaturesRequest\x1a#.api.proto.v1.GetSignaturesResponse\"#\x82\xd3\xe4\x93\x02\x1d\x12\x1b/v1/signatures/{request_id}\x12\x93\x01\n" + "\x14GetSignaturesByEpoch\x12).api.proto.v1.GetSignaturesByEpochRequest\x1a*.api.proto.v1.GetSignaturesByEpochResponse\"$\x82\xd3\xe4\x93\x02\x1e\x12\x1c/v1/signatures/epoch/{epoch}\x12\xb9\x01\n" + "\x1dGetSignatureRequestIDsByEpoch\x122.api.proto.v1.GetSignatureRequestIDsByEpochRequest\x1a3.api.proto.v1.GetSignatureRequestIDsByEpochResponse\"/\x82\xd3\xe4\x93\x02)\x12'/v1/signature-request-ids/epoch/{epoch}\x12\xb0\x01\n" + "\x1bGetSignatureRequestsByEpoch\x120.api.proto.v1.GetSignatureRequestsByEpochRequest\x1a1.api.proto.v1.GetSignatureRequestsByEpochResponse\",\x82\xd3\xe4\x93\x02&\x12$/v1/signature-requests/epoch/{epoch}\x12\x96\x01\n" + "\x13GetSignatureRequest\x12(.api.proto.v1.GetSignatureRequestRequest\x1a).api.proto.v1.GetSignatureRequestResponse\"*\x82\xd3\xe4\x93\x02$\x12\"/v1/signature-request/{request_id}\x12\x9a\x01\n" + "\x14GetAggregationStatus\x12).api.proto.v1.GetAggregationStatusRequest\x1a*.api.proto.v1.GetAggregationStatusResponse\"+\x82\xd3\xe4\x93\x02%\x12#/v1/aggregation/status/{request_id}\x12y\n" + "\x0fGetValidatorSet\x12$.api.proto.v1.GetValidatorSetRequest\x1a%.api.proto.v1.GetValidatorSetResponse\"\x19\x82\xd3\xe4\x93\x02\x13\x12\x11/v1/validator-set\x12\x99\x01\n" + "\x15GetValidatorByAddress\x12*.api.proto.v1.GetValidatorByAddressRequest\x1a+.api.proto.v1.GetValidatorByAddressResponse\"'\x82\xd3\xe4\x93\x02!\x12\x1f/v1/validator/address/{address}\x12\x98\x01\n" + "\x11GetValidatorByKey\x12&.api.proto.v1.GetValidatorByKeyRequest\x1a'.api.proto.v1.GetValidatorByKeyResponse\"2\x82\xd3\xe4\x93\x02,\x12*/v1/validator/key/{key_tag}/{on_chain_key}\x12\x81\x01\n" + "\x11GetLocalValidator\x12&.api.proto.v1.GetLocalValidatorRequest\x1a'.api.proto.v1.GetLocalValidatorResponse\"\x1b\x82\xd3\xe4\x93\x02\x15\x12\x13/v1/validator/local\x12\x92\x01\n" + "\x15GetValidatorSetHeader\x12*.api.proto.v1.GetValidatorSetHeaderRequest\x1a+.api.proto.v1.GetValidatorSetHeaderResponse\" \x82\xd3\xe4\x93\x02\x1a\x12\x18/v1/validator-set/header\x12\x94\x01\n" + "\x10GetLastCommitted\x12%.api.proto.v1.GetLastCommittedRequest\x1a&.api.proto.v1.GetLastCommittedResponse\"1\x82\xd3\xe4\x93\x02+\x12)/v1/committed/chain/{settlement_chain_id}\x12\x85\x01\n" + "\x13GetLastAllCommitted\x12(.api.proto.v1.GetLastAllCommittedRequest\x1a).api.proto.v1.GetLastAllCommittedResponse\"\x19\x82\xd3\xe4\x93\x02\x13\x12\x11/v1/committed/all\x12\x9a\x01\n" + "\x17GetValidatorSetMetadata\x12,.api.proto.v1.GetValidatorSetMetadataRequest\x1a-.api.proto.v1.GetValidatorSetMetadataResponse\"\"\x82\xd3\xe4\x93\x02\x1c\x12\x1a/v1/validator-set/metadata\x12\x82\x01\n" + "\x10ListenSignatures\x12%.api.proto.v1.ListenSignaturesRequest\x1a&.api.proto.v1.ListenSignaturesResponse\"\x1d\x82\xd3\xe4\x93\x02\x17\x12\x15/v1/stream/signatures0\x01\x12r\n" + "\fListenProofs\x12!.api.proto.v1.ListenProofsRequest\x1a\".api.proto.v1.ListenProofsResponse\"\x19\x82\xd3\xe4\x93\x02\x13\x12\x11/v1/stream/proofs0\x01\x12\x8b\x01\n" + "\x12ListenValidatorSet\x12'.api.proto.v1.ListenValidatorSetRequest\x1a(.api.proto.v1.ListenValidatorSetResponse\" \x82\xd3\xe4\x93\x02\x1a\x12\x18/v1/stream/validator-set0\x01B\x99\x01\n" + "\x10com.api.proto.v1B\bApiProtoP\x01Z)github.com/symbioticfi/relay/api/proto/v1\xa2\x02\x03APX\xaa\x02\fApi.Proto.V1\xca\x02\fApi\\Proto\\V1\xe2\x02\x18Api\\Proto\\V1\\GPBMetadata\xea\x02\x0eApi::Proto::V1b\x06proto3" ⋮---- var ( file_v1_api_proto_rawDescOnce sync.Once file_v1_api_proto_rawDescData []byte ) ⋮---- func file_v1_api_proto_rawDescGZIP() []byte ⋮---- var file_v1_api_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 52) var file_v1_api_proto_goTypes = []any{ (ValidatorSetStatus)(0), // 0: api.proto.v1.ValidatorSetStatus (SigningStatus)(0), // 1: api.proto.v1.SigningStatus (ErrorCode)(0), // 2: api.proto.v1.ErrorCode (*SignMessageRequest)(nil), // 3: api.proto.v1.SignMessageRequest (*SignMessageResponse)(nil), // 4: api.proto.v1.SignMessageResponse (*ListenSignaturesRequest)(nil), // 5: api.proto.v1.ListenSignaturesRequest (*ListenSignaturesResponse)(nil), // 6: api.proto.v1.ListenSignaturesResponse (*ListenProofsRequest)(nil), // 7: api.proto.v1.ListenProofsRequest (*ListenProofsResponse)(nil), // 8: api.proto.v1.ListenProofsResponse (*ListenValidatorSetRequest)(nil), // 9: api.proto.v1.ListenValidatorSetRequest (*ListenValidatorSetResponse)(nil), // 10: api.proto.v1.ListenValidatorSetResponse (*GetAggregationProofRequest)(nil), // 11: api.proto.v1.GetAggregationProofRequest (*GetAggregationProofsByEpochRequest)(nil), // 12: api.proto.v1.GetAggregationProofsByEpochRequest (*GetCurrentEpochRequest)(nil), // 13: api.proto.v1.GetCurrentEpochRequest (*GetSignaturesRequest)(nil), // 14: api.proto.v1.GetSignaturesRequest (*GetSignaturesByEpochRequest)(nil), // 15: api.proto.v1.GetSignaturesByEpochRequest (*GetSignaturesResponse)(nil), // 16: api.proto.v1.GetSignaturesResponse (*GetSignaturesByEpochResponse)(nil), // 17: api.proto.v1.GetSignaturesByEpochResponse (*GetSignatureRequestIDsByEpochRequest)(nil), // 18: api.proto.v1.GetSignatureRequestIDsByEpochRequest (*GetSignatureRequestIDsByEpochResponse)(nil), // 19: api.proto.v1.GetSignatureRequestIDsByEpochResponse (*GetSignatureRequestsByEpochRequest)(nil), // 20: api.proto.v1.GetSignatureRequestsByEpochRequest (*GetSignatureRequestsByEpochResponse)(nil), // 21: api.proto.v1.GetSignatureRequestsByEpochResponse (*GetSignatureRequestRequest)(nil), // 22: api.proto.v1.GetSignatureRequestRequest (*GetAggregationStatusRequest)(nil), // 23: api.proto.v1.GetAggregationStatusRequest (*GetValidatorSetRequest)(nil), // 24: api.proto.v1.GetValidatorSetRequest (*GetValidatorByAddressRequest)(nil), // 25: api.proto.v1.GetValidatorByAddressRequest (*GetValidatorByKeyRequest)(nil), // 26: api.proto.v1.GetValidatorByKeyRequest (*GetLocalValidatorRequest)(nil), // 27: api.proto.v1.GetLocalValidatorRequest (*GetValidatorSetHeaderRequest)(nil), // 28: api.proto.v1.GetValidatorSetHeaderRequest (*GetValidatorSetMetadataRequest)(nil), // 29: api.proto.v1.GetValidatorSetMetadataRequest (*GetCurrentEpochResponse)(nil), // 30: api.proto.v1.GetCurrentEpochResponse (*SignatureRequest)(nil), // 31: api.proto.v1.SignatureRequest (*GetSignatureRequestResponse)(nil), // 32: api.proto.v1.GetSignatureRequestResponse (*GetAggregationProofResponse)(nil), // 33: api.proto.v1.GetAggregationProofResponse (*GetAggregationProofsByEpochResponse)(nil), // 34: api.proto.v1.GetAggregationProofsByEpochResponse (*AggregationProof)(nil), // 35: api.proto.v1.AggregationProof (*GetAggregationStatusResponse)(nil), // 36: api.proto.v1.GetAggregationStatusResponse (*Signature)(nil), // 37: api.proto.v1.Signature (*GetValidatorSetResponse)(nil), // 38: api.proto.v1.GetValidatorSetResponse (*GetValidatorByAddressResponse)(nil), // 39: api.proto.v1.GetValidatorByAddressResponse (*GetValidatorByKeyResponse)(nil), // 40: api.proto.v1.GetValidatorByKeyResponse (*GetLocalValidatorResponse)(nil), // 41: api.proto.v1.GetLocalValidatorResponse (*ExtraData)(nil), // 42: api.proto.v1.ExtraData (*GetValidatorSetMetadataResponse)(nil), // 43: api.proto.v1.GetValidatorSetMetadataResponse (*GetValidatorSetHeaderResponse)(nil), // 44: api.proto.v1.GetValidatorSetHeaderResponse (*Validator)(nil), // 45: api.proto.v1.Validator (*Key)(nil), // 46: api.proto.v1.Key (*ValidatorVault)(nil), // 47: api.proto.v1.ValidatorVault (*GetLastCommittedRequest)(nil), // 48: api.proto.v1.GetLastCommittedRequest (*GetLastCommittedResponse)(nil), // 49: api.proto.v1.GetLastCommittedResponse (*GetLastAllCommittedRequest)(nil), // 50: api.proto.v1.GetLastAllCommittedRequest (*GetLastAllCommittedResponse)(nil), // 51: api.proto.v1.GetLastAllCommittedResponse (*ChainEpochInfo)(nil), // 52: api.proto.v1.ChainEpochInfo (*ValidatorSet)(nil), // 53: api.proto.v1.ValidatorSet nil, // 54: api.proto.v1.GetLastAllCommittedResponse.EpochInfosEntry (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp } ⋮---- (ValidatorSetStatus)(0), // 0: api.proto.v1.ValidatorSetStatus (SigningStatus)(0), // 1: api.proto.v1.SigningStatus (ErrorCode)(0), // 2: api.proto.v1.ErrorCode (*SignMessageRequest)(nil), // 3: api.proto.v1.SignMessageRequest (*SignMessageResponse)(nil), // 4: api.proto.v1.SignMessageResponse (*ListenSignaturesRequest)(nil), // 5: api.proto.v1.ListenSignaturesRequest (*ListenSignaturesResponse)(nil), // 6: api.proto.v1.ListenSignaturesResponse (*ListenProofsRequest)(nil), // 7: api.proto.v1.ListenProofsRequest (*ListenProofsResponse)(nil), // 8: api.proto.v1.ListenProofsResponse (*ListenValidatorSetRequest)(nil), // 9: api.proto.v1.ListenValidatorSetRequest (*ListenValidatorSetResponse)(nil), // 10: api.proto.v1.ListenValidatorSetResponse (*GetAggregationProofRequest)(nil), // 11: api.proto.v1.GetAggregationProofRequest (*GetAggregationProofsByEpochRequest)(nil), // 12: api.proto.v1.GetAggregationProofsByEpochRequest (*GetCurrentEpochRequest)(nil), // 13: api.proto.v1.GetCurrentEpochRequest (*GetSignaturesRequest)(nil), // 14: api.proto.v1.GetSignaturesRequest (*GetSignaturesByEpochRequest)(nil), // 15: api.proto.v1.GetSignaturesByEpochRequest (*GetSignaturesResponse)(nil), // 16: api.proto.v1.GetSignaturesResponse (*GetSignaturesByEpochResponse)(nil), // 17: api.proto.v1.GetSignaturesByEpochResponse (*GetSignatureRequestIDsByEpochRequest)(nil), // 18: api.proto.v1.GetSignatureRequestIDsByEpochRequest (*GetSignatureRequestIDsByEpochResponse)(nil), // 19: api.proto.v1.GetSignatureRequestIDsByEpochResponse (*GetSignatureRequestsByEpochRequest)(nil), // 20: api.proto.v1.GetSignatureRequestsByEpochRequest (*GetSignatureRequestsByEpochResponse)(nil), // 21: api.proto.v1.GetSignatureRequestsByEpochResponse (*GetSignatureRequestRequest)(nil), // 22: api.proto.v1.GetSignatureRequestRequest (*GetAggregationStatusRequest)(nil), // 23: api.proto.v1.GetAggregationStatusRequest (*GetValidatorSetRequest)(nil), // 24: api.proto.v1.GetValidatorSetRequest (*GetValidatorByAddressRequest)(nil), // 25: api.proto.v1.GetValidatorByAddressRequest (*GetValidatorByKeyRequest)(nil), // 26: api.proto.v1.GetValidatorByKeyRequest (*GetLocalValidatorRequest)(nil), // 27: api.proto.v1.GetLocalValidatorRequest (*GetValidatorSetHeaderRequest)(nil), // 28: api.proto.v1.GetValidatorSetHeaderRequest (*GetValidatorSetMetadataRequest)(nil), // 29: api.proto.v1.GetValidatorSetMetadataRequest (*GetCurrentEpochResponse)(nil), // 30: api.proto.v1.GetCurrentEpochResponse (*SignatureRequest)(nil), // 31: api.proto.v1.SignatureRequest (*GetSignatureRequestResponse)(nil), // 32: api.proto.v1.GetSignatureRequestResponse (*GetAggregationProofResponse)(nil), // 33: api.proto.v1.GetAggregationProofResponse (*GetAggregationProofsByEpochResponse)(nil), // 34: api.proto.v1.GetAggregationProofsByEpochResponse (*AggregationProof)(nil), // 35: api.proto.v1.AggregationProof (*GetAggregationStatusResponse)(nil), // 36: api.proto.v1.GetAggregationStatusResponse (*Signature)(nil), // 37: api.proto.v1.Signature (*GetValidatorSetResponse)(nil), // 38: api.proto.v1.GetValidatorSetResponse (*GetValidatorByAddressResponse)(nil), // 39: api.proto.v1.GetValidatorByAddressResponse (*GetValidatorByKeyResponse)(nil), // 40: api.proto.v1.GetValidatorByKeyResponse (*GetLocalValidatorResponse)(nil), // 41: api.proto.v1.GetLocalValidatorResponse (*ExtraData)(nil), // 42: api.proto.v1.ExtraData (*GetValidatorSetMetadataResponse)(nil), // 43: api.proto.v1.GetValidatorSetMetadataResponse (*GetValidatorSetHeaderResponse)(nil), // 44: api.proto.v1.GetValidatorSetHeaderResponse (*Validator)(nil), // 45: api.proto.v1.Validator (*Key)(nil), // 46: api.proto.v1.Key (*ValidatorVault)(nil), // 47: api.proto.v1.ValidatorVault (*GetLastCommittedRequest)(nil), // 48: api.proto.v1.GetLastCommittedRequest (*GetLastCommittedResponse)(nil), // 49: api.proto.v1.GetLastCommittedResponse (*GetLastAllCommittedRequest)(nil), // 50: api.proto.v1.GetLastAllCommittedRequest (*GetLastAllCommittedResponse)(nil), // 51: api.proto.v1.GetLastAllCommittedResponse (*ChainEpochInfo)(nil), // 52: api.proto.v1.ChainEpochInfo (*ValidatorSet)(nil), // 53: api.proto.v1.ValidatorSet nil, // 54: api.proto.v1.GetLastAllCommittedResponse.EpochInfosEntry (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp ⋮---- var file_v1_api_proto_depIdxs = []int32{ 37, // 0: api.proto.v1.ListenSignaturesResponse.signature:type_name -> api.proto.v1.Signature 35, // 1: api.proto.v1.ListenProofsResponse.aggregation_proof:type_name -> api.proto.v1.AggregationProof 53, // 2: api.proto.v1.ListenValidatorSetResponse.validator_set:type_name -> api.proto.v1.ValidatorSet 37, // 3: api.proto.v1.GetSignaturesResponse.signatures:type_name -> api.proto.v1.Signature 37, // 4: api.proto.v1.GetSignaturesByEpochResponse.signatures:type_name -> api.proto.v1.Signature 31, // 5: api.proto.v1.GetSignatureRequestsByEpochResponse.signature_requests:type_name -> api.proto.v1.SignatureRequest 55, // 6: api.proto.v1.GetCurrentEpochResponse.start_time:type_name -> google.protobuf.Timestamp 31, // 7: api.proto.v1.GetSignatureRequestResponse.signature_request:type_name -> api.proto.v1.SignatureRequest 35, // 8: api.proto.v1.GetAggregationProofResponse.aggregation_proof:type_name -> api.proto.v1.AggregationProof 35, // 9: api.proto.v1.GetAggregationProofsByEpochResponse.aggregation_proofs:type_name -> api.proto.v1.AggregationProof 53, // 10: api.proto.v1.GetValidatorSetResponse.validator_set:type_name -> api.proto.v1.ValidatorSet 45, // 11: api.proto.v1.GetValidatorByAddressResponse.validator:type_name -> api.proto.v1.Validator 45, // 12: api.proto.v1.GetValidatorByKeyResponse.validator:type_name -> api.proto.v1.Validator 45, // 13: api.proto.v1.GetLocalValidatorResponse.validator:type_name -> api.proto.v1.Validator 42, // 14: api.proto.v1.GetValidatorSetMetadataResponse.extra_data:type_name -> api.proto.v1.ExtraData 55, // 15: api.proto.v1.GetValidatorSetHeaderResponse.capture_timestamp:type_name -> google.protobuf.Timestamp 46, // 16: api.proto.v1.Validator.keys:type_name -> api.proto.v1.Key 47, // 17: api.proto.v1.Validator.vaults:type_name -> api.proto.v1.ValidatorVault 52, // 18: api.proto.v1.GetLastCommittedResponse.epoch_info:type_name -> api.proto.v1.ChainEpochInfo 54, // 19: api.proto.v1.GetLastAllCommittedResponse.epoch_infos:type_name -> api.proto.v1.GetLastAllCommittedResponse.EpochInfosEntry 52, // 20: api.proto.v1.GetLastAllCommittedResponse.suggested_epoch_info:type_name -> api.proto.v1.ChainEpochInfo 55, // 21: api.proto.v1.ChainEpochInfo.start_time:type_name -> google.protobuf.Timestamp 55, // 22: api.proto.v1.ValidatorSet.capture_timestamp:type_name -> google.protobuf.Timestamp 0, // 23: api.proto.v1.ValidatorSet.status:type_name -> api.proto.v1.ValidatorSetStatus 45, // 24: api.proto.v1.ValidatorSet.validators:type_name -> api.proto.v1.Validator 52, // 25: api.proto.v1.GetLastAllCommittedResponse.EpochInfosEntry.value:type_name -> api.proto.v1.ChainEpochInfo 3, // 26: api.proto.v1.SymbioticAPIService.SignMessage:input_type -> api.proto.v1.SignMessageRequest 11, // 27: api.proto.v1.SymbioticAPIService.GetAggregationProof:input_type -> api.proto.v1.GetAggregationProofRequest 12, // 28: api.proto.v1.SymbioticAPIService.GetAggregationProofsByEpoch:input_type -> api.proto.v1.GetAggregationProofsByEpochRequest 13, // 29: api.proto.v1.SymbioticAPIService.GetCurrentEpoch:input_type -> api.proto.v1.GetCurrentEpochRequest 14, // 30: api.proto.v1.SymbioticAPIService.GetSignatures:input_type -> api.proto.v1.GetSignaturesRequest 15, // 31: api.proto.v1.SymbioticAPIService.GetSignaturesByEpoch:input_type -> api.proto.v1.GetSignaturesByEpochRequest 18, // 32: api.proto.v1.SymbioticAPIService.GetSignatureRequestIDsByEpoch:input_type -> api.proto.v1.GetSignatureRequestIDsByEpochRequest 20, // 33: api.proto.v1.SymbioticAPIService.GetSignatureRequestsByEpoch:input_type -> api.proto.v1.GetSignatureRequestsByEpochRequest 22, // 34: api.proto.v1.SymbioticAPIService.GetSignatureRequest:input_type -> api.proto.v1.GetSignatureRequestRequest 23, // 35: api.proto.v1.SymbioticAPIService.GetAggregationStatus:input_type -> api.proto.v1.GetAggregationStatusRequest 24, // 36: api.proto.v1.SymbioticAPIService.GetValidatorSet:input_type -> api.proto.v1.GetValidatorSetRequest 25, // 37: api.proto.v1.SymbioticAPIService.GetValidatorByAddress:input_type -> api.proto.v1.GetValidatorByAddressRequest 26, // 38: api.proto.v1.SymbioticAPIService.GetValidatorByKey:input_type -> api.proto.v1.GetValidatorByKeyRequest 27, // 39: api.proto.v1.SymbioticAPIService.GetLocalValidator:input_type -> api.proto.v1.GetLocalValidatorRequest 28, // 40: api.proto.v1.SymbioticAPIService.GetValidatorSetHeader:input_type -> api.proto.v1.GetValidatorSetHeaderRequest 48, // 41: api.proto.v1.SymbioticAPIService.GetLastCommitted:input_type -> api.proto.v1.GetLastCommittedRequest 50, // 42: api.proto.v1.SymbioticAPIService.GetLastAllCommitted:input_type -> api.proto.v1.GetLastAllCommittedRequest 29, // 43: api.proto.v1.SymbioticAPIService.GetValidatorSetMetadata:input_type -> api.proto.v1.GetValidatorSetMetadataRequest 5, // 44: api.proto.v1.SymbioticAPIService.ListenSignatures:input_type -> api.proto.v1.ListenSignaturesRequest 7, // 45: api.proto.v1.SymbioticAPIService.ListenProofs:input_type -> api.proto.v1.ListenProofsRequest 9, // 46: api.proto.v1.SymbioticAPIService.ListenValidatorSet:input_type -> api.proto.v1.ListenValidatorSetRequest 4, // 47: api.proto.v1.SymbioticAPIService.SignMessage:output_type -> api.proto.v1.SignMessageResponse 33, // 48: api.proto.v1.SymbioticAPIService.GetAggregationProof:output_type -> api.proto.v1.GetAggregationProofResponse 34, // 49: api.proto.v1.SymbioticAPIService.GetAggregationProofsByEpoch:output_type -> api.proto.v1.GetAggregationProofsByEpochResponse 30, // 50: api.proto.v1.SymbioticAPIService.GetCurrentEpoch:output_type -> api.proto.v1.GetCurrentEpochResponse 16, // 51: api.proto.v1.SymbioticAPIService.GetSignatures:output_type -> api.proto.v1.GetSignaturesResponse 17, // 52: api.proto.v1.SymbioticAPIService.GetSignaturesByEpoch:output_type -> api.proto.v1.GetSignaturesByEpochResponse 19, // 53: api.proto.v1.SymbioticAPIService.GetSignatureRequestIDsByEpoch:output_type -> api.proto.v1.GetSignatureRequestIDsByEpochResponse 21, // 54: api.proto.v1.SymbioticAPIService.GetSignatureRequestsByEpoch:output_type -> api.proto.v1.GetSignatureRequestsByEpochResponse 32, // 55: api.proto.v1.SymbioticAPIService.GetSignatureRequest:output_type -> api.proto.v1.GetSignatureRequestResponse 36, // 56: api.proto.v1.SymbioticAPIService.GetAggregationStatus:output_type -> api.proto.v1.GetAggregationStatusResponse 38, // 57: api.proto.v1.SymbioticAPIService.GetValidatorSet:output_type -> api.proto.v1.GetValidatorSetResponse 39, // 58: api.proto.v1.SymbioticAPIService.GetValidatorByAddress:output_type -> api.proto.v1.GetValidatorByAddressResponse 40, // 59: api.proto.v1.SymbioticAPIService.GetValidatorByKey:output_type -> api.proto.v1.GetValidatorByKeyResponse 41, // 60: api.proto.v1.SymbioticAPIService.GetLocalValidator:output_type -> api.proto.v1.GetLocalValidatorResponse 44, // 61: api.proto.v1.SymbioticAPIService.GetValidatorSetHeader:output_type -> api.proto.v1.GetValidatorSetHeaderResponse 49, // 62: api.proto.v1.SymbioticAPIService.GetLastCommitted:output_type -> api.proto.v1.GetLastCommittedResponse 51, // 63: api.proto.v1.SymbioticAPIService.GetLastAllCommitted:output_type -> api.proto.v1.GetLastAllCommittedResponse 43, // 64: api.proto.v1.SymbioticAPIService.GetValidatorSetMetadata:output_type -> api.proto.v1.GetValidatorSetMetadataResponse 6, // 65: api.proto.v1.SymbioticAPIService.ListenSignatures:output_type -> api.proto.v1.ListenSignaturesResponse 8, // 66: api.proto.v1.SymbioticAPIService.ListenProofs:output_type -> api.proto.v1.ListenProofsResponse 10, // 67: api.proto.v1.SymbioticAPIService.ListenValidatorSet:output_type -> api.proto.v1.ListenValidatorSetResponse 47, // [47:68] is the sub-list for method output_type 26, // [26:47] is the sub-list for method input_type 26, // [26:26] is the sub-list for extension type_name 26, // [26:26] is the sub-list for extension extendee 0, // [0:26] is the sub-list for field type_name } ⋮---- 37, // 0: api.proto.v1.ListenSignaturesResponse.signature:type_name -> api.proto.v1.Signature 35, // 1: api.proto.v1.ListenProofsResponse.aggregation_proof:type_name -> api.proto.v1.AggregationProof 53, // 2: api.proto.v1.ListenValidatorSetResponse.validator_set:type_name -> api.proto.v1.ValidatorSet 37, // 3: api.proto.v1.GetSignaturesResponse.signatures:type_name -> api.proto.v1.Signature 37, // 4: api.proto.v1.GetSignaturesByEpochResponse.signatures:type_name -> api.proto.v1.Signature 31, // 5: api.proto.v1.GetSignatureRequestsByEpochResponse.signature_requests:type_name -> api.proto.v1.SignatureRequest 55, // 6: api.proto.v1.GetCurrentEpochResponse.start_time:type_name -> google.protobuf.Timestamp 31, // 7: api.proto.v1.GetSignatureRequestResponse.signature_request:type_name -> api.proto.v1.SignatureRequest 35, // 8: api.proto.v1.GetAggregationProofResponse.aggregation_proof:type_name -> api.proto.v1.AggregationProof 35, // 9: api.proto.v1.GetAggregationProofsByEpochResponse.aggregation_proofs:type_name -> api.proto.v1.AggregationProof 53, // 10: api.proto.v1.GetValidatorSetResponse.validator_set:type_name -> api.proto.v1.ValidatorSet 45, // 11: api.proto.v1.GetValidatorByAddressResponse.validator:type_name -> api.proto.v1.Validator 45, // 12: api.proto.v1.GetValidatorByKeyResponse.validator:type_name -> api.proto.v1.Validator 45, // 13: api.proto.v1.GetLocalValidatorResponse.validator:type_name -> api.proto.v1.Validator 42, // 14: api.proto.v1.GetValidatorSetMetadataResponse.extra_data:type_name -> api.proto.v1.ExtraData 55, // 15: api.proto.v1.GetValidatorSetHeaderResponse.capture_timestamp:type_name -> google.protobuf.Timestamp 46, // 16: api.proto.v1.Validator.keys:type_name -> api.proto.v1.Key 47, // 17: api.proto.v1.Validator.vaults:type_name -> api.proto.v1.ValidatorVault 52, // 18: api.proto.v1.GetLastCommittedResponse.epoch_info:type_name -> api.proto.v1.ChainEpochInfo 54, // 19: api.proto.v1.GetLastAllCommittedResponse.epoch_infos:type_name -> api.proto.v1.GetLastAllCommittedResponse.EpochInfosEntry 52, // 20: api.proto.v1.GetLastAllCommittedResponse.suggested_epoch_info:type_name -> api.proto.v1.ChainEpochInfo 55, // 21: api.proto.v1.ChainEpochInfo.start_time:type_name -> google.protobuf.Timestamp 55, // 22: api.proto.v1.ValidatorSet.capture_timestamp:type_name -> google.protobuf.Timestamp 0, // 23: api.proto.v1.ValidatorSet.status:type_name -> api.proto.v1.ValidatorSetStatus 45, // 24: api.proto.v1.ValidatorSet.validators:type_name -> api.proto.v1.Validator 52, // 25: api.proto.v1.GetLastAllCommittedResponse.EpochInfosEntry.value:type_name -> api.proto.v1.ChainEpochInfo 3, // 26: api.proto.v1.SymbioticAPIService.SignMessage:input_type -> api.proto.v1.SignMessageRequest 11, // 27: api.proto.v1.SymbioticAPIService.GetAggregationProof:input_type -> api.proto.v1.GetAggregationProofRequest 12, // 28: api.proto.v1.SymbioticAPIService.GetAggregationProofsByEpoch:input_type -> api.proto.v1.GetAggregationProofsByEpochRequest 13, // 29: api.proto.v1.SymbioticAPIService.GetCurrentEpoch:input_type -> api.proto.v1.GetCurrentEpochRequest 14, // 30: api.proto.v1.SymbioticAPIService.GetSignatures:input_type -> api.proto.v1.GetSignaturesRequest 15, // 31: api.proto.v1.SymbioticAPIService.GetSignaturesByEpoch:input_type -> api.proto.v1.GetSignaturesByEpochRequest 18, // 32: api.proto.v1.SymbioticAPIService.GetSignatureRequestIDsByEpoch:input_type -> api.proto.v1.GetSignatureRequestIDsByEpochRequest 20, // 33: api.proto.v1.SymbioticAPIService.GetSignatureRequestsByEpoch:input_type -> api.proto.v1.GetSignatureRequestsByEpochRequest 22, // 34: api.proto.v1.SymbioticAPIService.GetSignatureRequest:input_type -> api.proto.v1.GetSignatureRequestRequest 23, // 35: api.proto.v1.SymbioticAPIService.GetAggregationStatus:input_type -> api.proto.v1.GetAggregationStatusRequest 24, // 36: api.proto.v1.SymbioticAPIService.GetValidatorSet:input_type -> api.proto.v1.GetValidatorSetRequest 25, // 37: api.proto.v1.SymbioticAPIService.GetValidatorByAddress:input_type -> api.proto.v1.GetValidatorByAddressRequest 26, // 38: api.proto.v1.SymbioticAPIService.GetValidatorByKey:input_type -> api.proto.v1.GetValidatorByKeyRequest 27, // 39: api.proto.v1.SymbioticAPIService.GetLocalValidator:input_type -> api.proto.v1.GetLocalValidatorRequest 28, // 40: api.proto.v1.SymbioticAPIService.GetValidatorSetHeader:input_type -> api.proto.v1.GetValidatorSetHeaderRequest 48, // 41: api.proto.v1.SymbioticAPIService.GetLastCommitted:input_type -> api.proto.v1.GetLastCommittedRequest 50, // 42: api.proto.v1.SymbioticAPIService.GetLastAllCommitted:input_type -> api.proto.v1.GetLastAllCommittedRequest 29, // 43: api.proto.v1.SymbioticAPIService.GetValidatorSetMetadata:input_type -> api.proto.v1.GetValidatorSetMetadataRequest 5, // 44: api.proto.v1.SymbioticAPIService.ListenSignatures:input_type -> api.proto.v1.ListenSignaturesRequest 7, // 45: api.proto.v1.SymbioticAPIService.ListenProofs:input_type -> api.proto.v1.ListenProofsRequest 9, // 46: api.proto.v1.SymbioticAPIService.ListenValidatorSet:input_type -> api.proto.v1.ListenValidatorSetRequest 4, // 47: api.proto.v1.SymbioticAPIService.SignMessage:output_type -> api.proto.v1.SignMessageResponse 33, // 48: api.proto.v1.SymbioticAPIService.GetAggregationProof:output_type -> api.proto.v1.GetAggregationProofResponse 34, // 49: api.proto.v1.SymbioticAPIService.GetAggregationProofsByEpoch:output_type -> api.proto.v1.GetAggregationProofsByEpochResponse 30, // 50: api.proto.v1.SymbioticAPIService.GetCurrentEpoch:output_type -> api.proto.v1.GetCurrentEpochResponse 16, // 51: api.proto.v1.SymbioticAPIService.GetSignatures:output_type -> api.proto.v1.GetSignaturesResponse 17, // 52: api.proto.v1.SymbioticAPIService.GetSignaturesByEpoch:output_type -> api.proto.v1.GetSignaturesByEpochResponse 19, // 53: api.proto.v1.SymbioticAPIService.GetSignatureRequestIDsByEpoch:output_type -> api.proto.v1.GetSignatureRequestIDsByEpochResponse 21, // 54: api.proto.v1.SymbioticAPIService.GetSignatureRequestsByEpoch:output_type -> api.proto.v1.GetSignatureRequestsByEpochResponse 32, // 55: api.proto.v1.SymbioticAPIService.GetSignatureRequest:output_type -> api.proto.v1.GetSignatureRequestResponse 36, // 56: api.proto.v1.SymbioticAPIService.GetAggregationStatus:output_type -> api.proto.v1.GetAggregationStatusResponse 38, // 57: api.proto.v1.SymbioticAPIService.GetValidatorSet:output_type -> api.proto.v1.GetValidatorSetResponse 39, // 58: api.proto.v1.SymbioticAPIService.GetValidatorByAddress:output_type -> api.proto.v1.GetValidatorByAddressResponse 40, // 59: api.proto.v1.SymbioticAPIService.GetValidatorByKey:output_type -> api.proto.v1.GetValidatorByKeyResponse 41, // 60: api.proto.v1.SymbioticAPIService.GetLocalValidator:output_type -> api.proto.v1.GetLocalValidatorResponse 44, // 61: api.proto.v1.SymbioticAPIService.GetValidatorSetHeader:output_type -> api.proto.v1.GetValidatorSetHeaderResponse 49, // 62: api.proto.v1.SymbioticAPIService.GetLastCommitted:output_type -> api.proto.v1.GetLastCommittedResponse 51, // 63: api.proto.v1.SymbioticAPIService.GetLastAllCommitted:output_type -> api.proto.v1.GetLastAllCommittedResponse 43, // 64: api.proto.v1.SymbioticAPIService.GetValidatorSetMetadata:output_type -> api.proto.v1.GetValidatorSetMetadataResponse 6, // 65: api.proto.v1.SymbioticAPIService.ListenSignatures:output_type -> api.proto.v1.ListenSignaturesResponse 8, // 66: api.proto.v1.SymbioticAPIService.ListenProofs:output_type -> api.proto.v1.ListenProofsResponse 10, // 67: api.proto.v1.SymbioticAPIService.ListenValidatorSet:output_type -> api.proto.v1.ListenValidatorSetResponse 47, // [47:68] is the sub-list for method output_type 26, // [26:47] is the sub-list for method input_type 26, // [26:26] is the sub-list for extension type_name 26, // [26:26] is the sub-list for extension extendee 0, // [0:26] is the sub-list for field type_name ⋮---- func init() func file_v1_api_proto_init() ⋮---- type x struct{} ```` ## File: internal/gen/api/v1/api.pb.gw.go ````go // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. // source: v1/api.proto ⋮---- /* Package v1 is a reverse proxy. It translates gRPC into RESTful JSON APIs. */ package v1 ⋮---- import ( "context" "errors" "io" "net/http" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) ⋮---- "context" "errors" "io" "net/http" ⋮---- "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ⋮---- // Suppress "imported and not used" errors var ( _ codes.Code _ io.Reader _ status.Status _ = errors.New _ = runtime.String _ = utilities.NewDoubleArray _ = metadata.Join ) ⋮---- func request_SymbioticAPIService_SignMessage_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq SignMessageRequest metadata runtime.ServerMetadata ) ⋮---- func local_request_SymbioticAPIService_SignMessage_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetAggregationProof_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetAggregationProofRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetAggregationProof_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetAggregationProofsByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetAggregationProofsByEpochRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetAggregationProofsByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetCurrentEpoch_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetCurrentEpochRequest metadata runtime.ServerMetadata ) ⋮---- func local_request_SymbioticAPIService_GetCurrentEpoch_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetSignatures_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetSignaturesRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetSignatures_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetSignaturesByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetSignaturesByEpochRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetSignaturesByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetSignatureRequestIDsByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetSignatureRequestIDsByEpochRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetSignatureRequestIDsByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetSignatureRequestsByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetSignatureRequestsByEpochRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetSignatureRequestsByEpoch_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetSignatureRequest_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetSignatureRequestRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetSignatureRequest_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetAggregationStatus_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetAggregationStatusRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetAggregationStatus_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var filter_SymbioticAPIService_GetValidatorSet_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ⋮---- func request_SymbioticAPIService_GetValidatorSet_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetValidatorSetRequest metadata runtime.ServerMetadata ) ⋮---- func local_request_SymbioticAPIService_GetValidatorSet_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var filter_SymbioticAPIService_GetValidatorByAddress_0 = &utilities.DoubleArray{Encoding: map[string]int{"address": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ⋮---- func request_SymbioticAPIService_GetValidatorByAddress_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetValidatorByAddressRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetValidatorByAddress_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var filter_SymbioticAPIService_GetValidatorByKey_0 = &utilities.DoubleArray{Encoding: map[string]int{"key_tag": 0, "on_chain_key": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} ⋮---- func request_SymbioticAPIService_GetValidatorByKey_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetValidatorByKeyRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetValidatorByKey_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var filter_SymbioticAPIService_GetLocalValidator_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ⋮---- func request_SymbioticAPIService_GetLocalValidator_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetLocalValidatorRequest metadata runtime.ServerMetadata ) ⋮---- func local_request_SymbioticAPIService_GetLocalValidator_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var filter_SymbioticAPIService_GetValidatorSetHeader_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ⋮---- func request_SymbioticAPIService_GetValidatorSetHeader_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetValidatorSetHeaderRequest metadata runtime.ServerMetadata ) ⋮---- func local_request_SymbioticAPIService_GetValidatorSetHeader_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetLastCommitted_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetLastCommittedRequest metadata runtime.ServerMetadata err error ) ⋮---- func local_request_SymbioticAPIService_GetLastCommitted_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- func request_SymbioticAPIService_GetLastAllCommitted_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetLastAllCommittedRequest metadata runtime.ServerMetadata ) ⋮---- func local_request_SymbioticAPIService_GetLastAllCommitted_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var filter_SymbioticAPIService_GetValidatorSetMetadata_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ⋮---- func request_SymbioticAPIService_GetValidatorSetMetadata_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var ( protoReq GetValidatorSetMetadataRequest metadata runtime.ServerMetadata ) ⋮---- func local_request_SymbioticAPIService_GetValidatorSetMetadata_0(ctx context.Context, marshaler runtime.Marshaler, server SymbioticAPIServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) ⋮---- var filter_SymbioticAPIService_ListenSignatures_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ⋮---- func request_SymbioticAPIService_ListenSignatures_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (SymbioticAPIService_ListenSignaturesClient, runtime.ServerMetadata, error) ⋮---- var ( protoReq ListenSignaturesRequest metadata runtime.ServerMetadata ) ⋮---- var filter_SymbioticAPIService_ListenProofs_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ⋮---- func request_SymbioticAPIService_ListenProofs_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (SymbioticAPIService_ListenProofsClient, runtime.ServerMetadata, error) ⋮---- var ( protoReq ListenProofsRequest metadata runtime.ServerMetadata ) ⋮---- var filter_SymbioticAPIService_ListenValidatorSet_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ⋮---- func request_SymbioticAPIService_ListenValidatorSet_0(ctx context.Context, marshaler runtime.Marshaler, client SymbioticAPIServiceClient, req *http.Request, pathParams map[string]string) (SymbioticAPIService_ListenValidatorSetClient, runtime.ServerMetadata, error) ⋮---- var ( protoReq ListenValidatorSetRequest metadata runtime.ServerMetadata ) ⋮---- // RegisterSymbioticAPIServiceHandlerServer registers the http handlers for service SymbioticAPIService to "mux". // UnaryRPC :call SymbioticAPIServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterSymbioticAPIServiceHandlerFromEndpoint instead. // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterSymbioticAPIServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server SymbioticAPIServiceServer) error ⋮---- var stream runtime.ServerTransportStream ⋮---- // RegisterSymbioticAPIServiceHandlerFromEndpoint is same as RegisterSymbioticAPIServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterSymbioticAPIServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) ⋮---- // RegisterSymbioticAPIServiceHandler registers the http handlers for service SymbioticAPIService to "mux". // The handlers forward requests to the grpc endpoint over "conn". func RegisterSymbioticAPIServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error ⋮---- // RegisterSymbioticAPIServiceHandlerClient registers the http handlers for service SymbioticAPIService // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "SymbioticAPIServiceClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "SymbioticAPIServiceClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in // "SymbioticAPIServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterSymbioticAPIServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client SymbioticAPIServiceClient) error ⋮---- var ( pattern_SymbioticAPIService_SignMessage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "sign"}, "")) ⋮---- var ( forward_SymbioticAPIService_SignMessage_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetAggregationProof_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetAggregationProofsByEpoch_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetCurrentEpoch_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetSignatures_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetSignaturesByEpoch_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetSignatureRequestIDsByEpoch_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetSignatureRequestsByEpoch_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetSignatureRequest_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetAggregationStatus_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetValidatorSet_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetValidatorByAddress_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetValidatorByKey_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetLocalValidator_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetValidatorSetHeader_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetLastCommitted_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetLastAllCommitted_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_GetValidatorSetMetadata_0 = runtime.ForwardResponseMessage forward_SymbioticAPIService_ListenSignatures_0 = runtime.ForwardResponseStream forward_SymbioticAPIService_ListenProofs_0 = runtime.ForwardResponseStream forward_SymbioticAPIService_ListenValidatorSet_0 = runtime.ForwardResponseStream ) ```` ## File: internal/usecase/aggregation-policy/low-cost/low_cost_policy.go ````go package lowCostPolicy ⋮---- import ( symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/internal/entity" ) ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/symbioticfi/relay/internal/entity" ⋮---- type LowCostPolicy struct { maxUnsigners uint64 } ⋮---- func NewLowCostPolicy(maxUnsigners uint64) *LowCostPolicy ⋮---- func (lcp *LowCostPolicy) ShouldAggregate(signatureMap entity.SignatureMap, validatorSet symbiotic.ValidatorSet) bool ```` ## File: internal/usecase/aggregation-policy/low-latency/low_latency_policy.go ````go package lowLatencyPolicy ⋮---- import ( "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type LowLatencyPolicy struct { } ⋮---- func NewLowLatencyPolicy() *LowLatencyPolicy ⋮---- func (llp *LowLatencyPolicy) ShouldAggregate(signatureMap entity.SignatureMap, validatorSet symbiotic.ValidatorSet) bool ```` ## File: internal/usecase/aggregation-policy/types/types.go ````go package aggregationPolicyTypes ⋮---- import ( "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type AggregationPolicy interface { ShouldAggregate(signatureMap entity.SignatureMap, validatorSet symbiotic.ValidatorSet) bool } ```` ## File: internal/usecase/aggregation-policy/aggregation_policies.go ````go package aggregationPolicy ⋮---- import ( "errors" lowCostPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/low-cost" lowLatencyPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/low-latency" aggregationPolicyTypes "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/types" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "errors" ⋮---- lowCostPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/low-cost" lowLatencyPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/low-latency" aggregationPolicyTypes "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/types" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func NewAggregationPolicy(aggregationPolicyType symbiotic.AggregationPolicyType, maxUnsigners uint64) (aggregationPolicyTypes.AggregationPolicy, error) ```` ## File: internal/usecase/aggregator-app/mocks/aggregator_app.go ````go // Code generated by MockGen. DO NOT EDIT. // Source: aggregator_app.go // // Generated by this command: ⋮---- // mockgen -source=aggregator_app.go -destination=mocks/aggregator_app.go -package=mocks ⋮---- // Package mocks is a generated GoMock package. package mocks ⋮---- import ( context "context" reflect "reflect" time "time" common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/internal/entity" entity0 "github.com/symbioticfi/relay/symbiotic/entity" crypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" gomock "go.uber.org/mock/gomock" ) ⋮---- context "context" reflect "reflect" time "time" ⋮---- common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/internal/entity" entity0 "github.com/symbioticfi/relay/symbiotic/entity" crypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" gomock "go.uber.org/mock/gomock" ⋮---- // Mockrepository is a mock of repository interface. type Mockrepository struct { ctrl *gomock.Controller recorder *MockrepositoryMockRecorder isgomock struct{} ⋮---- // MockrepositoryMockRecorder is the mock recorder for Mockrepository. type MockrepositoryMockRecorder struct { mock *Mockrepository } ⋮---- // NewMockrepository creates a new mock instance. func NewMockrepository(ctrl *gomock.Controller) *Mockrepository ⋮---- // EXPECT returns an object that allows the caller to indicate expected use. func (m *Mockrepository) EXPECT() *MockrepositoryMockRecorder ⋮---- // GetAggregationProof mocks base method. func (m *Mockrepository) GetAggregationProof(ctx context.Context, requestID common.Hash) (entity0.AggregationProof, error) ⋮---- // GetAggregationProof indicates an expected call of GetAggregationProof. ⋮---- // GetAllSignatures mocks base method. func (m *Mockrepository) GetAllSignatures(ctx context.Context, requestID common.Hash) ([]entity0.Signature, error) ⋮---- // GetAllSignatures indicates an expected call of GetAllSignatures. ⋮---- // GetConfigByEpoch mocks base method. func (m *Mockrepository) GetConfigByEpoch(ctx context.Context, epoch entity0.Epoch) (entity0.NetworkConfig, error) ⋮---- // GetConfigByEpoch indicates an expected call of GetConfigByEpoch. ⋮---- // GetSignatureMap mocks base method. func (m *Mockrepository) GetSignatureMap(ctx context.Context, requestID common.Hash) (entity.SignatureMap, error) ⋮---- // GetSignatureMap indicates an expected call of GetSignatureMap. ⋮---- // GetSignatureRequest mocks base method. func (m *Mockrepository) GetSignatureRequest(arg0 context.Context, requestID common.Hash) (entity0.SignatureRequest, error) ⋮---- // GetSignatureRequest indicates an expected call of GetSignatureRequest. ⋮---- // GetValidatorSetByEpoch mocks base method. func (m *Mockrepository) GetValidatorSetByEpoch(ctx context.Context, epoch entity0.Epoch) (entity0.ValidatorSet, error) ⋮---- // GetValidatorSetByEpoch indicates an expected call of GetValidatorSetByEpoch. ⋮---- // Mockp2pClient is a mock of p2pClient interface. type Mockp2pClient struct { ctrl *gomock.Controller recorder *Mockp2pClientMockRecorder isgomock struct{} ⋮---- // Mockp2pClientMockRecorder is the mock recorder for Mockp2pClient. type Mockp2pClientMockRecorder struct { mock *Mockp2pClient } ⋮---- // NewMockp2pClient creates a new mock instance. func NewMockp2pClient(ctrl *gomock.Controller) *Mockp2pClient ⋮---- // BroadcastSignatureAggregatedMessage mocks base method. func (m *Mockp2pClient) BroadcastSignatureAggregatedMessage(ctx context.Context, proof entity0.AggregationProof) error ⋮---- // BroadcastSignatureAggregatedMessage indicates an expected call of BroadcastSignatureAggregatedMessage. ⋮---- // Mockmetrics is a mock of metrics interface. type Mockmetrics struct { ctrl *gomock.Controller recorder *MockmetricsMockRecorder isgomock struct{} ⋮---- // MockmetricsMockRecorder is the mock recorder for Mockmetrics. type MockmetricsMockRecorder struct { mock *Mockmetrics } ⋮---- // NewMockmetrics creates a new mock instance. func NewMockmetrics(ctrl *gomock.Controller) *Mockmetrics ⋮---- // ObserveAppAggregateDuration mocks base method. func (m *Mockmetrics) ObserveAppAggregateDuration(d time.Duration) ⋮---- // ObserveAppAggregateDuration indicates an expected call of ObserveAppAggregateDuration. ⋮---- // ObserveOnlyAggregateDuration mocks base method. func (m *Mockmetrics) ObserveOnlyAggregateDuration(d time.Duration) ⋮---- // ObserveOnlyAggregateDuration indicates an expected call of ObserveOnlyAggregateDuration. ⋮---- // Mockaggregator is a mock of aggregator interface. type Mockaggregator struct { ctrl *gomock.Controller recorder *MockaggregatorMockRecorder isgomock struct{} ⋮---- // MockaggregatorMockRecorder is the mock recorder for Mockaggregator. type MockaggregatorMockRecorder struct { mock *Mockaggregator } ⋮---- // NewMockaggregator creates a new mock instance. func NewMockaggregator(ctrl *gomock.Controller) *Mockaggregator ⋮---- // Aggregate mocks base method. func (m *Mockaggregator) Aggregate(valset entity0.ValidatorSet, keyTag entity0.KeyTag, messageHash []byte, signatures []entity0.Signature) (entity0.AggregationProof, error) ⋮---- // Aggregate indicates an expected call of Aggregate. ⋮---- // MockkeyProvider is a mock of keyProvider interface. type MockkeyProvider struct { ctrl *gomock.Controller recorder *MockkeyProviderMockRecorder isgomock struct{} ⋮---- // MockkeyProviderMockRecorder is the mock recorder for MockkeyProvider. type MockkeyProviderMockRecorder struct { mock *MockkeyProvider } ⋮---- // NewMockkeyProvider creates a new mock instance. func NewMockkeyProvider(ctrl *gomock.Controller) *MockkeyProvider ⋮---- // GetOnchainKeyFromCache mocks base method. func (m *MockkeyProvider) GetOnchainKeyFromCache(keyTag entity0.KeyTag) (entity0.CompactPublicKey, error) ⋮---- // GetOnchainKeyFromCache indicates an expected call of GetOnchainKeyFromCache. ⋮---- // GetPrivateKey mocks base method. func (m *MockkeyProvider) GetPrivateKey(keyTag entity0.KeyTag) (crypto.PrivateKey, error) ⋮---- // GetPrivateKey indicates an expected call of GetPrivateKey. ```` ## File: internal/usecase/aggregator-app/aggregator_app_test.go ````go package aggregator_app ⋮---- import ( "context" "fmt" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/samber/lo" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/internal/entity" aggregationPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy" "github.com/symbioticfi/relay/internal/usecase/aggregator-app/mocks" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "fmt" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/samber/lo" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/internal/entity" aggregationPolicy "github.com/symbioticfi/relay/internal/usecase/aggregation-policy" "github.com/symbioticfi/relay/internal/usecase/aggregator-app/mocks" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- type testSetup struct { ctrl *gomock.Controller mockRepo *mocks.Mockrepository mockP2PClient *mocks.Mockp2pClient mockAggregator *mocks.Mockaggregator mockMetrics *mocks.Mockmetrics app *AggregatorApp privateKey crypto.PrivateKey } ⋮---- func newTestSetup(t *testing.T, policyType symbiotic.AggregationPolicyType, maxUnsigners uint64) *testSetup ⋮---- func createTestSignatureExtended(t *testing.T, pk crypto.PrivateKey) symbiotic.Signature ⋮---- // Unified test data structure that keeps ValidatorSet and SignatureMap in sync type testData struct { ValidatorSet symbiotic.ValidatorSet SignatureMap entity.SignatureMap } ⋮---- // Create unified test data with a single ValidatorSet used consistently func createTestData(requestID common.Hash, epoch symbiotic.Epoch, totalValidators, signers int, key crypto.PrivateKey) testData ⋮---- // Create validators ⋮---- VotingPower: symbiotic.ToVotingPower(big.NewInt(100)), // Each validator has 100 voting power ⋮---- // Create the unified ValidatorSet ⋮---- QuorumThreshold: symbiotic.ToVotingPower(big.NewInt(670)), // Need 670 voting power for quorum ⋮---- // Create SignatureMap using the same ValidatorSet ⋮---- // Add signers (first 'signers' number of validators) ⋮---- votingPower := validatorSet.Validators[i].VotingPower // Use actual voting power from validator ⋮---- // Convenience function for common test scenarios func createTestDataWithQuorum(requestID common.Hash, epoch symbiotic.Epoch, thresholdReached bool, key crypto.PrivateKey) testData ⋮---- // 8 signers * 100 voting power = 800 > 670 threshold ⋮---- // 6 signers * 100 voting power = 600 < 670 threshold ⋮---- // Setup mocks for successful aggregation using unified test data func setupSuccessfulAggregationMocks(setup *testSetup, msg symbiotic.Signature, testData testData) ⋮---- var signatures []symbiotic.Signature ⋮---- // Use the unified test data ⋮---- // LOW LATENCY POLICY TESTS ⋮---- func TestHandleSignatureGeneratedMessage_LowLatencyPolicy_QuorumNotReached(t *testing.T) ⋮---- // Setup mocks for quorum NOT reached case ⋮---- // Execute ⋮---- // Verify - should return nil (no error) when quorum not reached, no aggregation ⋮---- func TestHandleSignatureGeneratedMessage_LowLatencyPolicy_QuorumReached(t *testing.T) ⋮---- // Setup mocks for quorum reached case - LowLatency should aggregate immediately ⋮---- // Verify - should successfully aggregate when quorum reached ⋮---- // LOW COST POLICY TESTS ⋮---- func TestHandleSignatureGeneratedMessage_LowCostPolicy_QuorumNotReached(t *testing.T) ⋮---- func TestHandleSignatureGeneratedMessage_LowCostPolicy_QuorumReached_TooManyUnsigners(t *testing.T) ⋮---- setup := newTestSetup(t, symbiotic.AggregationPolicyLowCost, 2) // Allow max 2 unsigners ⋮---- // Setup: 10 total validators, 7 signers = 3 unsigners (exceeds maxUnsigners=2) ⋮---- // Verify - should not aggregate due to too many unsigners ⋮---- func TestHandleSignatureGeneratedMessage_LowCostPolicy_QuorumReached_AcceptableUnsigners(t *testing.T) ⋮---- setup := newTestSetup(t, symbiotic.AggregationPolicyLowCost, 3) // Allow max 3 unsigners ⋮---- // Setup: 10 total validators, 8 signers = 2 unsigners (within maxUnsigners=3) ⋮---- // Verify - should successfully aggregate when unsigners within limit ⋮---- func TestHandleSignatureGeneratedMessage_LowCostPolicy_QuorumReached_ExactUnsignersLimit(t *testing.T) ⋮---- // Setup: 10 total validators, 7 signers = 3 unsigners (exactly maxUnsigners=3) ⋮---- // Verify - should successfully aggregate when exactly at unsigners limit ⋮---- func TestHandleSignatureGeneratedMessage_LowCostPolicy_AllValidatorsSigned(t *testing.T) ⋮---- setup := newTestSetup(t, symbiotic.AggregationPolicyLowCost, 1) // Allow max 1 unsigner ⋮---- // Setup: 10 total validators, 10 signers = 0 unsigners (well within limit) ⋮---- // Verify - should successfully aggregate when all validators signed ⋮---- // EDGE CASES ⋮---- func TestHandleSignatureGeneratedMessage_LowCostPolicy_ZeroMaxUnsigners(t *testing.T) ⋮---- setup := newTestSetup(t, symbiotic.AggregationPolicyLowCost, 0) // Allow 0 unsigners ⋮---- // Setup: 5 total validators, 4 signers = 1 unsigner (exceeds maxUnsigners=0) ⋮---- // Verify - should not aggregate due to any unsigners when maxUnsigners=0 ⋮---- func TestHandleSignatureGeneratedMessage_LowCostPolicy_HighMaxUnsigners(t *testing.T) ⋮---- setup := newTestSetup(t, symbiotic.AggregationPolicyLowCost, 100) // Allow 100 unsigners ⋮---- // Setup: 10 total validators, 7 signers = 3 unsigners (well within limit) // 7 signers = 7*100 = 700 > 670 for quorum ⋮---- // Verify - should successfully aggregate with high unsigners limit ⋮---- // Test helper function to verify SignatureMap functionality with unified test data func TestSignatureMapFunctionality(t *testing.T) ⋮---- // Test with unified creation ⋮---- testingData := createTestData(requestID, 1, 5, 0, pk) // 5 validators, 0 signers initially ⋮---- // Initially no validators signed ⋮---- // Add 3 validators using their actual voting power from the validator set ⋮---- require.False(t, signatureMap.ThresholdReached(validatorSet.QuorumThreshold)) // 300 < 670 ⋮---- // Add 4 more validators (5 total = 5 * 100 = 500 voting power) ⋮---- require.False(t, signatureMap.ThresholdReached(validatorSet.QuorumThreshold)) // 500 < 670 require.True(t, signatureMap.ThresholdReached(symbiotic.ToVotingPower(big.NewInt(400)))) // 500 >= 400 ⋮---- // Verify that the SignatureMap and ValidatorSet are consistent ```` ## File: internal/usecase/aggregator-app/aggregator_app.go ````go package aggregator_app ⋮---- import ( "context" "log/slog" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" aggregationPolicyTypes "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/types" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "log/slog" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/internal/entity" aggregationPolicyTypes "github.com/symbioticfi/relay/internal/usecase/aggregation-policy/types" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- //go:generate mockgen -source=aggregator_app.go -destination=mocks/aggregator_app.go -package=mocks type repository interface { GetValidatorSetByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) GetAggregationProof(ctx context.Context, requestID common.Hash) (symbiotic.AggregationProof, error) GetSignatureRequest(_ context.Context, requestID common.Hash) (symbiotic.SignatureRequest, error) GetAllSignatures(ctx context.Context, requestID common.Hash) ([]symbiotic.Signature, error) GetConfigByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) GetSignatureMap(ctx context.Context, requestID common.Hash) (entity.SignatureMap, error) } ⋮---- type p2pClient interface { BroadcastSignatureAggregatedMessage(ctx context.Context, proof symbiotic.AggregationProof) error } ⋮---- type metrics interface { ObserveOnlyAggregateDuration(d time.Duration) ObserveAppAggregateDuration(d time.Duration) } ⋮---- type aggregator interface { Aggregate(valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, messageHash []byte, signatures []symbiotic.Signature) (symbiotic.AggregationProof, error) } ⋮---- type keyProvider interface { GetPrivateKey(keyTag symbiotic.KeyTag) (crypto.PrivateKey, error) GetOnchainKeyFromCache(keyTag symbiotic.KeyTag) (symbiotic.CompactPublicKey, error) } ⋮---- type Config struct { Repo repository `validate:"required"` P2PClient p2pClient `validate:"required"` Aggregator aggregator `validate:"required"` Metrics metrics `validate:"required"` AggregationPolicy aggregatorPolicy `validate:"required"` KeyProvider keyProvider `validate:"required"` ForceAggregator bool } ⋮---- func (c Config) Validate() error ⋮---- type AggregatorApp struct { cfg Config } ⋮---- func NewAggregatorApp(cfg Config) (*AggregatorApp, error) ⋮---- func (s *AggregatorApp) HandleSignatureProcessedMessage(ctx context.Context, msg symbiotic.Signature) error ⋮---- // Get validator set for quorum threshold checks // todo load only valset header when totalVotingPower is added to it ⋮---- func (s *AggregatorApp) GetAggregationStatus(ctx context.Context, requestID common.Hash) (symbiotic.AggregationStatus, error) ⋮---- // Get validator set for quorum threshold checks and aggregation ⋮---- func extractPublicKeys(signatures []symbiotic.Signature) []symbiotic.CompactPublicKey ```` ## File: internal/usecase/api-server/mocks/app_mock.go ````go // Code generated by MockGen. DO NOT EDIT. // Source: app.go // // Generated by this command: ⋮---- // mockgen -source=app.go -destination=mocks/app_mock.go -package=mocks ⋮---- // Package mocks is a generated GoMock package. package mocks ⋮---- import ( context "context" reflect "reflect" common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/internal/entity" entity0 "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ) ⋮---- context "context" reflect "reflect" ⋮---- common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/internal/entity" entity0 "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ⋮---- // Mocksigner is a mock of signer interface. type Mocksigner struct { ctrl *gomock.Controller recorder *MocksignerMockRecorder isgomock struct{} ⋮---- // MocksignerMockRecorder is the mock recorder for Mocksigner. type MocksignerMockRecorder struct { mock *Mocksigner } ⋮---- // NewMocksigner creates a new mock instance. func NewMocksigner(ctrl *gomock.Controller) *Mocksigner ⋮---- // EXPECT returns an object that allows the caller to indicate expected use. func (m *Mocksigner) EXPECT() *MocksignerMockRecorder ⋮---- // RequestSignature mocks base method. func (m *Mocksigner) RequestSignature(ctx context.Context, req entity0.SignatureRequest) (common.Hash, error) ⋮---- // RequestSignature indicates an expected call of RequestSignature. ⋮---- // Mockrepo is a mock of repo interface. type Mockrepo struct { ctrl *gomock.Controller recorder *MockrepoMockRecorder isgomock struct{} ⋮---- // MockrepoMockRecorder is the mock recorder for Mockrepo. type MockrepoMockRecorder struct { mock *Mockrepo } ⋮---- // NewMockrepo creates a new mock instance. func NewMockrepo(ctrl *gomock.Controller) *Mockrepo ⋮---- // GetAggregationProof mocks base method. func (m *Mockrepo) GetAggregationProof(ctx context.Context, requestID common.Hash) (entity0.AggregationProof, error) ⋮---- // GetAggregationProof indicates an expected call of GetAggregationProof. ⋮---- // GetAggregationProofsByEpoch mocks base method. func (m *Mockrepo) GetAggregationProofsByEpoch(ctx context.Context, epoch entity0.Epoch) ([]entity0.AggregationProof, error) ⋮---- // GetAggregationProofsByEpoch indicates an expected call of GetAggregationProofsByEpoch. ⋮---- // GetAggregationProofsStartingFromEpoch mocks base method. func (m *Mockrepo) GetAggregationProofsStartingFromEpoch(ctx context.Context, epoch entity0.Epoch) ([]entity0.AggregationProof, error) ⋮---- // GetAggregationProofsStartingFromEpoch indicates an expected call of GetAggregationProofsStartingFromEpoch. ⋮---- // GetAllSignatures mocks base method. func (m *Mockrepo) GetAllSignatures(ctx context.Context, requestID common.Hash) ([]entity0.Signature, error) ⋮---- // GetAllSignatures indicates an expected call of GetAllSignatures. ⋮---- // GetLatestValidatorSetEpoch mocks base method. func (m *Mockrepo) GetLatestValidatorSetEpoch(arg0 context.Context) (entity0.Epoch, error) ⋮---- // GetLatestValidatorSetEpoch indicates an expected call of GetLatestValidatorSetEpoch. ⋮---- // GetLatestValidatorSetHeader mocks base method. func (m *Mockrepo) GetLatestValidatorSetHeader(arg0 context.Context) (entity0.ValidatorSetHeader, error) ⋮---- // GetLatestValidatorSetHeader indicates an expected call of GetLatestValidatorSetHeader. ⋮---- // GetSignatureRequest mocks base method. func (m *Mockrepo) GetSignatureRequest(ctx context.Context, requestID common.Hash) (entity0.SignatureRequest, error) ⋮---- // GetSignatureRequest indicates an expected call of GetSignatureRequest. ⋮---- // GetSignatureRequestIDsByEpoch mocks base method. func (m *Mockrepo) GetSignatureRequestIDsByEpoch(ctx context.Context, epoch entity0.Epoch) ([]common.Hash, error) ⋮---- // GetSignatureRequestIDsByEpoch indicates an expected call of GetSignatureRequestIDsByEpoch. ⋮---- // GetSignatureRequestsWithIDByEpoch mocks base method. func (m *Mockrepo) GetSignatureRequestsWithIDByEpoch(ctx context.Context, epoch entity0.Epoch) ([]entity.SignatureRequestWithID, error) ⋮---- // GetSignatureRequestsWithIDByEpoch indicates an expected call of GetSignatureRequestsWithIDByEpoch. ⋮---- // GetSignaturesByEpoch mocks base method. func (m *Mockrepo) GetSignaturesByEpoch(ctx context.Context, epoch entity0.Epoch) ([]entity0.Signature, error) ⋮---- // GetSignaturesByEpoch indicates an expected call of GetSignaturesByEpoch. ⋮---- // GetSignaturesStartingFromEpoch mocks base method. func (m *Mockrepo) GetSignaturesStartingFromEpoch(ctx context.Context, epoch entity0.Epoch) ([]entity0.Signature, error) ⋮---- // GetSignaturesStartingFromEpoch indicates an expected call of GetSignaturesStartingFromEpoch. ⋮---- // GetValidatorSetByEpoch mocks base method. func (m *Mockrepo) GetValidatorSetByEpoch(arg0 context.Context, epoch entity0.Epoch) (entity0.ValidatorSet, error) ⋮---- // GetValidatorSetByEpoch indicates an expected call of GetValidatorSetByEpoch. ⋮---- // GetValidatorSetMetadata mocks base method. func (m *Mockrepo) GetValidatorSetMetadata(ctx context.Context, epoch entity0.Epoch) (entity0.ValidatorSetMetadata, error) ⋮---- // GetValidatorSetMetadata indicates an expected call of GetValidatorSetMetadata. ⋮---- // GetValidatorSetsStartingFromEpoch mocks base method. func (m *Mockrepo) GetValidatorSetsStartingFromEpoch(ctx context.Context, epoch entity0.Epoch) ([]entity0.ValidatorSet, error) ⋮---- // GetValidatorSetsStartingFromEpoch indicates an expected call of GetValidatorSetsStartingFromEpoch. ⋮---- // MockevmClient is a mock of evmClient interface. type MockevmClient struct { ctrl *gomock.Controller recorder *MockevmClientMockRecorder isgomock struct{} ⋮---- // MockevmClientMockRecorder is the mock recorder for MockevmClient. type MockevmClientMockRecorder struct { mock *MockevmClient } ⋮---- // NewMockevmClient creates a new mock instance. func NewMockevmClient(ctrl *gomock.Controller) *MockevmClient ⋮---- // GetConfig mocks base method. func (m *MockevmClient) GetConfig(ctx context.Context, timestamp entity0.Timestamp, epoch entity0.Epoch) (entity0.NetworkConfig, error) ⋮---- // GetConfig indicates an expected call of GetConfig. ⋮---- // GetCurrentEpoch mocks base method. func (m *MockevmClient) GetCurrentEpoch(ctx context.Context) (entity0.Epoch, error) ⋮---- // GetCurrentEpoch indicates an expected call of GetCurrentEpoch. ⋮---- // GetEpochStart mocks base method. func (m *MockevmClient) GetEpochStart(ctx context.Context, epoch entity0.Epoch) (entity0.Timestamp, error) ⋮---- // GetEpochStart indicates an expected call of GetEpochStart. ⋮---- // GetLastCommittedHeaderEpoch mocks base method. func (m *MockevmClient) GetLastCommittedHeaderEpoch(ctx context.Context, addr entity0.CrossChainAddress, opts ...entity0.EVMOption) (entity0.Epoch, error) ⋮---- // GetLastCommittedHeaderEpoch indicates an expected call of GetLastCommittedHeaderEpoch. ⋮---- // Mockaggregator is a mock of aggregator interface. type Mockaggregator struct { ctrl *gomock.Controller recorder *MockaggregatorMockRecorder isgomock struct{} ⋮---- // MockaggregatorMockRecorder is the mock recorder for Mockaggregator. type MockaggregatorMockRecorder struct { mock *Mockaggregator } ⋮---- // NewMockaggregator creates a new mock instance. func NewMockaggregator(ctrl *gomock.Controller) *Mockaggregator ⋮---- // GetAggregationStatus mocks base method. func (m *Mockaggregator) GetAggregationStatus(ctx context.Context, requestID common.Hash) (entity0.AggregationStatus, error) ⋮---- // GetAggregationStatus indicates an expected call of GetAggregationStatus. ⋮---- // Mockderiver is a mock of deriver interface. type Mockderiver struct { ctrl *gomock.Controller recorder *MockderiverMockRecorder isgomock struct{} ⋮---- // MockderiverMockRecorder is the mock recorder for Mockderiver. type MockderiverMockRecorder struct { mock *Mockderiver } ⋮---- // NewMockderiver creates a new mock instance. func NewMockderiver(ctrl *gomock.Controller) *Mockderiver ⋮---- // GetValidatorSet mocks base method. func (m *Mockderiver) GetValidatorSet(ctx context.Context, epoch entity0.Epoch, config entity0.NetworkConfig) (entity0.ValidatorSet, error) ⋮---- // GetValidatorSet indicates an expected call of GetValidatorSet. ⋮---- // MockkeyProvider is a mock of keyProvider interface. type MockkeyProvider struct { ctrl *gomock.Controller recorder *MockkeyProviderMockRecorder isgomock struct{} ⋮---- // MockkeyProviderMockRecorder is the mock recorder for MockkeyProvider. type MockkeyProviderMockRecorder struct { mock *MockkeyProvider } ⋮---- // NewMockkeyProvider creates a new mock instance. func NewMockkeyProvider(ctrl *gomock.Controller) *MockkeyProvider ⋮---- // GetOnchainKeyFromCache mocks base method. func (m *MockkeyProvider) GetOnchainKeyFromCache(keyTag entity0.KeyTag) (entity0.CompactPublicKey, error) ⋮---- // GetOnchainKeyFromCache indicates an expected call of GetOnchainKeyFromCache. ```` ## File: internal/usecase/api-server/app.go ````go package api_server ⋮---- import ( "context" "log/slog" "net" "net/http" "net/http/pprof" "strings" "time" "github.com/symbioticfi/relay/internal/usecase/broadcaster" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/prometheus/client_golang/prometheus/promhttp" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" "google.golang.org/grpc" "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/reflection" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/server" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" "net" "net/http" "net/http/pprof" "strings" "time" ⋮---- "github.com/symbioticfi/relay/internal/usecase/broadcaster" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/prometheus/client_golang/prometheus/promhttp" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" "google.golang.org/grpc" "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/reflection" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/metrics" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/server" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- //go:generate mockgen -source=app.go -destination=mocks/app_mock.go -package=mocks type signer interface { RequestSignature(ctx context.Context, req symbiotic.SignatureRequest) (common.Hash, error) } ⋮---- type repo interface { GetAggregationProof(ctx context.Context, requestID common.Hash) (symbiotic.AggregationProof, error) GetValidatorSetByEpoch(_ context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) GetAllSignatures(ctx context.Context, requestID common.Hash) ([]symbiotic.Signature, error) GetSignatureRequest(ctx context.Context, requestID common.Hash) (symbiotic.SignatureRequest, error) GetLatestValidatorSetHeader(_ context.Context) (symbiotic.ValidatorSetHeader, error) GetLatestValidatorSetEpoch(_ context.Context) (symbiotic.Epoch, error) GetValidatorSetMetadata(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSetMetadata, error) GetSignaturesStartingFromEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.Signature, error) GetSignaturesByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.Signature, error) GetSignatureRequestIDsByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]common.Hash, error) GetSignatureRequestsWithIDByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]entity.SignatureRequestWithID, error) GetAggregationProofsStartingFromEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.AggregationProof, error) GetAggregationProofsByEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.AggregationProof, error) GetValidatorSetsStartingFromEpoch(ctx context.Context, epoch symbiotic.Epoch) ([]symbiotic.ValidatorSet, error) } type evmClient interface { GetCurrentEpoch(ctx context.Context) (symbiotic.Epoch, error) GetEpochStart(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.Timestamp, error) GetConfig(ctx context.Context, timestamp symbiotic.Timestamp, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) GetLastCommittedHeaderEpoch(ctx context.Context, addr symbiotic.CrossChainAddress, opts ...symbiotic.EVMOption) (_ symbiotic.Epoch, err error) } ⋮---- type aggregator interface { GetAggregationStatus(ctx context.Context, requestID common.Hash) (symbiotic.AggregationStatus, error) } ⋮---- type deriver interface { GetValidatorSet(ctx context.Context, epoch symbiotic.Epoch, config symbiotic.NetworkConfig) (symbiotic.ValidatorSet, error) } ⋮---- type keyProvider interface { GetOnchainKeyFromCache(keyTag symbiotic.KeyTag) (symbiotic.CompactPublicKey, error) } ⋮---- type Config struct { Address string `validate:"required"` ReadHeaderTimeout time.Duration `validate:"required,gt=0"` ShutdownTimeout time.Duration `validate:"required,gt=0"` Signer signer `validate:"required"` Repo repo `validate:"required"` EvmClient evmClient `validate:"required"` Deriver deriver `validate:"required"` KeyProvider keyProvider `validate:"required"` Aggregator aggregator ServeMetrics bool ServePprof bool ServeHTTPGateway bool Metrics *metrics.Metrics `validate:"required"` VerboseLogging bool MaxAllowedStreamsCount int `validate:"required,gt=0"` } ⋮---- func (c Config) Validate() error ⋮---- // grpcHandler implements the gRPC service interface type grpcHandler struct { apiv1.SymbioticAPIServiceServer cfg Config proofsHub *broadcaster.Hub[symbiotic.AggregationProof] signatureHub *broadcaster.Hub[symbiotic.Signature] validatorSetsHub *broadcaster.Hub[symbiotic.ValidatorSet] } type SymbioticServer struct { grpcServer *grpc.Server httpServer *http.Server listener net.Listener cfg Config handler *grpcHandler startGatewayFunc func() error } ⋮---- func NewSymbioticServer(ctx context.Context, cfg Config) (*SymbioticServer, error) ⋮---- // Create listener ⋮---- // Create gRPC server with interceptors ⋮---- //nolint:contextcheck // the context comes from th stream ⋮---- // Create and register the handler ⋮---- // Register health service ⋮---- // Register reflection service for development ⋮---- // Create HTTP server for documentation with panic recovery ⋮---- // Wrap the entire mux with panic recovery ⋮---- // Register HTTP gateway if enabled var startGatewayFunc func() error ⋮---- // Root redirect to docs ⋮---- // Health check endpoint ⋮---- // Debug pprof endpoints if enabled ⋮---- // Serve API documentation ⋮---- // Serve metrics endpoint if enabled ⋮---- // Create HTTP/2 server that can handle both HTTP and gRPC ⋮---- // createMuxHandler creates a handler that multiplexes between gRPC and HTTP func createMuxHandler(grpcServer *grpc.Server, httpHandler http.Handler) http.Handler ⋮---- // Check if this is a gRPC request ⋮---- // Handle gRPC request ⋮---- // Handle as HTTP request (documentation, health checks, etc.) ⋮---- func (a *SymbioticServer) Start(ctx context.Context) error ⋮---- // Start serving in a goroutine ⋮---- // Initialize HTTP gateway connection after server starts ⋮---- // Retry connection to gRPC server with exponential backoff const maxRetries = 5 var lastErr error ⋮---- // Wait for context cancellation or server error ⋮---- // Graceful shutdown with timeout ⋮---- // Shutdown HTTP server //nolint:contextcheck // we need to use background context here as the original context is already cancelled ⋮---- // Force stop gRPC server ⋮---- // Graceful stop for gRPC server ⋮---- func (a *SymbioticServer) HandleProofAggregated() func(context.Context, symbiotic.AggregationProof) error ⋮---- func (a *SymbioticServer) HandleSignatureProcessed() func(context.Context, symbiotic.Signature) error ⋮---- func (a *SymbioticServer) HandleValidatorSet() func(context.Context, symbiotic.ValidatorSet) error ```` ## File: internal/usecase/api-server/get_aggregation_proof_v1_test.go ````go package api_server ⋮---- import ( "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetAggregationProof_Success_ReturnsProof(t *testing.T) ⋮---- func TestGetAggregationProof_NotFound_ReturnsNotFoundError(t *testing.T) ⋮---- func TestGetAggregationProof_RepositoryError_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/get_aggregation_proof_v1.go ````go package api_server ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- // GetAggregationProof handles the gRPC GetAggregationProof request func (h *grpcHandler) GetAggregationProof(ctx context.Context, req *apiv1.GetAggregationProofRequest) (*apiv1.GetAggregationProofResponse, error) ⋮---- func convertAggregationProofToPB(proof symbiotic.AggregationProof) *apiv1.AggregationProof ```` ## File: internal/usecase/api-server/get_aggregation_proofs_by_epoch_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetAggregationProofsByEpoch_Success(t *testing.T) ⋮---- func TestGetAggregationProofsByEpoch_EmptyResult(t *testing.T) ⋮---- func TestGetAggregationProofsByEpoch_RepositoryError(t *testing.T) ```` ## File: internal/usecase/api-server/get_aggregation_proofs_by_epoch_v1.go ````go package api_server ⋮---- import ( "context" "github.com/go-errors/errors" "github.com/samber/lo" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" "github.com/samber/lo" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetAggregationProofsByEpoch handles the gRPC GetAggregationProofsByEpoch request func (h *grpcHandler) GetAggregationProofsByEpoch(ctx context.Context, req *apiv1.GetAggregationProofsByEpochRequest) (*apiv1.GetAggregationProofsByEpochResponse, error) ```` ## File: internal/usecase/api-server/get_aggregation_status_v1_test.go ````go package api_server ⋮---- import ( "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetAggregationStatus_Success_ReturnsStatusWithSortedOperators(t *testing.T) ⋮---- func TestGetAggregationStatus_NoAggregator_ReturnsError(t *testing.T) ⋮---- func TestGetAggregationStatus_NotFound_ReturnsNotFoundError(t *testing.T) ⋮---- func TestGetAggregationStatus_AggregatorError_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/get_aggregation_status_v1.go ````go package api_server ⋮---- import ( "context" "sort" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "sort" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetAggregationStatus handles the gRPC GetAggregationStatus request func (h *grpcHandler) GetAggregationStatus(ctx context.Context, req *apiv1.GetAggregationStatusRequest) (*apiv1.GetAggregationStatusResponse, error) ```` ## File: internal/usecase/api-server/get_current_epoch_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetCurrentEpoch_Success_ReturnsEpochAndStartTime(t *testing.T) ⋮---- captureTimestamp := symbiotic.Timestamp(1640995200) // 2022-01-01 00:00:00 UTC ⋮---- func TestGetCurrentEpoch_NotFound_ReturnsNotFoundError(t *testing.T) ⋮---- func TestGetCurrentEpoch_RepositoryError_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/get_current_epoch_v1.go ````go package api_server ⋮---- import ( "context" "time" "github.com/go-errors/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" ) ⋮---- "context" "time" ⋮---- "github.com/go-errors/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" ⋮---- // GetCurrentEpoch handles the gRPC GetCurrentEpoch request func (h *grpcHandler) GetCurrentEpoch(ctx context.Context, req *apiv1.GetCurrentEpochRequest) (*apiv1.GetCurrentEpochResponse, error) ```` ## File: internal/usecase/api-server/get_last_all_committed_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" deriverMocks "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" deriverMocks "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ⋮---- func TestGetLastAllCommitted_Success_ReturnsAllChainsWithMinimum(t *testing.T) ⋮---- func TestGetLastAllCommitted_GetConfigFails_ReturnsError(t *testing.T) ⋮---- func TestGetLastAllCommitted_GetLastCommittedEpochFails_ReturnsError(t *testing.T) ⋮---- func TestGetLastAllCommitted_GetEpochStartFails_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/get_last_all_committed_v1.go ````go package api_server ⋮---- import ( "context" "time" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" "google.golang.org/protobuf/types/known/timestamppb" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "time" ⋮---- "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" "google.golang.org/protobuf/types/known/timestamppb" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetLastAllCommitted handles the gRPC GetLastAllCommitted request func (h *grpcHandler) GetLastAllCommitted(ctx context.Context, _ *apiv1.GetLastAllCommittedRequest) (*apiv1.GetLastAllCommittedResponse, error) ⋮---- var minLastCommited *apiv1.ChainEpochInfo ```` ## File: internal/usecase/api-server/get_last_committed_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" deriverMocks "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" deriverMocks "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ⋮---- func TestGetLastCommitted_Success_ReturnsLastCommittedEpoch(t *testing.T) ⋮---- func TestGetLastCommitted_ZeroChainID_ReturnsInvalidArgumentError(t *testing.T) ⋮---- func TestGetLastCommitted_ChainNotFound_ReturnsNotFoundError(t *testing.T) ⋮---- func TestGetLastCommitted_GetLastCommittedHeaderEpochFails_ReturnsError(t *testing.T) ⋮---- func TestGetLastCommitted_GetEpochStartFails_ReturnsError(t *testing.T) ⋮---- func TestGetLastCommitted_GetConfigFails_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/get_last_committed_v1.go ````go package api_server ⋮---- import ( "context" "time" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "time" ⋮---- "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetLastCommitted handles the gRPC GetLastCommitted request func (h *grpcHandler) GetLastCommitted(ctx context.Context, req *apiv1.GetLastCommittedRequest) (*apiv1.GetLastCommittedResponse, error) ⋮---- var settlementChain *symbiotic.CrossChainAddress ⋮---- // TODO: Get the epoch start time ```` ## File: internal/usecase/api-server/get_local_validator_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetLocalValidator_Success(t *testing.T) ⋮---- func TestGetLocalValidator_UseCurrentEpoch(t *testing.T) ⋮---- func TestGetLocalValidator_ErrorWhenEpochFromFuture(t *testing.T) ⋮---- func TestGetLocalValidator_ErrorWhenKeyProviderFails(t *testing.T) ⋮---- func TestGetLocalValidator_ErrorWhenValidatorNotFound(t *testing.T) ⋮---- func TestGetLocalValidator_ErrorWhenRepositoryFails(t *testing.T) ```` ## File: internal/usecase/api-server/get_local_validator_v1.go ````go package api_server ⋮---- import ( "context" "github.com/go-errors/errors" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- // GetLocalValidator handles the gRPC GetLocalValidator request func (h *grpcHandler) GetLocalValidator(ctx context.Context, req *apiv1.GetLocalValidatorRequest) (*apiv1.GetLocalValidatorResponse, error) ```` ## File: internal/usecase/api-server/get_signature_request_ids_by_epoch_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetSignatureRequestIDsByEpoch_Success(t *testing.T) ⋮---- func TestGetSignatureRequestIDsByEpoch_EmptyResult(t *testing.T) ⋮---- func TestGetSignatureRequestIDsByEpoch_RepositoryError(t *testing.T) ```` ## File: internal/usecase/api-server/get_signature_request_ids_by_epoch_v1.go ````go package api_server ⋮---- import ( "context" "github.com/samber/lo" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/samber/lo" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetSignatureRequestIDsByEpoch handles the gRPC GetSignatureRequestIDsByEpoch request func (h *grpcHandler) GetSignatureRequestIDsByEpoch(ctx context.Context, req *apiv1.GetSignatureRequestIDsByEpochRequest) (*apiv1.GetSignatureRequestIDsByEpochResponse, error) ```` ## File: internal/usecase/api-server/get_signature_request_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetSignatureRequest_Success(t *testing.T) ⋮---- // Verify request ID is included ⋮---- func TestGetSignatureRequest_NotFound(t *testing.T) ⋮---- // Check that it's a NotFound error ⋮---- func TestGetSignatureRequest_RepositoryError(t *testing.T) ```` ## File: internal/usecase/api-server/get_signature_request_v1.go ````go package api_server ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" ⋮---- // GetSignatureRequest handles the gRPC GetSignatureRequest request func (h *grpcHandler) GetSignatureRequest(ctx context.Context, req *apiv1.GetSignatureRequestRequest) (*apiv1.GetSignatureRequestResponse, error) ```` ## File: internal/usecase/api-server/get_signature_requests_by_epoch_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetSignatureRequestsByEpoch_Success(t *testing.T) ⋮---- // Verify first request ⋮---- // Verify second request ⋮---- func TestGetSignatureRequestsByEpoch_EmptyResult(t *testing.T) ⋮---- func TestGetSignatureRequestsByEpoch_RepositoryError(t *testing.T) ```` ## File: internal/usecase/api-server/get_signature_requests_by_epoch_v1.go ````go package api_server ⋮---- import ( "context" "github.com/go-errors/errors" "github.com/samber/lo" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" "github.com/samber/lo" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetSignatureRequestsByEpoch handles the gRPC GetSignatureRequestsByEpoch request func (h *grpcHandler) GetSignatureRequestsByEpoch(ctx context.Context, req *apiv1.GetSignatureRequestsByEpochRequest) (*apiv1.GetSignatureRequestsByEpochResponse, error) ```` ## File: internal/usecase/api-server/get_signature_v1.go ````go package api_server ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetSignatures handles the gRPC GetSignatures request func (h *grpcHandler) GetSignatures(ctx context.Context, req *apiv1.GetSignaturesRequest) (*apiv1.GetSignaturesResponse, error) ⋮---- func convertSignaturesToPB(signatures []symbiotic.Signature) []*apiv1.Signature ⋮---- func convertSignatureToPB(sig symbiotic.Signature) *apiv1.Signature ```` ## File: internal/usecase/api-server/get_signatures_by_epoch_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func TestGetSignaturesByEpoch_Success(t *testing.T) ⋮---- func TestGetSignaturesByEpoch_EmptyResult(t *testing.T) ⋮---- func TestGetSignaturesByEpoch_RepositoryError(t *testing.T) ```` ## File: internal/usecase/api-server/get_signatures_by_epoch_v1.go ````go package api_server ⋮---- import ( "context" "github.com/go-errors/errors" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetSignaturesByEpoch handles the gRPC GetSignaturesByEpoch request func (h *grpcHandler) GetSignaturesByEpoch(ctx context.Context, req *apiv1.GetSignaturesByEpochRequest) (*apiv1.GetSignaturesByEpochResponse, error) ```` ## File: internal/usecase/api-server/get_signatures_v1_test.go ````go package api_server ⋮---- import ( "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func TestGetSignatures_Success_ReturnsAllSignatures(t *testing.T) ⋮---- func TestGetSignatures_NotFound_ReturnsNotFoundError(t *testing.T) ⋮---- func TestGetSignatures_RepositoryError_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/get_validator_by_address_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetValidatorByAddress_ValidatorFoundInRepo(t *testing.T) ⋮---- // Create test data ⋮---- expectedValidator := validatorSet.Validators[0] // First validator has address 0x123 ⋮---- // Setup mocks - validator set found in repository ⋮---- // Execute the method under test ⋮---- // Assertions ⋮---- func TestGetValidatorByAddress_ValidatorSetNotInRepo_DerivedFail(t *testing.T) ⋮---- // Setup mocks - validator set not in repository, needs to be derived ⋮---- func TestGetValidatorByAddress_UseCurrentEpoch_WhenNoEpochSpecified(t *testing.T) ⋮---- // Setup mocks - no epoch specified, should use current epoch ⋮---- // Execute the method under test - no epoch specified ⋮---- func TestGetValidatorByAddress_ErrorWhenEpochFromFuture(t *testing.T) ⋮---- // Setup mocks ⋮---- func TestGetValidatorByAddress_ErrorWhenInvalidAddress(t *testing.T) ⋮---- func TestGetValidatorByAddress_ErrorWhenValidatorNotFound(t *testing.T) ⋮---- // Create test data without the requested validator ⋮---- func TestGetValidatorByAddress_ErrorWhenGetCurrentEpochFails(t *testing.T) ⋮---- func TestGetValidatorByAddress_ErrorWhenRepositoryFails(t *testing.T) ```` ## File: internal/usecase/api-server/get_validator_by_address_v1.go ````go package api_server ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetValidatorByAddress handles the gRPC GetValidatorByAddress request func (h *grpcHandler) GetValidatorByAddress(ctx context.Context, req *apiv1.GetValidatorByAddressRequest) (*apiv1.GetValidatorByAddressResponse, error) ⋮---- // epoch from future ⋮---- // parse validator address ⋮---- // get validator set for the epoch ⋮---- // find validator by address ```` ## File: internal/usecase/api-server/get_validator_by_key_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/go-errors/errors" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetValidatorByKey_Success(t *testing.T) ⋮---- func TestGetValidatorByKey_UseCurrentEpoch(t *testing.T) ⋮---- func TestGetValidatorByKey_ErrorWhenEpochFromFuture(t *testing.T) ⋮---- func TestGetValidatorByKey_ErrorWhenKeyTagIsZero(t *testing.T) ⋮---- func TestGetValidatorByKey_ErrorWhenOnChainKeyIsEmpty(t *testing.T) ⋮---- func TestGetValidatorByKey_ErrorWhenValidatorNotFound(t *testing.T) ⋮---- func TestGetValidatorByKey_ErrorWhenRepositoryFails(t *testing.T) ```` ## File: internal/usecase/api-server/get_validator_by_key_v1.go ````go package api_server ⋮---- import ( "bytes" "context" "github.com/go-errors/errors" "github.com/samber/lo" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) ⋮---- "bytes" "context" ⋮---- "github.com/go-errors/errors" "github.com/samber/lo" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- // GetValidatorByKey handles the gRPC GetValidatorByKey request func (h *grpcHandler) GetValidatorByKey(ctx context.Context, req *apiv1.GetValidatorByKeyRequest) (*apiv1.GetValidatorByKeyResponse, error) ```` ## File: internal/usecase/api-server/get_validator_set_header_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/go-errors/errors" "github.com/stretchr/testify/require" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetValidatorSetHeader_ValidatorSetFoundInRepo(t *testing.T) ⋮---- // Create test data ⋮---- expectedHeader, err := validatorSet.GetHeader() // Use the real GetHeader method ⋮---- // Setup mocks - validator set found in repository ⋮---- // Execute the method under test ⋮---- // Assertions ⋮---- func TestGetValidatorSetHeader_UseCurrentEpoch_WhenNoEpochSpecified(t *testing.T) ⋮---- // Setup mocks - no epoch specified, should use current epoch ⋮---- // Execute the method under test - no epoch specified ⋮---- func TestGetValidatorSetHeader_ErrorWhenEpochFromFuture(t *testing.T) ⋮---- // Setup mocks ⋮---- func TestGetValidatorSetHeader_ErrorWhenGetCurrentEpochFails(t *testing.T) ⋮---- func TestGetValidatorSetHeader_ErrorWhenRepositoryFails(t *testing.T) ```` ## File: internal/usecase/api-server/get_validator_set_header_v1.go ````go package api_server ⋮---- import ( "context" "time" "github.com/go-errors/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "time" ⋮---- "github.com/go-errors/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetValidatorSetHeader handles the gRPC GetValidatorSetHeader request func (h *grpcHandler) GetValidatorSetHeader(ctx context.Context, req *apiv1.GetValidatorSetHeaderRequest) (*apiv1.GetValidatorSetHeaderResponse, error) ⋮---- // epoch from future ⋮---- // get header from validator set ```` ## File: internal/usecase/api-server/get_validator_set_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetValidatorSet_WithoutEpoch_ReturnsLatestValidatorSet(t *testing.T) ⋮---- func TestGetValidatorSet_WithSpecificEpoch_ReturnsRequestedValidatorSet(t *testing.T) ⋮---- func TestGetValidatorSet_FutureEpoch_ReturnsInvalidArgumentError(t *testing.T) ⋮---- func TestGetValidatorSet_GetLatestEpochFails_ReturnsError(t *testing.T) ⋮---- func TestConvertValidatorSetStatusToPB_AllStatuses(t *testing.T) ```` ## File: internal/usecase/api-server/get_validator_set_v1.go ````go package api_server ⋮---- import ( "context" "time" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "time" ⋮---- "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetValidatorSet handles the gRPC GetValidatorSet request func (h *grpcHandler) GetValidatorSet(ctx context.Context, req *apiv1.GetValidatorSetRequest) (*apiv1.GetValidatorSetResponse, error) ⋮---- // epoch from future ⋮---- // getValidatorSetForEpoch retrieves validator set for a given epoch, either from repo or by deriving it func (h *grpcHandler) getValidatorSetForEpoch(ctx context.Context, epochRequested symbiotic.Epoch) (symbiotic.ValidatorSet, error) ⋮---- func convertValidatorSetToPB(valSet symbiotic.ValidatorSet) *apiv1.ValidatorSet ⋮---- func convertValidatorToPB(v symbiotic.Validator) *apiv1.Validator ⋮---- func convertValidatorSetStatusToPB(status symbiotic.ValidatorSetStatus) apiv1.ValidatorSetStatus ```` ## File: internal/usecase/api-server/get_validatorset_metadata_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetValidatorSetMetadata_WithoutEpoch_ReturnsLatestMetadata(t *testing.T) ⋮---- func TestGetValidatorSetMetadata_WithEpoch_ReturnsMetadataForEpoch(t *testing.T) ⋮---- func TestGetValidatorSetMetadata_NotFound_ReturnsNotFoundError(t *testing.T) ⋮---- func TestGetValidatorSetMetadata_RepositoryError_ReturnsError(t *testing.T) ⋮---- func TestGetValidatorSetMetadata_GetLatestEpochFails_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/get_validatorset_metadata_v1.go ````go package api_server ⋮---- import ( "context" "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" "github.com/samber/lo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // GetValidatorSetMetadata handles the gRPC GetValidatorSetMetadata request func (h *grpcHandler) GetValidatorSetMetadata(ctx context.Context, req *apiv1.GetValidatorSetMetadataRequest) (*apiv1.GetValidatorSetMetadataResponse, error) ⋮---- var epochRequested symbiotic.Epoch ```` ## File: internal/usecase/api-server/helpers_test.go ````go package api_server ⋮---- import ( "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" deriverMocks "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ) ⋮---- "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" deriverMocks "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ⋮---- // testSetup contains all the mocks and test helper functions // This unified setup can be used for all API server endpoint tests type testSetup struct { ctrl *gomock.Controller mockEvmClient *deriverMocks.MockEvmClient mockRepo *mocks.Mockrepo mockDeriver *mocks.Mockderiver handler *grpcHandler } ⋮---- // newTestSetup creates a new test setup with mocked dependencies // This reuses the same construction pattern as production code func newTestSetup(t *testing.T) *testSetup ⋮---- // Create Config using the same structure as production ⋮---- Address: ":8080", // not used in unit tests ⋮---- // Inject mocked dependencies ⋮---- // Create grpcHandler using the same pattern as production ⋮---- // createTestValidatorSet creates a sample validator set for testing // This is the simpler version used for GetValidatorSetHeader tests func createTestValidatorSet(epoch symbiotic.Epoch) symbiotic.ValidatorSet ⋮---- CaptureTimestamp: 1640995200, // 2022-01-01 00:00:00 UTC ⋮---- // createTestValidatorSetWithMultipleValidators creates a sample validator set with multiple validators for testing // This is the richer version used for GetValidatorByAddress tests func createTestValidatorSetWithMultipleValidators(epoch symbiotic.Epoch) symbiotic.ValidatorSet ```` ## File: internal/usecase/api-server/http_test.go ````go package api_server ⋮---- import ( "bytes" "fmt" "net/http" "net/http/httptest" "strings" "testing" "github.com/go-errors/errors" ) ⋮---- "bytes" "fmt" "net/http" "net/http/httptest" "strings" "testing" ⋮---- "github.com/go-errors/errors" ⋮---- // mockFlusher implements http.Flusher for testing type mockFlusher struct { flushCount int } ⋮---- func (m *mockFlusher) Flush() ⋮---- // mockResponseWriter implements http.ResponseWriter and http.Flusher for testing type mockResponseWriter struct { mockFlusher header http.Header body bytes.Buffer statusCode int } ⋮---- func newMockResponseWriter() *mockResponseWriter ⋮---- func (m *mockResponseWriter) Header() http.Header ⋮---- func (m *mockResponseWriter) Write(b []byte) (int, error) ⋮---- func (m *mockResponseWriter) WriteHeader(statusCode int) ⋮---- func TestSSEResponseWriter_CompleteMessages(t *testing.T) ⋮---- // Write complete JSON messages ⋮---- // Check output is in SSE format ⋮---- // Check that flush was called for each message ⋮---- // Verify headers were set correctly ⋮---- func TestSSEResponseWriter_PartialWrites(t *testing.T) ⋮---- // Simulate json.Encoder behavior: writes in chunks without newline ⋮---- // Write chunks one by one ⋮---- // After first write, no output should be produced (no complete line yet) ⋮---- // Still no output (no newline yet) ⋮---- // Now we should have complete output ⋮---- // Should have flushed once (after complete line) ⋮---- func TestSSEResponseWriter_EmptyLines(t *testing.T) ⋮---- // Write with empty lines ⋮---- // Empty lines should be skipped ⋮---- func TestSSEResponseWriter_MultipleMessagesWithPartials(t *testing.T) ⋮---- // Write complete message followed by partial ⋮---- // Check that first message was output ⋮---- // Complete the partial message ⋮---- // Now both messages should be present ⋮---- func TestSSEResponseWriter_BufferOverflow(t *testing.T) ⋮---- // Create a message larger than 5MB (the maxBufferSize) without newline ⋮---- func TestSSEResponseWriter_WriteError(t *testing.T) ⋮---- // Create a mock that fails on write ⋮---- // Should still return the bytes we accepted from input ⋮---- // failingResponseWriter always fails on Write type failingResponseWriter struct { header http.Header } ⋮---- func TestSSEResponseWriter_BufferPersistence(t *testing.T) ⋮---- // Write partial message ⋮---- // Check buffer contains partial data ⋮---- // Write more partial data ⋮---- // Buffer should have grown ⋮---- // Complete the message ⋮---- // Buffer should be empty (or contain only remaining data) ⋮---- // Verify complete message was output ⋮---- func TestSSEResponseWriter_EmptyWrite(t *testing.T) ⋮---- // Write empty data ⋮---- // Should produce no output ⋮---- func TestSSEResponseWriter_NilFlusher(t *testing.T) ⋮---- flusher: nil, // nil flusher ⋮---- // Write should fail with nil flusher ⋮---- func TestSSEResponseWriter_ConcurrentWrites(t *testing.T) ⋮---- // Perform concurrent writes const numGoroutines = 10 ⋮---- // Wait for all goroutines ⋮---- // Should have written all messages (order may vary due to concurrency) ⋮---- func TestSSEResponseWriter_FlushWithNilFlusher(t *testing.T) ⋮---- // Flush should not panic with nil flusher ⋮---- func TestSSEResponseWriter_RealWorldScenario(t *testing.T) ⋮---- // Simulate real httptest.ResponseRecorder behavior ⋮---- // Simulate json.Encoder writing large objects in chunks // This is the actual problematic scenario described in the issue ⋮---- // Simulate chunked writes (what json.Encoder does) ⋮---- // Don't add newline until the end ⋮---- // Verify the complete JSON was output as a single SSE event ⋮---- // Count number of SSE events (should be 1) ⋮---- // Verify the JSON is complete and valid ```` ## File: internal/usecase/api-server/http.go ````go package api_server ⋮---- import ( "bytes" "context" "fmt" "io" "log/slog" "net/http" "strings" "sync" "github.com/go-errors/errors" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) ⋮---- "bytes" "context" "fmt" "io" "log/slog" "net/http" "strings" "sync" ⋮---- "github.com/go-errors/errors" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ⋮---- const maxBufferSize = 5 * 1024 * 1024 // 5MB ⋮---- // sseResponseWriter wraps http.ResponseWriter to convert newline-delimited JSON to SSE format type sseResponseWriter struct { http.ResponseWriter flusher http.Flusher headersWritten bool buffer bytes.Buffer // Buffer for incomplete lines mu sync.Mutex // Protect buffer from concurrent writes } ⋮---- buffer bytes.Buffer // Buffer for incomplete lines mu sync.Mutex // Protect buffer from concurrent writes ⋮---- // WriteHeader intercepts header writes to set SSE headers func (s *sseResponseWriter) WriteHeader(statusCode int) ⋮---- // Override content-type for SSE ⋮---- func (s *sseResponseWriter) Write(b []byte) (int, error) ⋮---- // Process complete lines (those ending with \n) ⋮---- // No complete line yet - restore partial data to buffer // ReadBytes with EOF consumes all data from buffer, so we put it back ⋮---- // Unexpected error from ReadBytes ⋮---- // Write in SSE format: data: {json}\n\n ⋮---- // Return the number of bytes we accepted from the input ⋮---- func (s *sseResponseWriter) Flush() ⋮---- // setupHttpProxy configures the HTTP-to-gRPC gateway proxy // Returns a start function that should be called after the gRPC server starts listening func setupHttpProxy(ctx context.Context, grpcAddr string, httpMux *http.ServeMux) func() error ⋮---- // Create gRPC client connection to the actual gRPC server via TCP ⋮---- grpc.MaxCallRecvMsgSize(10*1024*1024), // 10MB grpc.MaxCallSendMsgSize(10*1024*1024), // 10MB ⋮---- var conn *grpc.ClientConn ⋮---- // Start function that will be called after gRPC server is listening ⋮---- var err error ⋮---- // Mount the gateway under /api prefix with CORS and streaming support ⋮---- // Check if gateway is initialized ⋮---- // Set CORS headers ⋮---- w.Header().Set("Access-Control-Max-Age", "86400") // 24 hours ⋮---- // Handle preflight OPTIONS request ⋮---- // For streaming endpoints, wrap the response writer to intercept and convert to SSE ⋮---- // Wrap with SSE writer that will handle headers and format conversion ```` ## File: internal/usecase/api-server/interceptors_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" ⋮---- func TestConvertToGRPCError_NilError_ReturnsNil(t *testing.T) ⋮---- func TestConvertToGRPCError_AlreadyGRPCError_ReturnsAsIs(t *testing.T) ⋮---- func TestConvertToGRPCError_ErrNotAnAggregator_ReturnsPermissionDenied(t *testing.T) ⋮---- func TestConvertToGRPCError_ErrEntityNotFound_ReturnsNotFound(t *testing.T) ⋮---- func TestConvertToGRPCError_ErrChainNotFound_ReturnsNotFound(t *testing.T) ⋮---- func TestConvertToGRPCError_ErrEntityAlreadyExist_ReturnsAlreadyExists(t *testing.T) ⋮---- func TestConvertToGRPCError_ErrNoPeers_ReturnsUnavailable(t *testing.T) ⋮---- func TestConvertToGRPCError_ContextCanceled_ReturnsCanceled(t *testing.T) ⋮---- func TestConvertToGRPCError_ContextDeadlineExceeded_ReturnsDeadlineExceeded(t *testing.T) ⋮---- func TestConvertToGRPCError_UnknownError_ReturnsInternal(t *testing.T) ⋮---- func TestErrorHandlingInterceptor_HandlerReturnsNil_ReturnsSuccess(t *testing.T) ⋮---- func TestErrorHandlingInterceptor_HandlerReturnsError_ConvertsError(t *testing.T) ⋮---- func TestErrorHandlingInterceptor_HandlerReturnsGRPCError_ReturnsAsIs(t *testing.T) ⋮---- type mockServerStream struct { grpc.ServerStream ctx context.Context } ⋮---- func (m *mockServerStream) Context() context.Context ⋮---- func TestStreamErrorHandlingInterceptor_HandlerReturnsNil_ReturnsSuccess(t *testing.T) ⋮---- func TestStreamErrorHandlingInterceptor_HandlerReturnsError_ConvertsError(t *testing.T) ⋮---- func TestStreamErrorHandlingInterceptor_HandlerReturnsGRPCError_ReturnsAsIs(t *testing.T) ```` ## File: internal/usecase/api-server/interceptors.go ````go package api_server ⋮---- import ( "context" "log/slog" "github.com/go-errors/errors" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/internal/entity" ) ⋮---- "context" "log/slog" ⋮---- "github.com/go-errors/errors" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/internal/entity" ⋮---- // convertToGRPCError converts internal errors to gRPC status errors func convertToGRPCError(ctx context.Context, err error) error ⋮---- // If the error is already a gRPC status error, return it as-is ⋮---- // Handle known entity errors ⋮---- // Log internal errors ⋮---- // ErrorHandlingInterceptor handles error conversion for unary RPCs func ErrorHandlingInterceptor() grpc.UnaryServerInterceptor ⋮---- // StreamErrorHandlingInterceptor handles error conversion for streaming RPCs func StreamErrorHandlingInterceptor() grpc.StreamServerInterceptor ```` ## File: internal/usecase/api-server/listen_proofs_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/metadata" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" "github.com/symbioticfi/relay/internal/usecase/broadcaster" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/metadata" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" "github.com/symbioticfi/relay/internal/usecase/broadcaster" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type mockProofsStream struct { ctx context.Context sentItems []*apiv1.ListenProofsResponse sendError error sendCalled chan struct{} ⋮---- func (m *mockProofsStream) Context() context.Context ⋮---- func (m *mockProofsStream) Send(msg *apiv1.ListenProofsResponse) error ⋮---- func (m *mockProofsStream) SendMsg(interface ⋮---- func (m *mockProofsStream) RecvMsg(interface ⋮---- func (m *mockProofsStream) SetHeader(metadata.MD) error ⋮---- func (m *mockProofsStream) SendHeader(metadata.MD) error ⋮---- func (m *mockProofsStream) SetTrailer(metadata.MD) ⋮---- func TestListenProofs_OnlyHistoricalData(t *testing.T) ⋮---- func TestListenProofs_OnlyBroadcast(t *testing.T) ⋮---- func TestListenProofs_HistoricalAndBroadcast(t *testing.T) ⋮---- func TestListenProofs_RepositoryError(t *testing.T) ⋮---- func TestListenProofs_StreamSendError(t *testing.T) ⋮---- func TestListenProofs_MultipleBroadcasts(t *testing.T) ⋮---- func TestListenProofs_MaxStreamsReached_ReturnsError(t *testing.T) ⋮---- func TestListenProofs_EmptyHistoricalData(t *testing.T) ```` ## File: internal/usecase/api-server/listen_proofs_v1.go ````go package api_server ⋮---- import ( "github.com/google/uuid" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) ⋮---- "github.com/google/uuid" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- func (h *grpcHandler) ListenProofs( req *apiv1.ListenProofsRequest, stream grpc.ServerStreamingServer[apiv1.ListenProofsResponse], ) error ```` ## File: internal/usecase/api-server/listen_signature_v1.go ````go package api_server ⋮---- import ( "github.com/google/uuid" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) ⋮---- "github.com/google/uuid" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- func (h *grpcHandler) ListenSignatures( req *apiv1.ListenSignaturesRequest, stream grpc.ServerStreamingServer[apiv1.ListenSignaturesResponse], ) error ```` ## File: internal/usecase/api-server/listen_signatures_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/metadata" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" "github.com/symbioticfi/relay/internal/usecase/broadcaster" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/metadata" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" "github.com/symbioticfi/relay/internal/usecase/broadcaster" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- type mockSignaturesStream struct { ctx context.Context sentItems []*apiv1.ListenSignaturesResponse sendError error sendCalled chan struct{} ⋮---- func (m *mockSignaturesStream) Context() context.Context ⋮---- func (m *mockSignaturesStream) Send(msg *apiv1.ListenSignaturesResponse) error ⋮---- func (m *mockSignaturesStream) SendMsg(interface ⋮---- func (m *mockSignaturesStream) RecvMsg(interface ⋮---- func (m *mockSignaturesStream) SetHeader(metadata.MD) error ⋮---- func (m *mockSignaturesStream) SendHeader(metadata.MD) error ⋮---- func (m *mockSignaturesStream) SetTrailer(metadata.MD) ⋮---- func TestListenSignatures_OnlyHistoricalData(t *testing.T) ⋮---- func TestListenSignatures_OnlyBroadcast(t *testing.T) ⋮---- func TestListenSignatures_HistoricalAndBroadcast(t *testing.T) ⋮---- func TestListenSignatures_RepositoryError(t *testing.T) ⋮---- func TestListenSignatures_StreamSendError(t *testing.T) ⋮---- func TestListenSignatures_MultipleBroadcasts(t *testing.T) ⋮---- func TestListenSignatures_MaxStreamsReached_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/listen_validator_set_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "time" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/metadata" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" "github.com/symbioticfi/relay/internal/usecase/broadcaster" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "google.golang.org/grpc/metadata" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" "github.com/symbioticfi/relay/internal/usecase/broadcaster" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type mockValidatorSetsStream struct { ctx context.Context sentItems []*apiv1.ListenValidatorSetResponse sendError error sendCalled chan struct{} ⋮---- func (m *mockValidatorSetsStream) Context() context.Context ⋮---- func (m *mockValidatorSetsStream) Send(msg *apiv1.ListenValidatorSetResponse) error ⋮---- func (m *mockValidatorSetsStream) SendMsg(interface ⋮---- func (m *mockValidatorSetsStream) RecvMsg(interface ⋮---- func (m *mockValidatorSetsStream) SetHeader(metadata.MD) error ⋮---- func (m *mockValidatorSetsStream) SendHeader(metadata.MD) error ⋮---- func (m *mockValidatorSetsStream) SetTrailer(metadata.MD) ⋮---- func TestListenValidatorSet_OnlyHistoricalData(t *testing.T) ⋮---- func TestListenValidatorSet_OnlyBroadcast(t *testing.T) ⋮---- func TestListenValidatorSet_HistoricalAndBroadcast(t *testing.T) ⋮---- func TestListenValidatorSet_RepositoryError(t *testing.T) ⋮---- func TestListenValidatorSet_StreamSendError(t *testing.T) ⋮---- func TestListenValidatorSet_MultipleBroadcasts(t *testing.T) ⋮---- func TestListenValidatorSet_EmptyHistoricalData(t *testing.T) ⋮---- func TestListenValidatorSet_ConcurrentBroadcasts(t *testing.T) ⋮---- func TestListenValidatorSet_MaxStreamsReached_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/listen_validator_set_v1.go ````go package api_server ⋮---- import ( "github.com/google/uuid" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) ⋮---- "github.com/google/uuid" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- func (h *grpcHandler) ListenValidatorSet( req *apiv1.ListenValidatorSetRequest, stream grpc.ServerStreamingServer[apiv1.ListenValidatorSetResponse], ) error ⋮---- func convertValidatorSetToStreamResponse(valSet symbiotic.ValidatorSet) *apiv1.ListenValidatorSetResponse ```` ## File: internal/usecase/api-server/sign_message_v1_test.go ````go package api_server ⋮---- import ( "context" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" "github.com/symbioticfi/relay/internal/usecase/api-server/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestSignMessage_WithRequiredEpoch_Success(t *testing.T) ⋮---- func TestSignMessage_WithoutRequiredEpoch_UsesLatestEpoch(t *testing.T) ⋮---- func TestSignMessage_GetLatestEpochFails_ReturnsError(t *testing.T) ⋮---- func TestSignMessage_RequestSignatureFails_ReturnsError(t *testing.T) ```` ## File: internal/usecase/api-server/sign_message_v1.go ````go package api_server ⋮---- import ( "context" apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- apiv1 "github.com/symbioticfi/relay/internal/gen/api/v1" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // SignMessage handles the gRPC SignMessage request func (h *grpcHandler) SignMessage(ctx context.Context, req *apiv1.SignMessageRequest) (*apiv1.SignMessageResponse, error) ```` ## File: internal/usecase/broadcaster/doc.go ````go // Package broadcaster provides a generic Hub implementation for dynamic fan-out messaging. // // The Hub allows publishers to broadcast messages to a dynamic set of subscribers. // Subscribers can join and leave at any time (0 to N subscribers). ⋮---- // Usage example: ⋮---- // // Create a hub for string messages with custom buffer size // hub := broadcaster.NewHub[string]( // broadcaster.WithBufferSize[string](100), // ) ⋮---- // // Subscribe to receive messages // ch := hub.Subscribe("subscriber-1") // defer hub.Unsubscribe("subscriber-1") ⋮---- // // Receive messages in a goroutine // go func() { // for msg := range ch { // fmt.Println("Received:", msg) // } // }() ⋮---- // // Broadcast to all subscribers (non-blocking) // hub.Broadcast("Hello, World!") ⋮---- // // Check subscriber count // count := hub.Count() // fmt.Printf("Active subscribers: %d\n", count) ⋮---- // Thread Safety: ⋮---- // All Hub methods are thread-safe and can be called concurrently from multiple goroutines. ⋮---- // Backpressure Handling: ⋮---- // The Hub uses buffered channels for each subscriber. If a subscriber's channel buffer is full, // the Broadcast method will drop the message for that subscriber (non-blocking). // Use BroadcastWait if you need to ensure all subscribers receive the message (blocking). package broadcaster ```` ## File: internal/usecase/broadcaster/hub_test.go ````go package broadcaster ⋮---- import ( "sync" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) ⋮---- "sync" "testing" "time" ⋮---- "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- func TestHub_SubscribeUnsubscribe(t *testing.T) ⋮---- // Subscribe ⋮---- // Subscribe another ⋮---- // Unsubscribe ⋮---- func TestHub_SubscribeIdempotent(t *testing.T) ⋮---- // Subscribe twice with same ID ⋮---- // Should return same channel ⋮---- func TestHub_BroadcastToAll(t *testing.T) ⋮---- // Subscribe multiple subscribers ⋮---- // Broadcast message ⋮---- // All should receive the message ⋮---- func TestHub_BroadcastWithNoSubscribers(t *testing.T) ⋮---- // Should not panic ⋮---- func TestHub_BroadcastDropsWhenBufferFull(t *testing.T) ⋮---- // Fill the buffer ⋮---- hub.Broadcast("msg2") // This should be dropped ⋮---- // Read one message ⋮---- // Channel should be empty now ⋮---- // Expected - no more messages ⋮---- func TestHub_BroadcastWaitBlocks(t *testing.T) ⋮---- // BroadcastWait should block until we read ⋮---- // Give it time to block ⋮---- // Should still be blocking ⋮---- // Expected ⋮---- // Read from channel to unblock ⋮---- // Now should complete ⋮---- func TestHub_ConcurrentAccess(t *testing.T) ⋮---- var wg sync.WaitGroup ⋮---- // Start subscribers ⋮---- // Start broadcasting ⋮---- // Start receiving ⋮---- func TestHub_UnsubscribeClosesChannel(t *testing.T) ⋮---- // Channel should be closed ⋮---- func TestHub_Close(t *testing.T) ⋮---- // All channels should be closed ⋮---- // Count should be 0 ⋮---- func TestHub_WithOptions(t *testing.T) ⋮---- func TestHub_BroadcastAfterUnsubscribe(t *testing.T) ⋮---- // Unsubscribe one ⋮---- // Broadcast should only go to remaining subscriber ⋮---- // sub2 should receive ⋮---- // sub1 should be closed ```` ## File: internal/usecase/broadcaster/hub.go ````go package broadcaster ⋮---- import ( "log/slog" "sync" ) ⋮---- "log/slog" "sync" ⋮---- // Hub is a generic broadcaster that manages dynamic fan-out of messages to subscribers // T is the type of messages being broadcast type Hub[T any] struct { mu sync.RWMutex subscribers map[string]*subscriber[T] bufferSize int } ⋮---- // subscriber represents a single subscriber with its channel type subscriber[T any] struct { id string ch chan T stopped bool mu sync.Mutex } ⋮---- // HubOption configures the Hub type HubOption[T any] func(*Hub[T]) ⋮---- // WithBufferSize sets the buffer size for subscriber channels func WithBufferSize[T any](size int) HubOption[T] ⋮---- // NewHub creates a new Hub with optional configuration func NewHub[T any](opts ...HubOption[T]) *Hub[T] ⋮---- bufferSize: 100, // default buffer size ⋮---- // Subscribe adds a new subscriber with the given ID and returns the channel to receive messages // If a subscriber with the same ID already exists, it returns the existing channel func (h *Hub[T]) Subscribe(id string) chan T ⋮---- // Check if subscriber already exists ⋮---- // Unsubscribe removes a subscriber and closes its channel func (h *Hub[T]) Unsubscribe(id string) ⋮---- // Broadcast sends a message to all active subscribers // Slow subscribers will have messages dropped (non-blocking send) func (h *Hub[T]) Broadcast(msg T) ⋮---- // successfully sent ⋮---- // channel is full, drop message ⋮---- // BroadcastWait sends a message to all active subscribers and waits for all sends to complete // This is a blocking operation that ensures all subscribers receive the message func (h *Hub[T]) BroadcastWait(msg T) ⋮---- // Blocking send ⋮---- // Count returns the number of active subscribers func (h *Hub[T]) Count() int ⋮---- // Close unsubscribes all subscribers and cleans up resources func (h *Hub[T]) Close() ```` ## File: internal/usecase/entity-processor/mocks/entity_processor.go ````go // Code generated by MockGen. DO NOT EDIT. // Source: entity_processor.go // // Generated by this command: ⋮---- // mockgen -source=entity_processor.go -destination=mocks/entity_processor.go -package=mocks ⋮---- // Package mocks is a generated GoMock package. package mocks ⋮---- import ( context "context" reflect "reflect" common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ) ⋮---- context "context" reflect "reflect" ⋮---- common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ⋮---- // MockRepository is a mock of Repository interface. type MockRepository struct { ctrl *gomock.Controller recorder *MockRepositoryMockRecorder isgomock struct{} ⋮---- // MockRepositoryMockRecorder is the mock recorder for MockRepository. type MockRepositoryMockRecorder struct { mock *MockRepository } ⋮---- // NewMockRepository creates a new mock instance. func NewMockRepository(ctrl *gomock.Controller) *MockRepository ⋮---- // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockRepository) EXPECT() *MockRepositoryMockRecorder ⋮---- // GetAggregationProof mocks base method. func (m *MockRepository) GetAggregationProof(ctx context.Context, requestID common.Hash) (entity.AggregationProof, error) ⋮---- // GetAggregationProof indicates an expected call of GetAggregationProof. ⋮---- // GetSignatureByIndex mocks base method. func (m *MockRepository) GetSignatureByIndex(ctx context.Context, requestID common.Hash, validatorIndex uint32) (entity.Signature, error) ⋮---- // GetSignatureByIndex indicates an expected call of GetSignatureByIndex. ⋮---- // GetValidatorByKey mocks base method. func (m *MockRepository) GetValidatorByKey(ctx context.Context, epoch entity.Epoch, keyTag entity.KeyTag, publicKey []byte) (entity.Validator, uint32, error) ⋮---- // GetValidatorByKey indicates an expected call of GetValidatorByKey. ⋮---- // GetValidatorSetByEpoch mocks base method. func (m *MockRepository) GetValidatorSetByEpoch(ctx context.Context, epoch entity.Epoch) (entity.ValidatorSet, error) ⋮---- // GetValidatorSetByEpoch indicates an expected call of GetValidatorSetByEpoch. ⋮---- // SaveProof mocks base method. func (m *MockRepository) SaveProof(ctx context.Context, aggregationProof entity.AggregationProof) error ⋮---- // SaveProof indicates an expected call of SaveProof. ⋮---- // SaveSignature mocks base method. func (m *MockRepository) SaveSignature(ctx context.Context, signature entity.Signature, validator entity.Validator, activeIndex uint32) error ⋮---- // SaveSignature indicates an expected call of SaveSignature. ⋮---- // MockAggregator is a mock of Aggregator interface. type MockAggregator struct { ctrl *gomock.Controller recorder *MockAggregatorMockRecorder isgomock struct{} ⋮---- // MockAggregatorMockRecorder is the mock recorder for MockAggregator. type MockAggregatorMockRecorder struct { mock *MockAggregator } ⋮---- // NewMockAggregator creates a new mock instance. func NewMockAggregator(ctrl *gomock.Controller) *MockAggregator ⋮---- // Verify mocks base method. func (m *MockAggregator) Verify(valset entity.ValidatorSet, keyTag entity.KeyTag, aggregationProof entity.AggregationProof) (bool, error) ⋮---- // Verify indicates an expected call of Verify. ⋮---- // MockAggProofSignal is a mock of AggProofSignal interface. type MockAggProofSignal struct { ctrl *gomock.Controller recorder *MockAggProofSignalMockRecorder isgomock struct{} ⋮---- // MockAggProofSignalMockRecorder is the mock recorder for MockAggProofSignal. type MockAggProofSignalMockRecorder struct { mock *MockAggProofSignal } ⋮---- // NewMockAggProofSignal creates a new mock instance. func NewMockAggProofSignal(ctrl *gomock.Controller) *MockAggProofSignal ⋮---- // Emit mocks base method. func (m *MockAggProofSignal) Emit(payload entity.AggregationProof) error ⋮---- // Emit indicates an expected call of Emit. ```` ## File: internal/usecase/entity-processor/entity_processor_test.go ````go package entity_processor ⋮---- import ( "crypto/rand" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "golang.org/x/sync/errgroup" "github.com/symbioticfi/relay/internal/client/repository/badger" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "crypto/rand" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "golang.org/x/sync/errgroup" ⋮---- "github.com/symbioticfi/relay/internal/client/repository/badger" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func TestEntityProcessor_ProcessSignature(t *testing.T) ⋮---- // Setup validator set header with high quorum threshold (1000) ⋮---- // Setup validator set header with low quorum threshold (50) ⋮---- expectPendingExists: false, // Should be removed due to quorum ⋮---- // Setup validator set header with high quorum threshold ⋮---- // Setup validator set header with quorum threshold of 150 ⋮---- // First signature - not enough for quorum ⋮---- // Verify pending exists after first signature ⋮---- // Return second signature that will reach quorum ⋮---- expectPendingExists: false, // Should be removed after reaching quorum ⋮---- // Don't setup validator set header - will cause error ⋮---- // Verify signature map was created/updated ⋮---- // Verify at least one validator is present in the bitmap ⋮---- // Verify pending collection state ⋮---- func TestEntityProcessor_ProcessSignature_ConcurrentSignatures(t *testing.T) ⋮---- // Setup validator set header with quorum threshold of 300 ⋮---- // Simulate 4 concurrent signatures ⋮---- // Process signatures sequentially (testing transaction consistency) ⋮---- // Verify final state ⋮---- // Since all signatures use the same key tag, they would resolve to the same validator // So we should have at least one validator present ⋮---- // Pending collection should be empty (quorum reached) ⋮---- func TestEntityProcessor_ProcessSignature_Conflict(t *testing.T) ⋮---- func TestEntityProcessor_ProcessSignature_DuplicateSignatureForSameValidator(t *testing.T) ⋮---- // First signature should succeed ⋮---- // Duplicate signature should fail ⋮---- func TestEntityProcessor_ProcessSignature_ExactQuorumThreshold(t *testing.T) ⋮---- // Set quorum threshold to exactly 100 ⋮---- // Should reach quorum and remove from pending ⋮---- // Helper functions ⋮---- func createMockAggregator(t *testing.T) *mocks.MockAggregator ⋮---- // Default behavior: return true for verification ⋮---- func createMockAggProofSignal(t *testing.T) *mocks.MockAggProofSignal ⋮---- // Default behavior: return nil for emit ⋮---- func createMockSignatureProcessedSignal(t *testing.T) *signals.Signal[symbiotic.Signature] ⋮---- func setupTestRepository(t *testing.T) *badger.Repository ⋮---- func randomBytes(t *testing.T, n int) []byte ⋮---- func computeMessageHash(t *testing.T, keyTag symbiotic.KeyTag, message []byte) []byte ⋮---- func randomSignatureRequest(t *testing.T, epoch symbiotic.Epoch) symbiotic.SignatureRequest ⋮---- func randomSignatureExtendedForKeyWithParams(t *testing.T, privateKey crypto.PrivateKey, req symbiotic.SignatureRequest) symbiotic.Signature ⋮---- // signatureExtendedForRequest creates a Signature for a given SignatureRequest using the same message func signatureExtendedForRequest(t *testing.T, privateKey crypto.PrivateKey, req symbiotic.SignatureRequest) symbiotic.Signature ⋮---- func createValidatorSetWithCount(t *testing.T, epoch symbiotic.Epoch, quorumThreshold *big.Int, validatorCount int) (symbiotic.ValidatorSet, []map[symbiotic.KeyTag]crypto.PrivateKey) ⋮---- // Generate a valid key for the validator ⋮---- Payload: privateKeyBLS.PublicKey().OnChain(), // Use the actual on-chain representation ⋮---- Payload: privateKeyECDSA.PublicKey().OnChain(), // Use the actual on-chain representation ⋮---- validatorsList.SortByOperatorAddressAsc() // Sort validators by operator address ⋮---- func setupValidatorSetHeader(t *testing.T, repo *badger.Repository, epoch symbiotic.Epoch, quorumThreshold *big.Int) (symbiotic.ValidatorSet, []map[symbiotic.KeyTag]crypto.PrivateKey) ⋮---- vs, privateKeys := createValidatorSetWithCount(t, epoch, quorumThreshold, 4) // Default to 4 validators for backward compatibility ⋮---- func TestEntityProcessor_ProcessAggregationProof_SuccessfullyProcesses(t *testing.T) ⋮---- // Setup validator set for this epoch (required by ProcessAggregationProof) ⋮---- // Process aggregation proof ⋮---- // Verify aggregation proof was saved ⋮---- // Verify pending aggregation proof was removed ⋮---- func TestEntityProcessor_ProcessAggregationProof_HandlesMissingPendingGracefully(t *testing.T) ⋮---- // Process aggregation proof without pending entry (should succeed) ⋮---- // Verify aggregation proof was still saved ⋮---- func TestEntityProcessor_ProcessAggregationProof_FailsWhenAlreadyExists(t *testing.T) ⋮---- // Attempt to process same aggregation proof should fail ⋮---- func TestEntityProcessor_ProcessSignature_SavesAggregationProofPendingForAggregationKeys(t *testing.T) ⋮---- // Process signature ⋮---- // Verify aggregation proof pending was also saved ⋮---- func TestEntityProcessor_ProcessSignature_SaveAggregationProofPendingForNonAggregationKeys(t *testing.T) ⋮---- req.KeyTag = symbiotic.KeyTag(0x10) // Ensure it's NOT an aggregation key (EcdsaSecp256k1) ⋮---- // Verify signature request was saved but NOT to pending collection ⋮---- // Verify no pending aggregation proof requests ⋮---- func TestEntityProcessor_ProcessSignature_FullSignatureToAggregationProofFlow(t *testing.T) ⋮---- // Step 1: Process signature (should create pending aggregation proof) ⋮---- // Verify pending aggregation proof exists ⋮---- // Step 2: Process aggregation proof (should remove from pending) ```` ## File: internal/usecase/entity-processor/entity_processor.go ````go package entity_processor ⋮---- import ( "context" "log/slog" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- //go:generate mockgen -source=entity_processor.go -destination=mocks/entity_processor.go -package=mocks ⋮---- // Repository defines the interface needed by the entity processor type Repository interface { SaveSignature(ctx context.Context, signature symbiotic.Signature, validator symbiotic.Validator, activeIndex uint32) error GetSignatureByIndex(ctx context.Context, requestID common.Hash, validatorIndex uint32) (symbiotic.Signature, error) GetValidatorByKey(ctx context.Context, epoch symbiotic.Epoch, keyTag symbiotic.KeyTag, publicKey []byte) (symbiotic.Validator, uint32, error) GetValidatorSetByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) GetAggregationProof(ctx context.Context, requestID common.Hash) (symbiotic.AggregationProof, error) SaveProof(ctx context.Context, aggregationProof symbiotic.AggregationProof) error } ⋮---- type Aggregator interface { Verify(valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, aggregationProof symbiotic.AggregationProof) (bool, error) } ⋮---- type AggProofSignal interface { Emit(payload symbiotic.AggregationProof) error } ⋮---- type Config struct { Repo Repository `validate:"required"` Aggregator Aggregator `validate:"required"` AggProofSignal AggProofSignal `validate:"required"` SignatureProcessedSignal *signals.Signal[symbiotic.Signature] `validate:"required"` } ⋮---- func (c Config) Validate() error ⋮---- // EntityProcessor handles both signature and aggregation proof processing with SignatureMap operations type EntityProcessor struct { cfg Config } ⋮---- // NewEntityProcessor creates a new entity processor func NewEntityProcessor(cfg Config) (*EntityProcessor, error) ⋮---- // ProcessSignature processes a signature with SignatureMap operations and optionally saves SignatureRequest func (s *EntityProcessor) ProcessSignature(ctx context.Context, signature symbiotic.Signature, self bool) error ⋮---- // if self signature ignore validator check and signature existence check ⋮---- // check if signature already exists ⋮---- // Emit signal after successful processing ⋮---- // ProcessAggregationProof processes an aggregation proof by saving it and removing from pending collection func (s *EntityProcessor) ProcessAggregationProof(ctx context.Context, aggregationProof symbiotic.AggregationProof) error ⋮---- // Emit signal after successful save ```` ## File: internal/usecase/key-provider/cache_key_provider.go ````go package keyprovider ⋮---- import ( "sync" "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "sync" ⋮---- "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type CacheKeyProvider struct { KeyProvider nodeKeyMap *sync.Map // map[keyTag]CompactPublicKey } ⋮---- nodeKeyMap *sync.Map // map[keyTag]CompactPublicKey ⋮---- func NewCacheKeyProvider(kp KeyProvider) *CacheKeyProvider ⋮---- func (c *CacheKeyProvider) GetOnchainKeyFromCache(keyTag entity.KeyTag) (entity.CompactPublicKey, error) ```` ## File: internal/usecase/key-provider/env_provider.go ````go package keyprovider ⋮---- import ( "encoding/base64" "os" "strings" "sync" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/go-errors/errors" ) ⋮---- "encoding/base64" "os" "strings" "sync" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/go-errors/errors" ⋮---- type EnvKeyProvider struct { cache map[string]crypto.PrivateKey mu sync.RWMutex } ⋮---- func NewEnvKeyProvider() *EnvKeyProvider ⋮---- func (e *EnvKeyProvider) GetPrivateKey(keyTag symbiotic.KeyTag) (crypto.PrivateKey, error) ⋮---- func (e *EnvKeyProvider) GetPrivateKeyByNamespaceTypeId( namespace string, keyType symbiotic.KeyType, keyId int, ) (crypto.PrivateKey, error) ⋮---- func (e *EnvKeyProvider) GetPrivateKeyByAlias(alias string) (crypto.PrivateKey, error) ⋮---- func (e *EnvKeyProvider) HasKey(keyTag symbiotic.KeyTag) (bool, error) ⋮---- func (e *EnvKeyProvider) HasKeyByAlias(alias string) (bool, error) ⋮---- func (e *EnvKeyProvider) HasKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (bool, error) ```` ## File: internal/usecase/key-provider/key_provider.go ````go package keyprovider ⋮---- import ( "strconv" "strings" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "strconv" "strings" ⋮---- "github.com/go-errors/errors" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- const ( SYMBIOTIC_KEY_NAMESPACE = "symb" EVM_KEY_NAMESPACE = "evm" P2P_KEY_NAMESPACE = "p2p" // DEFAULT_EVM_CHAIN_ID chain id used to identify the default key for all chains DEFAULT_EVM_CHAIN_ID = 0 P2P_HOST_IDENTITY_KEY_ID = 1 ) ⋮---- // DEFAULT_EVM_CHAIN_ID chain id used to identify the default key for all chains ⋮---- type KeyProvider interface { GetPrivateKey(keyTag symbiotic.KeyTag) (crypto.PrivateKey, error) GetPrivateKeyByAlias(alias string) (crypto.PrivateKey, error) GetPrivateKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (crypto.PrivateKey, error) HasKey(keyTag symbiotic.KeyTag) (bool, error) HasKeyByAlias(alias string) (bool, error) HasKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (bool, error) } ⋮---- func KeyTagToAliasWithNS(namespace string, keyTag symbiotic.KeyTag) (string, error) ⋮---- // https://github.com/symbioticfi/middleware-sdk-mirror/blob/change-header/src/contracts/libraries/utils/KeyTags.sol#L24-L40 ⋮---- func KeyTagToAlias(keyTag symbiotic.KeyTag) (string, error) ⋮---- func ToAlias(namespace string, keyType symbiotic.KeyType, keyId int) (string, error) ⋮---- //nolint:revive // we need to return the ns too func AliasToKeyTypeId(alias string) (string, symbiotic.KeyType, int, error) ```` ## File: internal/usecase/key-provider/key_store_provider_test.go ````go package keyprovider ⋮---- import ( "testing" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/stretchr/testify/require" ) ⋮---- "testing" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/stretchr/testify/require" ⋮---- func TestNewKeystore(t *testing.T) ⋮---- func TestAddKey(t *testing.T) ⋮---- func TestForceAddKey(t *testing.T) ⋮---- func TestCreateAndReopen(t *testing.T) ⋮---- func TestDefaultEVMKey(t *testing.T) ⋮---- // shouldn't work for other chains ```` ## File: internal/usecase/key-provider/key_store_provider.go ````go package keyprovider ⋮---- import ( "log/slog" "os" "path/filepath" "time" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/go-errors/errors" "github.com/pavlo-v-chernykh/keystore-go/v4" ) ⋮---- "log/slog" "os" "path/filepath" "time" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/go-errors/errors" "github.com/pavlo-v-chernykh/keystore-go/v4" ⋮---- type KeystoreProvider struct { ks keystore.KeyStore filePath string } ⋮---- func NewKeystoreProvider(filePath, password string) (*KeystoreProvider, error) ⋮---- func (k *KeystoreProvider) GetAliases() []string ⋮---- func (k *KeystoreProvider) GetPrivateKey(keyTag symbiotic.KeyTag) (crypto.PrivateKey, error) ⋮---- func (k *KeystoreProvider) GetPrivateKeyByAlias(alias string) (crypto.PrivateKey, error) ⋮---- func (k *KeystoreProvider) GetPrivateKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (crypto.PrivateKey, error) ⋮---- // For EVM keys, we check for default key with chain ID 0 if the requested chain id is absent ⋮---- func (k *KeystoreProvider) HasKey(keyTag symbiotic.KeyTag) (bool, error) ⋮---- func (k *KeystoreProvider) HasKeyByAlias(alias string) (bool, error) ⋮---- func (k *KeystoreProvider) HasKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (bool, error) ⋮---- func (k *KeystoreProvider) AddKey(namespace string, keyTag symbiotic.KeyTag, privateKey crypto.PrivateKey, password string, force bool) error ⋮---- func (k *KeystoreProvider) DeleteKey(keyTag symbiotic.KeyTag, password string) error ⋮---- func (k *KeystoreProvider) AddKeyByNamespaceTypeId(ns string, tp symbiotic.KeyType, id int, privateKey crypto.PrivateKey, password string, force bool) error ⋮---- func (k *KeystoreProvider) DeleteKeyByNamespaceTypeId(ns string, tp symbiotic.KeyType, id int, password string) error ⋮---- func (k *KeystoreProvider) dump(password string) error ```` ## File: internal/usecase/key-provider/simple_key_provider.go ````go package keyprovider ⋮---- import ( "log/slog" "sync" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "log/slog" "sync" ⋮---- "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- type SimpleKeystoreProvider struct { keys map[string]crypto.PrivateKey mu sync.RWMutex } ⋮---- func NewSimpleKeystoreProvider() (*SimpleKeystoreProvider, error) ⋮---- func (k *SimpleKeystoreProvider) GetPrivateKey(keyTag symbiotic.KeyTag) (crypto.PrivateKey, error) ⋮---- func (k *SimpleKeystoreProvider) GetPrivateKeyByAlias(alias string) (crypto.PrivateKey, error) ⋮---- func (k *SimpleKeystoreProvider) GetPrivateKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (crypto.PrivateKey, error) ⋮---- // For EVM keys, we check for default key with chain ID 0 if the requested chain id is absent ⋮---- func (k *SimpleKeystoreProvider) HasKey(keyTag symbiotic.KeyTag) (bool, error) ⋮---- func (k *SimpleKeystoreProvider) HasKeyByAlias(alias string) (bool, error) ⋮---- func (k *SimpleKeystoreProvider) HasKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (bool, error) ⋮---- func (k *SimpleKeystoreProvider) AddKey(keyTag symbiotic.KeyTag, privateKey crypto.PrivateKey) error ⋮---- func (k *SimpleKeystoreProvider) AddKeyByNamespaceTypeId(ns string, tp symbiotic.KeyType, id int, privateKey crypto.PrivateKey) error ⋮---- func (k *SimpleKeystoreProvider) DeleteKey(keyTag symbiotic.KeyTag) error ```` ## File: internal/usecase/metrics/metrics_app.go ````go package metrics ⋮---- import ( "context" "time" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/server" ) ⋮---- "context" "time" ⋮---- "github.com/go-errors/errors" "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/server" ⋮---- type AppConfig struct { Address string `validate:"required"` ReadHeaderTimeout time.Duration `validate:"required,gt=0"` } ⋮---- func (c AppConfig) Validate() error ⋮---- type App struct { srv *server.MetricsServer } ⋮---- func NewApp(cfg AppConfig) (*App, error) ⋮---- func (a *App) Start(ctx context.Context) error ```` ## File: internal/usecase/metrics/metrics_grpc.go ````go package metrics ⋮---- import ( "context" "time" "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" "google.golang.org/grpc/status" ) ⋮---- "context" "time" ⋮---- "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" "google.golang.org/grpc/status" ⋮---- // GRPCMetrics holds Prometheus metrics for gRPC requests type GRPCMetrics struct { requestDuration *prometheus.HistogramVec requestsTotal *prometheus.CounterVec requestsInFlight *prometheus.GaugeVec } ⋮---- // UnaryServerInterceptor returns a gRPC unary interceptor for metrics collection func (m *Metrics) UnaryServerInterceptor() grpc.UnaryServerInterceptor ⋮---- // Track in-flight requests ⋮---- // Start timing ⋮---- // Call the handler ⋮---- // Calculate duration ⋮---- // Determine status code ⋮---- // Record metrics ⋮---- // StreamServerInterceptor returns a gRPC stream interceptor for metrics collection func (m *Metrics) StreamServerInterceptor() grpc.StreamServerInterceptor ```` ## File: internal/usecase/metrics/metrics.go ````go package metrics ⋮---- import ( "math/big" "strconv" "time" "github.com/prometheus/client_golang/prometheus" ) ⋮---- "math/big" "strconv" "time" ⋮---- "github.com/prometheus/client_golang/prometheus" ⋮---- type Config struct { Registerer prometheus.Registerer } ⋮---- type Metrics struct { GRPCMetrics // signatures and aggregation pkSignDuration prometheus.Summary appSignDuration prometheus.Summary onlyAggregateDuration prometheus.Summary appAggregationDuration prometheus.Summary aggregationProofSize *prometheus.HistogramVec // p2p p2pPeerMessagesSent *prometheus.CounterVec p2pSyncProcessedSignatures *prometheus.CounterVec p2pSyncRequestedHashes prometheus.Counter p2pSyncProcessedAggProofs *prometheus.CounterVec p2pSyncRequestedAggProofHashes prometheus.Counter // repo repoQueryDuration *prometheus.HistogramVec repoQueryTotalDuration *prometheus.HistogramVec // evm evmMethodCall *prometheus.HistogramVec evmCommitGasUsed *prometheus.HistogramVec evmCommitGasPrice *prometheus.HistogramVec } ⋮---- // signatures and aggregation ⋮---- // p2p ⋮---- // repo ⋮---- // evm ⋮---- func New(cfg Config) *Metrics ⋮---- func newMetrics(registerer prometheus.Registerer) *Metrics ⋮---- var all []prometheus.Collector ⋮---- 256, // 256B 512, // 512B 1024, // 1KB 2048, // 2KB 4096, // 4KB 8192, // 8KB 16384, // 16KB 32768, // 32KB 65536, // 64KB 131072, // 128KB 262144, // 256KB 393216, // 384KB 524288, // 512KB 786432, // 768KB 1048576, // 1MB ⋮---- func (m *Metrics) ObservePKSignDuration(d time.Duration) ⋮---- func (m *Metrics) ObserveAppSignDuration(d time.Duration) ⋮---- func (m *Metrics) ObserveOnlyAggregateDuration(d time.Duration) ⋮---- func (m *Metrics) ObserveAppAggregateDuration(d time.Duration) ⋮---- func (m *Metrics) ObserveP2PPeerMessageSent(messageType, status string) ⋮---- func (m *Metrics) ObserveEVMMethodCall(method string, chainID uint64, status string, d time.Duration) ⋮---- func (m *Metrics) ObserveCommitValsetHeaderParams(chainID uint64, gasUsed uint64, effectiveGasPrice *big.Int) ⋮---- func (m *Metrics) ObserveP2PSyncSignaturesProcessed(resultType string, count int) ⋮---- func (m *Metrics) ObserveP2PSyncRequestedHashes(count int) ⋮---- func (m *Metrics) ObserveP2PSyncAggregationProofsProcessed(resultType string, count int) ⋮---- func (m *Metrics) ObserveP2PSyncRequestedAggregationProofs(count int) ⋮---- func (m *Metrics) ObserveAggregationProofSize(proofSizeBytes int, activeValidatorCount int) ⋮---- func (m *Metrics) ObserveRepoQueryDuration(queryName, status string, d time.Duration) ⋮---- func (m *Metrics) ObserveRepoQueryTotalDuration(queryName, status string, d time.Duration) ```` ## File: internal/usecase/signature-listener/mocks/signature_listener_uc.go ````go // Code generated by MockGen. DO NOT EDIT. // Source: signature_listener_uc.go // // Generated by this command: ⋮---- // mockgen -source=signature_listener_uc.go -destination=mocks/signature_listener_uc.go -package=mocks ⋮---- // Package mocks is a generated GoMock package. package mocks ⋮---- import ( context "context" reflect "reflect" entity "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ) ⋮---- context "context" reflect "reflect" ⋮---- entity "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ⋮---- // Mockrepo is a mock of repo interface. type Mockrepo struct { ctrl *gomock.Controller recorder *MockrepoMockRecorder isgomock struct{} ⋮---- // MockrepoMockRecorder is the mock recorder for Mockrepo. type MockrepoMockRecorder struct { mock *Mockrepo } ⋮---- // NewMockrepo creates a new mock instance. func NewMockrepo(ctrl *gomock.Controller) *Mockrepo ⋮---- // EXPECT returns an object that allows the caller to indicate expected use. func (m *Mockrepo) EXPECT() *MockrepoMockRecorder ⋮---- // GetValidatorByKey mocks base method. func (m *Mockrepo) GetValidatorByKey(ctx context.Context, epoch entity.Epoch, keyTag entity.KeyTag, publicKey []byte) (entity.Validator, uint32, error) ⋮---- // GetValidatorByKey indicates an expected call of GetValidatorByKey. ⋮---- // GetValidatorSetByEpoch mocks base method. func (m *Mockrepo) GetValidatorSetByEpoch(ctx context.Context, epoch entity.Epoch) (entity.ValidatorSet, error) ⋮---- // GetValidatorSetByEpoch indicates an expected call of GetValidatorSetByEpoch. ⋮---- // MockentityProcessor is a mock of entityProcessor interface. type MockentityProcessor struct { ctrl *gomock.Controller recorder *MockentityProcessorMockRecorder isgomock struct{} ⋮---- // MockentityProcessorMockRecorder is the mock recorder for MockentityProcessor. type MockentityProcessorMockRecorder struct { mock *MockentityProcessor } ⋮---- // NewMockentityProcessor creates a new mock instance. func NewMockentityProcessor(ctrl *gomock.Controller) *MockentityProcessor ⋮---- // ProcessSignature mocks base method. func (m *MockentityProcessor) ProcessSignature(ctx context.Context, signature entity.Signature, self bool) error ⋮---- // ProcessSignature indicates an expected call of ProcessSignature. ```` ## File: internal/usecase/signature-listener/signature_listener_uc_test.go ````go package signature_listener ⋮---- import ( "crypto/rand" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/internal/client/repository/badger" intEntity "github.com/symbioticfi/relay/internal/entity" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "crypto/rand" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/internal/client/repository/badger" intEntity "github.com/symbioticfi/relay/internal/entity" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func TestHandleSignatureReceivedMessage_HappyPath(t *testing.T) ⋮---- // Create real private key for signing ⋮---- // Create signature with the private key ⋮---- // Create validator set with the matching public key ⋮---- // Create P2P message with real signature ⋮---- // Execute ⋮---- // Verify that signature was saved ⋮---- // Verify the signature matches what we expect ⋮---- // Verify that signature map was updated ⋮---- type testSetup struct { repo *badger.Repository useCase *SignatureListenerUseCase } ⋮---- func newTestSetup(t *testing.T) *testSetup ⋮---- // Create mock aggregator for entity processor ⋮---- // Create mock aggregation proof signal for entity processor ⋮---- // Create mock signature processed signal for entity processor ⋮---- func newPrivateKey(t *testing.T) crypto.PrivateKey ⋮---- func (setup *testSetup) createTestValidatorSetWithKey(t *testing.T, privateKey crypto.PrivateKey) symbiotic.ValidatorSet ⋮---- // Save the validator set to the repository ⋮---- func createTestP2PMessageWithSignature(privateKey crypto.PrivateKey, hash []byte, signature []byte) intEntity.P2PMessage[symbiotic.Signature] ```` ## File: internal/usecase/signature-listener/signature_listener_uc.go ````go package signature_listener ⋮---- import ( "context" "log/slog" "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" ⋮---- "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- //go:generate mockgen -source=signature_listener_uc.go -destination=mocks/signature_listener_uc.go -package=mocks ⋮---- type repo interface { GetValidatorByKey(ctx context.Context, epoch symbiotic.Epoch, keyTag symbiotic.KeyTag, publicKey []byte) (symbiotic.Validator, uint32, error) GetValidatorSetByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) } ⋮---- type entityProcessor interface { ProcessSignature(ctx context.Context, signature symbiotic.Signature, self bool) error } ⋮---- type Config struct { Repo repo `validate:"required"` EntityProcessor entityProcessor `validate:"required"` SignalCfg signals.Config `validate:"required"` SelfP2PID string `validate:"required"` } ⋮---- type SignatureListenerUseCase struct { cfg Config } ⋮---- func New(cfg Config) (*SignatureListenerUseCase, error) ⋮---- func (s *SignatureListenerUseCase) HandleSignatureReceivedMessage(ctx context.Context, p2pMsg entity.P2PMessage[symbiotic.Signature]) error ⋮---- // ignore if signature already exists ```` ## File: internal/usecase/signer-app/mocks/signer_app.go ````go // Code generated by MockGen. DO NOT EDIT. // Source: signer_app.go // // Generated by this command: ⋮---- // mockgen -source=signer_app.go -destination=mocks/signer_app.go -package=mocks ⋮---- // Package mocks is a generated GoMock package. package mocks ⋮---- import ( context "context" reflect "reflect" time "time" common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/symbiotic/entity" crypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" gomock "go.uber.org/mock/gomock" ) ⋮---- context "context" reflect "reflect" time "time" ⋮---- common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/symbiotic/entity" crypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" gomock "go.uber.org/mock/gomock" ⋮---- // Mockrepo is a mock of repo interface. type Mockrepo struct { ctrl *gomock.Controller recorder *MockrepoMockRecorder isgomock struct{} ⋮---- // MockrepoMockRecorder is the mock recorder for Mockrepo. type MockrepoMockRecorder struct { mock *Mockrepo } ⋮---- // NewMockrepo creates a new mock instance. func NewMockrepo(ctrl *gomock.Controller) *Mockrepo ⋮---- // EXPECT returns an object that allows the caller to indicate expected use. func (m *Mockrepo) EXPECT() *MockrepoMockRecorder ⋮---- // GetSignaturePending mocks base method. func (m *Mockrepo) GetSignaturePending(ctx context.Context, limit int) ([]common.Hash, error) ⋮---- // GetSignaturePending indicates an expected call of GetSignaturePending. ⋮---- // GetSignatureRequest mocks base method. func (m *Mockrepo) GetSignatureRequest(ctx context.Context, requestID common.Hash) (entity.SignatureRequest, error) ⋮---- // GetSignatureRequest indicates an expected call of GetSignatureRequest. ⋮---- // GetValidatorSetByEpoch mocks base method. func (m *Mockrepo) GetValidatorSetByEpoch(ctx context.Context, epoch entity.Epoch) (entity.ValidatorSet, error) ⋮---- // GetValidatorSetByEpoch indicates an expected call of GetValidatorSetByEpoch. ⋮---- // RemoveSignaturePending mocks base method. func (m *Mockrepo) RemoveSignaturePending(ctx context.Context, epoch entity.Epoch, requestID common.Hash) error ⋮---- // RemoveSignaturePending indicates an expected call of RemoveSignaturePending. ⋮---- // SaveSignatureRequest mocks base method. func (m *Mockrepo) SaveSignatureRequest(ctx context.Context, requestID common.Hash, req entity.SignatureRequest) error ⋮---- // SaveSignatureRequest indicates an expected call of SaveSignatureRequest. ⋮---- // Mockp2pService is a mock of p2pService interface. type Mockp2pService struct { ctrl *gomock.Controller recorder *Mockp2pServiceMockRecorder isgomock struct{} ⋮---- // Mockp2pServiceMockRecorder is the mock recorder for Mockp2pService. type Mockp2pServiceMockRecorder struct { mock *Mockp2pService } ⋮---- // NewMockp2pService creates a new mock instance. func NewMockp2pService(ctrl *gomock.Controller) *Mockp2pService ⋮---- // BroadcastSignatureGeneratedMessage mocks base method. func (m *Mockp2pService) BroadcastSignatureGeneratedMessage(ctx context.Context, msg entity.Signature) error ⋮---- // BroadcastSignatureGeneratedMessage indicates an expected call of BroadcastSignatureGeneratedMessage. ⋮---- // MockkeyProvider is a mock of keyProvider interface. type MockkeyProvider struct { ctrl *gomock.Controller recorder *MockkeyProviderMockRecorder isgomock struct{} ⋮---- // MockkeyProviderMockRecorder is the mock recorder for MockkeyProvider. type MockkeyProviderMockRecorder struct { mock *MockkeyProvider } ⋮---- // NewMockkeyProvider creates a new mock instance. func NewMockkeyProvider(ctrl *gomock.Controller) *MockkeyProvider ⋮---- // GetOnchainKeyFromCache mocks base method. func (m *MockkeyProvider) GetOnchainKeyFromCache(keyTag entity.KeyTag) (entity.CompactPublicKey, error) ⋮---- // GetOnchainKeyFromCache indicates an expected call of GetOnchainKeyFromCache. ⋮---- // GetPrivateKey mocks base method. func (m *MockkeyProvider) GetPrivateKey(keyTag entity.KeyTag) (crypto.PrivateKey, error) ⋮---- // GetPrivateKey indicates an expected call of GetPrivateKey. ⋮---- // Mockmetrics is a mock of metrics interface. type Mockmetrics struct { ctrl *gomock.Controller recorder *MockmetricsMockRecorder isgomock struct{} ⋮---- // MockmetricsMockRecorder is the mock recorder for Mockmetrics. type MockmetricsMockRecorder struct { mock *Mockmetrics } ⋮---- // NewMockmetrics creates a new mock instance. func NewMockmetrics(ctrl *gomock.Controller) *Mockmetrics ⋮---- // ObserveAppSignDuration mocks base method. func (m *Mockmetrics) ObserveAppSignDuration(d time.Duration) ⋮---- // ObserveAppSignDuration indicates an expected call of ObserveAppSignDuration. ⋮---- // ObservePKSignDuration mocks base method. func (m *Mockmetrics) ObservePKSignDuration(d time.Duration) ⋮---- // ObservePKSignDuration indicates an expected call of ObservePKSignDuration. ⋮---- // MockentityProcessor is a mock of entityProcessor interface. type MockentityProcessor struct { ctrl *gomock.Controller recorder *MockentityProcessorMockRecorder isgomock struct{} ⋮---- // MockentityProcessorMockRecorder is the mock recorder for MockentityProcessor. type MockentityProcessorMockRecorder struct { mock *MockentityProcessor } ⋮---- // NewMockentityProcessor creates a new mock instance. func NewMockentityProcessor(ctrl *gomock.Controller) *MockentityProcessor ⋮---- // ProcessAggregationProof mocks base method. func (m *MockentityProcessor) ProcessAggregationProof(ctx context.Context, proof entity.AggregationProof) error ⋮---- // ProcessAggregationProof indicates an expected call of ProcessAggregationProof. ⋮---- // ProcessSignature mocks base method. func (m *MockentityProcessor) ProcessSignature(ctx context.Context, signature entity.Signature, self bool) error ⋮---- // ProcessSignature indicates an expected call of ProcessSignature. ```` ## File: internal/usecase/signer-app/signer_app_handle_signature_aggregated_message.go ````go package signer_app ⋮---- import ( "context" "log/slog" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" ⋮---- "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (s *SignerApp) HandleSignaturesAggregatedMessage(ctx context.Context, p2pMsg entity.P2PMessage[symbiotic.AggregationProof]) error ⋮---- // if the aggregation proof already exists, we have already seen the message and broadcasted it so short-circuit ```` ## File: internal/usecase/signer-app/signer_app_test.go ````go package signer_app ⋮---- import ( "crypto/rand" "log/slog" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/samber/lo" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/internal/client/repository/badger" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" entity_mocks "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/signer-app/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "crypto/rand" "log/slog" "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/samber/lo" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/internal/client/repository/badger" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" entity_mocks "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/internal/usecase/signer-app/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func TestSign_HappyPath(t *testing.T) ⋮---- // Add the private key to the real key provider ⋮---- // Mock the remaining dependencies ⋮---- // Sign ⋮---- // Verify that signature request was saved ⋮---- // Verify that signature is correct ⋮---- type testSetup struct { ctrl *gomock.Controller repo *badger.Repository keyProvider *keyprovider.SimpleKeystoreProvider mockP2P *mocks.Mockp2pService mockMetrics *mocks.Mockmetrics app *SignerApp } ⋮---- func newTestSetup(t *testing.T) *testSetup ⋮---- // Create mocks for other dependencies ⋮---- // Create mock aggregator for entity processor ⋮---- // Create mock aggregation proof signal for entity processor ⋮---- // Create mock signature processed signal for entity processor ⋮---- func createTestSignatureRequest(msg string) symbiotic.SignatureRequest ⋮---- func newPrivateKey(t *testing.T) crypto.PrivateKey ⋮---- func createTestValidatorSet(t *testing.T, setup *testSetup, privateKey crypto.PrivateKey) symbiotic.ValidatorSet ```` ## File: internal/usecase/signer-app/signer_app.go ````go package signer_app ⋮---- import ( "context" "log/slog" "time" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" "k8s.io/client-go/util/workqueue" ) ⋮---- "context" "log/slog" "time" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" validate "github.com/go-playground/validator/v10" "k8s.io/client-go/util/workqueue" ⋮---- //go:generate mockgen -source=signer_app.go -destination=mocks/signer_app.go -package=mocks ⋮---- type repo interface { SaveSignatureRequest(ctx context.Context, requestID common.Hash, req symbiotic.SignatureRequest) error RemoveSignaturePending(ctx context.Context, epoch symbiotic.Epoch, requestID common.Hash) error GetSignaturePending(ctx context.Context, limit int) ([]common.Hash, error) GetSignatureRequest(ctx context.Context, requestID common.Hash) (symbiotic.SignatureRequest, error) GetValidatorSetByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) } ⋮---- type p2pService interface { BroadcastSignatureGeneratedMessage(ctx context.Context, msg symbiotic.Signature) error } ⋮---- type keyProvider interface { GetPrivateKey(keyTag symbiotic.KeyTag) (crypto.PrivateKey, error) GetOnchainKeyFromCache(keyTag symbiotic.KeyTag) (symbiotic.CompactPublicKey, error) } ⋮---- type metrics interface { ObservePKSignDuration(d time.Duration) ObserveAppSignDuration(d time.Duration) } ⋮---- type entityProcessor interface { ProcessSignature(ctx context.Context, signature symbiotic.Signature, self bool) error ProcessAggregationProof(ctx context.Context, proof symbiotic.AggregationProof) error } ⋮---- type Config struct { KeyProvider keyProvider `validate:"required"` Repo repo `validate:"required"` EntityProcessor entityProcessor `validate:"required"` Metrics metrics `validate:"required"` } ⋮---- func (c Config) Validate() error ⋮---- type SignerApp struct { cfg Config queue *workqueue.Typed[common.Hash] } ⋮---- func NewSignerApp(cfg Config) (*SignerApp, error) ⋮---- // RequestSignature creates a signature request and queues it for signing, returns requestID // The actual signing is done in the background by workers func (s *SignerApp) RequestSignature(ctx context.Context, req symbiotic.SignatureRequest) (common.Hash, error) ⋮---- // does not return the actual signature yet ⋮---- func (s *SignerApp) completeSign(ctx context.Context, req symbiotic.SignatureRequest, p2pService p2pService) error ⋮---- func (s *SignerApp) HandleSignatureRequests(ctx context.Context, workerCount int, p2pService p2pService) error ⋮---- // start workers ⋮---- func (s *SignerApp) worker(ctx context.Context, id int, p2pService p2pService) ⋮---- func (s *SignerApp) handleMissedSignaturesOnce(ctx context.Context) error ```` ## File: internal/usecase/sync-provider/sync_provider_build_want_aggregation_proofs_request.go ````go package sync_provider ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // BuildWantAggregationProofsRequest builds a request for missing aggregation proofs from recent epochs func (s *Syncer) BuildWantAggregationProofsRequest(ctx context.Context) (entity.WantAggregationProofsRequest, error) ⋮---- // Get the latest epoch ⋮---- var allRequestIDs []common.Hash ⋮---- // Iterate through epochs from newest to oldest to prioritize recent requests ⋮---- var lastHash common.Hash ⋮---- // Paginate through signature requests without aggregation proofs for this epoch ⋮---- break // No more requests for this epoch ⋮---- // Collect request ids ⋮---- continue // Skip non-aggregation requests ⋮---- // check if proof exists ⋮---- // remove pending from db ⋮---- // ignore not found and tx conflict errors, as they indicate the proof was already processed or is being processed ⋮---- continue // Proof already exists, skip ⋮---- lastHash = req.RequestID // Update for pagination ⋮---- // Handle epoch == 0 to avoid underflow in unsigned arithmetic ```` ## File: internal/usecase/sync-provider/sync_provider_build_want_signatures_map.go ````go package sync_provider ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (s *Syncer) BuildWantSignaturesRequest(ctx context.Context) (entity.WantSignaturesRequest, error) ⋮---- // Collect all pending signature requests across epochs ⋮---- // buildWantSignaturesMap constructs a map of request id to missing validator bitmaps // for pending signature requests across multiple epochs. // // The method performs the following operations: // 1. Determines the epoch range to scan (from latest epoch back to EpochsToSync epochs) // 2. Iterates through epochs from newest to oldest to prioritize recent requests // 3. For each epoch, fetches pending signature requests in batches // 4. For each request, identifies validators that haven't provided signatures yet // 5. Builds a map where keys are request ids and values are bitmaps of missing validators ⋮---- // The scanning is limited by MaxSignatureRequestsPerSync to prevent excessive memory usage // and network overhead during synchronization. ⋮---- // Behavior: // - Scans epochs in reverse order (newest first) to prioritize recent requests // - Stops scanning when MaxSignatureRequestsPerSync limit is reached // - Only includes requests that have missing signatures (non-empty bitmaps) // - Uses pagination to handle large numbers of requests per epoch func (s *Syncer) buildWantSignaturesMap(ctx context.Context) (map[common.Hash]entity.Bitmap, error) ⋮---- // Get the latest epoch ⋮---- // Calculate the starting epoch (go back EpochsToSync epochs) var startEpoch symbiotic.Epoch ⋮---- var lastHash common.Hash ⋮---- // Process each request to find missing signatures ⋮---- // Get current signature map ⋮---- // No signatures yet, all validators are missing ⋮---- // Get missing validators from signature map ⋮---- // If we got fewer requests than requested, we've reached the end for this epoch ```` ## File: internal/usecase/sync-provider/sync_provider_handle_want_aggregation_proofs_request.go ````go package sync_provider ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // HandleWantAggregationProofsRequest handles incoming requests for aggregation proofs from peers func (s *Syncer) HandleWantAggregationProofsRequest(ctx context.Context, request entity.WantAggregationProofsRequest) (entity.WantAggregationProofsResponse, error) ⋮---- // Process each requested hash ⋮---- // Stop if we've reached the maximum response count ⋮---- // Try to get the aggregation proof ⋮---- // Aggregation proof not found, skip this request ⋮---- // Add the proof to the response ```` ## File: internal/usecase/sync-provider/sync_provider_handle_want_signatures.go ````go package sync_provider ⋮---- import ( "context" "log/slog" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" ) ⋮---- "context" "log/slog" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" ⋮---- // HandleWantSignaturesRequest processes a peer's request for missing signatures and returns // the requested signatures that are available in local storage. // // The method performs the following operations: // 1. Iterates through each request id in the incoming request // 2. For each requested validator index, directly retrieves the signature using GetSignatureByIndex // 3. Builds a response containing validator signatures organized by request id ⋮---- // The response is limited by MaxResponseSignatureCount to prevent memory exhaustion // and network congestion during P2P synchronization. ⋮---- // Behavior: // - Processes requests in iteration order (map iteration is non-deterministic) // - Stops processing when MaxResponseSignatureCount limit is reached // - Skips validator indices where signatures are not found locally // - Returns empty signatures map for request ids where no matching signatures are found func (s *Syncer) HandleWantSignaturesRequest(ctx context.Context, request entity.WantSignaturesRequest) (entity.WantSignaturesResponse, error) ⋮---- // Check signature count limit before processing each request ⋮---- var validatorSigs []entity.ValidatorSignature ⋮---- // Iterate over requested validator indices and get signatures directly ⋮---- // Check limit before processing each signature ⋮---- // Get signature by validator index directly ⋮---- // Signature not found for this validator index, skip ```` ## File: internal/usecase/sync-provider/sync_provider_process_received_aggregation_proofs.go ````go package sync_provider ⋮---- import ( "context" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- // ProcessReceivedAggregationProofs processes aggregation proofs received from peers func (s *Syncer) ProcessReceivedAggregationProofs(ctx context.Context, response entity.WantAggregationProofsResponse) (entity.AggregationProofProcessingStats, error) ⋮---- // Process each received aggregation proof ⋮---- // processSingleAggregationProof processes a single aggregation proof func (s *Syncer) processSingleAggregationProof(ctx context.Context, proof symbiotic.AggregationProof, stats *entity.AggregationProofProcessingStats) ⋮---- // Process the aggregation proof using the signature processor ⋮---- return // Continue processing other proofs ```` ## File: internal/usecase/sync-provider/sync_provider_process_received_signatures.go ````go package sync_provider ⋮---- import ( "context" "log/slog" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" ) ⋮---- "context" "log/slog" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" ⋮---- // ProcessReceivedSignatures validates and processes signatures received from peer nodes during // synchronization, updating local storage and tracking statistics for monitoring. // // The method performs the following validation and processing steps: // 1. Validates that received signatures were actually requested (hash and validator index matching) // 2. Retrieves original signature request metadata (epoch, key type, etc.) // 3. Reconstructs and validates public keys from signature data // 4. Cross-references validator information to ensure consistency // 5. Processes valid signatures through the signature processor // 6. Emits signature received signals for downstream components // 7. Tracks comprehensive statistics for all outcomes ⋮---- // The method is designed to be resilient against malformed or malicious peer responses, // validating all received data before processing and continuing on errors. ⋮---- // Behavior: // - Validates all received signatures against original requests // - Skips invalid signatures and continues processing others // - Handles duplicate signatures gracefully (tracks but doesn't error) // - Emits signals for successfully processed signatures // - Returns comprehensive statistics for monitoring and debugging // - Logs warnings for validation failures and errors func (s *Syncer) ProcessReceivedSignatures(ctx context.Context, response entity.WantSignaturesResponse, wantSignatures map[common.Hash]entity.Bitmap) entity.SignatureProcessingStats ⋮---- var stats entity.SignatureProcessingStats ⋮---- // Validate that we actually requested this validator's signature ⋮---- // Get the original signature request to extract epoch and other details ```` ## File: internal/usecase/sync-provider/sync_provider_test.go ````go package sync_provider ⋮---- import ( "crypto/rand" "fmt" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/internal/client/repository/badger" "github.com/symbioticfi/relay/internal/entity" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "crypto/rand" "fmt" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/internal/client/repository/badger" "github.com/symbioticfi/relay/internal/entity" entity_processor "github.com/symbioticfi/relay/internal/usecase/entity-processor" "github.com/symbioticfi/relay/internal/usecase/entity-processor/mocks" "github.com/symbioticfi/relay/pkg/signals" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- func TestAskSignatures_HandleWantSignaturesRequest_Integration(t *testing.T) ⋮---- // Create test data ⋮---- // Save signature request and signature on peer ⋮---- // Save signature request on both repos so peer can respond to requests ⋮---- // Requester needs SignatureMap for BuildWantSignaturesRequest to work ⋮---- // Create peer syncer first (with a temporary mock) ⋮---- // Create requester syncer ⋮---- // Verify requester initially has no signatures ⋮---- require.Len(t, initialSignatures, 1) // Already has one signature from param1 ⋮---- // Verify requester has signature request ⋮---- // Call BuildWantSignaturesRequest on requester ⋮---- // Verify requester now has the signature ⋮---- // Verify the signature is correct ⋮---- func createMockAggregator(t *testing.T) *mocks.MockAggregator ⋮---- // Default behavior: return true for verification ⋮---- func createMockAggProofSignal(t *testing.T) *mocks.MockAggProofSignal ⋮---- // Default behavior: return nil for emit ⋮---- func createMockSignatureProcessedSignal(t *testing.T) *signals.Signal[symbiotic.Signature] ⋮---- func createTestRepo(t *testing.T) *badger.Repository ⋮---- func createTestSignatureRequest(t *testing.T) symbiotic.SignatureRequest ⋮---- Message: randomBytes(t, 100), // Random message makes each request unique ⋮---- func newPrivateKey(t *testing.T) crypto.PrivateKey ⋮---- func createTestValidatorSet(t *testing.T, privateKey ...crypto.PrivateKey) symbiotic.ValidatorSet ⋮---- func createTestValidatorSetWithMultipleValidators(t *testing.T, count int) (symbiotic.ValidatorSet, []crypto.PrivateKey) ⋮---- Payload: privateKey.PublicKey().OnChain(), // Same key for all validators for simplicity ⋮---- func randomBytes(t *testing.T, n int) []byte ⋮---- func TestHandleWantSignaturesRequest_EmptyRequest(t *testing.T) ⋮---- func TestHandleWantSignaturesRequest_MaxResponseSignatureCountLimit(t *testing.T) ⋮---- // Create test data with multiple signatures validatorSet, privateKeys := createTestValidatorSetWithMultipleValidators(t, 5) // Create 5 validators ⋮---- // Setup repository with validator set and signature request ⋮---- // Store multiple signatures by validator index ⋮---- var requestID common.Hash // Save signatures for multiple validator indices (simulate multiple validators) ⋮---- MaxResponseSignatureCount: 2, // Low limit ⋮---- requestID: entity.NewBitmapOf(0, 1, 2, 3, 4), // Request all 5 signatures ⋮---- require.Len(t, response.Signatures[requestID], 2) // Should return only 2 signatures due to limit ⋮---- MaxResponseSignatureCount: 3, // Allow 3 signatures ⋮---- requestID: entity.NewBitmapOf(0, 1, 2), // Request exactly 3 signatures ⋮---- func TestHandleWantSignaturesRequest_MultipleRequestIDs(t *testing.T) ⋮---- // Store signatures for both requests ⋮---- validatorSet, privateKeys := createTestValidatorSetWithMultipleValidators(t, 2) // Create 2 validators ⋮---- // Setup repository ⋮---- // Save signature for first request ⋮---- // Save signature for second request ⋮---- param1.RequestID(): entity.NewBitmapOf(0), // Request validator 0 from first request param2.RequestID(): entity.NewBitmapOf(1), // Request validator 1 from second request ⋮---- func TestHandleWantSignaturesRequest_PartialSignatureAvailability(t *testing.T) ⋮---- validatorSet, privateKeys := createTestValidatorSetWithMultipleValidators(t, 4) // Create 4 validators ⋮---- // Save signatures only for validator indices 0 and 2 (skip 1 and 3) ⋮---- requestID: entity.NewBitmapOf(0, 1, 2, 3), // Request all 4, but only 0 and 2 exist ⋮---- // Check that we got the right validator indices ```` ## File: internal/usecase/sync-provider/sync_provider.go ````go package sync_provider ⋮---- import ( "context" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/internal/entity" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type repo interface { GetSignatureMap(ctx context.Context, requestID common.Hash) (entity.SignatureMap, error) GetLatestValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) GetSignatureRequest(ctx context.Context, requestID common.Hash) (symbiotic.SignatureRequest, error) GetValidatorByKey(ctx context.Context, epoch symbiotic.Epoch, keyTag symbiotic.KeyTag, publicKey []byte) (symbiotic.Validator, uint32, error) GetAllSignatures(ctx context.Context, requestID common.Hash) ([]symbiotic.Signature, error) GetSignatureByIndex(ctx context.Context, requestID common.Hash, validatorIndex uint32) (symbiotic.Signature, error) GetSignatureRequestsWithoutAggregationProof(ctx context.Context, epoch symbiotic.Epoch, limit int, lastHash common.Hash) ([]symbiotic.SignatureRequestWithID, error) GetAggregationProof(ctx context.Context, requestID common.Hash) (symbiotic.AggregationProof, error) RemoveAggregationProofPending(ctx context.Context, epoch symbiotic.Epoch, requestID common.Hash) error } ⋮---- type entityProcessor interface { ProcessSignature(ctx context.Context, signature symbiotic.Signature, self bool) error ProcessAggregationProof(ctx context.Context, proof symbiotic.AggregationProof) error } ⋮---- type Config struct { Repo repo `validate:"required"` EntityProcessor entityProcessor `validate:"required"` EpochsToSync uint64 `validate:"gte=0"` MaxSignatureRequestsPerSync int `validate:"gt=0"` MaxResponseSignatureCount int `validate:"gt=0"` MaxAggProofRequestsPerSync int `validate:"gt=0"` MaxResponseAggProofCount int `validate:"gt=0"` } ⋮---- type Syncer struct { cfg Config } ⋮---- func New(cfg Config) (*Syncer, error) ```` ## File: internal/usecase/sync-runner/sync_runner.go ````go package sync_runner ⋮---- import ( "context" "log/slog" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" ) ⋮---- "context" "log/slog" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" ⋮---- type p2pService interface { SendWantSignaturesRequest(ctx context.Context, request entity.WantSignaturesRequest) (entity.WantSignaturesResponse, error) SendWantAggregationProofsRequest(ctx context.Context, request entity.WantAggregationProofsRequest) (entity.WantAggregationProofsResponse, error) } ⋮---- type provider interface { BuildWantSignaturesRequest(ctx context.Context) (entity.WantSignaturesRequest, error) ProcessReceivedSignatures(ctx context.Context, response entity.WantSignaturesResponse, wantSignatures map[common.Hash]entity.Bitmap) entity.SignatureProcessingStats BuildWantAggregationProofsRequest(ctx context.Context) (entity.WantAggregationProofsRequest, error) ProcessReceivedAggregationProofs(ctx context.Context, response entity.WantAggregationProofsResponse) (entity.AggregationProofProcessingStats, error) } ⋮---- type metrics interface { ObserveP2PSyncSignaturesProcessed(resultType string, count int) ObserveP2PSyncRequestedHashes(count int) ObserveP2PSyncAggregationProofsProcessed(resultType string, count int) ObserveP2PSyncRequestedAggregationProofs(count int) } ⋮---- type Config struct { Enabled bool P2PService p2pService `validate:"required"` Provider provider `validate:"required"` SyncPeriod time.Duration `validate:"gt=0"` SyncTimeout time.Duration `validate:"gt=0"` Metrics metrics `validate:"required"` } ⋮---- type Runner struct { cfg Config } ⋮---- func New(cfg Config) (*Runner, error) ⋮---- func (s *Runner) Start(ctx context.Context) error ⋮---- // Run signature sync ⋮---- // Run aggregation proof sync independently ⋮---- func (s *Runner) runSignatureSync(ctx context.Context) error ⋮---- // Create context with timeout for signature sync ⋮---- func (s *Runner) runAggregationProofSync(ctx context.Context) error ⋮---- // Create context with timeout for aggregation proof sync ```` ## File: internal/usecase/valset-listener/valset_generator_handle_agg_proof.go ````go package valset_listener ⋮---- import ( "context" "log/slog" "time" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" "time" ⋮---- "github.com/go-errors/errors" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( minCommitterPollIntervalSeconds = uint64(5) ⋮---- func (s *Service) StartCommitterLoop(ctx context.Context) error ⋮---- // get the latest epoch and try to find schedule of committers and start committing ⋮---- // force to tick immediately as soon as it starts ⋮---- // get latest known valset ⋮---- // if latest valset is already committed, nothing to do ⋮---- // get lat committed epoch // TODO(oxsteins): if this is too slow, might have to update status-tracker to catchup quickly and store last committed epoch in db // currently it is polling one by one and asynchronously so might not catchup early enough for committer to work // (alrxy) i think it's better to do in listener cuz listener provides valsets and configs, it will be more consistent ⋮---- func (s *Service) processPendingProof(ctx context.Context, proofKey symbiotic.ProofCommitKey) error ⋮---- // get proof ⋮---- func (s *Service) detectLastCommittedEpoch(ctx context.Context, config symbiotic.NetworkConfig) symbiotic.Epoch ⋮---- // skip chain if networking issue, we will recheck again anyway and if the rpc/chain recovers we will detect issue later ⋮---- // commitValsetToAllSettlements commits the validator set header to all configured settlement chains. // // Performance Optimization: This method uses entity.BlockNumberLatest instead of finalized blocks // when checking commitment status. This optimization reduces latency by ~12-15 seconds // on Ethereum (approximately 2 finalization epochs), allowing faster detection of already-committed // headers and reducing unnecessary duplicate commitment transactions. ⋮---- // Safety: The pending proof cleanup happens separately in the status tracker, which uses finalized // blocks to verify commitments before removing pending proofs. This ensures data consistency: // - This method: uses latest blocks for fast pre-flight checks (avoid duplicate tx submissions) // - Status tracker: uses finalized blocks for authoritative verification (safe pending proof removal) ⋮---- // Trade-off: Using latest blocks for pre-flight checks introduces a small reorg risk, but this is // acceptable because: // 1. False positives (thinking a header is committed when it's not due to reorg) may trigger a // duplicate transaction, but the contract will reject it // 2. False negatives (missing a commitment due to reorg) will be corrected in the next iteration // 3. The performance benefit of reduced latency outweighs the minimal reorg risk // 4. Final cleanup only happens after finalized block confirmation in the status tracker func (s *Service) commitValsetToAllSettlements(ctx context.Context, config symbiotic.NetworkConfig, header symbiotic.ValidatorSetHeader, extraData []symbiotic.ExtraData, proof []byte) error ⋮---- // todo replace it with tx check instead of call to contract // if commit tx was sent but still not finalized this check will // return false positive and trigger one more commitment tx ```` ## File: internal/usecase/valset-listener/valset_listener_uc.go ````go package valset_listener ⋮---- import ( "context" "log/slog" "math/big" "sync" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/signals" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" "log/slog" "math/big" "sync" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/pkg/signals" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- type signer interface { RequestSignature(ctx context.Context, req symbiotic.SignatureRequest) (common.Hash, error) } ⋮---- type repo interface { GetLatestValidatorSetHeader(_ context.Context) (symbiotic.ValidatorSetHeader, error) GetOldestValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) GetLatestSignedValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) GetValidatorSetByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) GetValidatorSetMetadata(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSetMetadata, error) GetConfigByEpoch(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) GetAggregationProof(ctx context.Context, requestID common.Hash) (symbiotic.AggregationProof, error) SaveLatestSignedValidatorSetEpoch(_ context.Context, valset symbiotic.ValidatorSet) error SaveProof(ctx context.Context, aggregationProof symbiotic.AggregationProof) error SaveProofCommitPending(ctx context.Context, epoch symbiotic.Epoch, requestID common.Hash) error GetPendingProofCommitsSinceEpoch(ctx context.Context, epoch symbiotic.Epoch, limit int) ([]symbiotic.ProofCommitKey, error) RemoveProofCommitPending(ctx context.Context, epoch symbiotic.Epoch) error SaveValidatorSetMetadata(ctx context.Context, data symbiotic.ValidatorSetMetadata) error SaveConfig(ctx context.Context, config symbiotic.NetworkConfig, epoch symbiotic.Epoch) error SaveValidatorSet(ctx context.Context, valset symbiotic.ValidatorSet) error } ⋮---- type deriver interface { GetValidatorSet(ctx context.Context, epoch symbiotic.Epoch, config symbiotic.NetworkConfig) (symbiotic.ValidatorSet, error) GetNetworkData(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.NetworkData, error) } ⋮---- type metrics interface { ObserveAggregationProofSize(proofSize int, validatorCount int) } ⋮---- type keyProvider interface { GetPrivateKey(keyTag symbiotic.KeyTag) (crypto.PrivateKey, error) GetOnchainKeyFromCache(keyTag symbiotic.KeyTag) (symbiotic.CompactPublicKey, error) } ⋮---- type Config struct { EvmClient evm.IEvmClient `validate:"required"` Repo repo `validate:"required"` Deriver deriver `validate:"required"` PollingInterval time.Duration `validate:"required,gt=0"` Signer signer `validate:"required"` ValidatorSet *signals.Signal[symbiotic.ValidatorSet] `validate:"required"` KeyProvider keyProvider Aggregator aggregator.Aggregator Metrics metrics `validate:"required"` ForceCommitter bool EpochRetentionCount uint64 } ⋮---- func (c Config) Validate() error ⋮---- type Service struct { cfg Config mutex sync.Mutex } ⋮---- func New(cfg Config) (*Service, error) ⋮---- // LoadAllMissingEpochs runs tryLoadMissingEpochs until all missing epochs are loaded successfully func (s *Service) LoadAllMissingEpochs(ctx context.Context) error ⋮---- const maxRetries = 10 ⋮---- func (s *Service) Start(ctx context.Context) error ⋮---- func (s *Service) determineStartupSyncRange(ctx context.Context) (from symbiotic.Epoch, to symbiotic.Epoch, err error) ⋮---- func (s *Service) determineSteadySyncRange(ctx context.Context) (from symbiotic.Epoch, to symbiotic.Epoch, err error) ⋮---- func (s *Service) determineSyncRangeFromLatestWithHeader( ctx context.Context, latestHeader symbiotic.ValidatorSetHeader, currentEpoch symbiotic.Epoch, ) (from symbiotic.Epoch, to symbiotic.Epoch, err error) ⋮---- func (s *Service) tryLoadMissingEpochs(ctx context.Context, nextEpoch, currentEpoch symbiotic.Epoch) (time.Duration, error) ⋮---- // locking up mutex to prevent concurrent processing ⋮---- var ( prevValset symbiotic.ValidatorSet err error ) ⋮---- // we couldn't find previous valset in repo, maybe we start fresh node with empty db ⋮---- var ( latestEpochConfig *symbiotic.NetworkConfig latestEpochTimestamp *uint64 ) ⋮---- func (s *Service) process(ctx context.Context, prevValSet symbiotic.ValidatorSet, valSet symbiotic.ValidatorSet, config symbiotic.NetworkConfig) error ⋮---- // if we are a signer, sign the commitment, otherwise just save the metadata ⋮---- // save pending proof commit here // we store pending commit request for all nodes and not just current commiters because // if committers of this epoch fail then commiters for next epoch should still try to commit old proofs ⋮---- func (s *Service) getNetworkData(ctx context.Context, config symbiotic.NetworkConfig) (symbiotic.NetworkData, error) ⋮---- func (s *Service) headerCommitmentData( networkData symbiotic.NetworkData, header symbiotic.ValidatorSetHeader, extraData []symbiotic.ExtraData, ) ([]byte, error) ⋮---- func (s *Service) derive(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, symbiotic.NetworkConfig, error) ```` ## File: internal/usecase/valset-status-tracker/status_tracker.go ````go package valsetStatusTracker ⋮---- import ( "context" "log/slog" "math" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" "math" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/pkg/log" "github.com/symbioticfi/relay/symbiotic/client/evm" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- var zeroHeaderHash = common.HexToHash("0x868e09d528a16744c1f38ea3c10cc2251e01a456434f91172247695087d129b7") ⋮---- type repo interface { GetConfigByEpoch(_ context.Context, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) GetValidatorSetByEpoch(_ context.Context, epoch symbiotic.Epoch) (symbiotic.ValidatorSet, error) UpdateValidatorSetStatus(ctx context.Context, valset symbiotic.ValidatorSet) error UpdateValidatorSetStatusAndRemovePendingProof(ctx context.Context, valset symbiotic.ValidatorSet) error GetFirstUncommittedValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) SaveFirstUncommittedValidatorSetEpoch(_ context.Context, epoch symbiotic.Epoch) error GetLatestValidatorSetEpoch(ctx context.Context) (symbiotic.Epoch, error) } ⋮---- type Config struct { EvmClient evm.IEvmClient `validate:"required"` Repo repo `validate:"required"` PollingInterval time.Duration `validate:"required,gt=0"` } ⋮---- type Service struct { cfg Config } ⋮---- func (c Config) Validate() error ⋮---- func New(cfg Config) (*Service, error) ⋮---- // TrackMissingEpochsStatuses runs trackCommittedEpochs until all missing epochs statuses are loaded successfully func (s *Service) TrackMissingEpochsStatuses(ctx context.Context) error ⋮---- const maxRetries = 10 ⋮---- func (s *Service) Start(ctx context.Context) error ⋮---- func (s *Service) HandleProofAggregated(ctx context.Context, msg symbiotic.AggregationProof) error ⋮---- return errors.Errorf("failed to get validator set: %w", err) // if not found then it's failure case ⋮---- func (s *Service) trackCommittedEpochs(ctx context.Context) error ⋮---- var lastCommittedEpoch uint64 = math.MaxUint64 ⋮---- func (s *Service) findLatestNonZeroSettlements(ctx context.Context) ([]symbiotic.CrossChainAddress, error) ```` ## File: pkg/log/context_handler.go ````go //nolint:wrapcheck // this is the library code, don't need to wrap it package log ⋮---- import ( "context" "log/slog" ) ⋮---- "context" "log/slog" ⋮---- type ContextHandler struct { slog.Handler } ⋮---- func (h ContextHandler) Handle(ctx context.Context, r slog.Record) error ⋮---- type attrsKey struct{} ⋮---- var attrsKeyValue attrsKey ⋮---- func WithComponent(ctx context.Context, component string) context.Context ⋮---- func WithAttrs(ctx context.Context, as ...slog.Attr) context.Context ⋮---- func copyAttrs(parentAttrs []slog.Attr, addCapacity int) []slog.Attr ⋮---- func getAttrs(ctx context.Context) []slog.Attr ```` ## File: pkg/log/log_test.go ````go package log ⋮---- import ( "log/slog" "testing" "time" "github.com/go-errors/errors" ) ⋮---- "log/slog" "testing" "time" ⋮---- "github.com/go-errors/errors" ⋮---- func TestLog(t *testing.T) ⋮---- func TestComponent(t *testing.T) ⋮---- func TestComponentJSON(t *testing.T) ⋮---- func errorFunc() error ⋮---- func TestSplit(t *testing.T) ```` ## File: pkg/log/log.go ````go package log ⋮---- import ( "context" "fmt" "log/slog" "math/big" "os" "runtime" "strconv" "strings" "sync" "time" "github.com/go-errors/errors" slogmulti "github.com/samber/slog-multi" ) ⋮---- "context" "fmt" "log/slog" "math/big" "os" "runtime" "strconv" "strings" "sync" "time" ⋮---- "github.com/go-errors/errors" slogmulti "github.com/samber/slog-multi" ⋮---- var once sync.Once ⋮---- func Init(levelStr, mode string) ⋮---- func internalInit(level slog.Level, mode string) ⋮---- func parseLogLevel(levelStr string) slog.Level ⋮---- func initPretty(level slog.Level) ⋮---- func initText(level slog.Level) ⋮---- func initJson(level slog.Level) ⋮---- func errorLevel(_ context.Context, r slog.Record) bool ⋮---- func notErrorLevel(_ context.Context, r slog.Record) bool ⋮---- type humanDuration time.Duration ⋮---- func (d humanDuration) MarshalJSON() ([]byte, error) ⋮---- func replaceAttr(groups []string, a slog.Attr) slog.Attr ⋮---- // Normalize big numbers to strings to avoid scientific notation in pretty logger ⋮---- // fmtErr returns a slog.GroupValue with keys "msg" and "trace". // If the error does not implement interface { StackTrace() errors.StackTrace }, // the "trace" key is omitted. func fmtErr(err error) slog.Value ⋮---- var groupValues []slog.Attr ⋮---- type StackTracer interface { Callers() []uintptr } // Find the trace to the location of the first errors.New, // errors.Wrap, or errors.WithStack call. var st StackTracer ```` ## File: pkg/log/prettylog.go ````go //nolint:wrapcheck // this is the library code, don't need to wrap it package log ⋮---- import ( "bytes" "context" "encoding/json" "fmt" "io" "log/slog" "os" "strconv" "strings" "sync" "github.com/go-errors/errors" "gopkg.in/yaml.v2" ) ⋮---- "bytes" "context" "encoding/json" "fmt" "io" "log/slog" "os" "strconv" "strings" "sync" ⋮---- "github.com/go-errors/errors" "gopkg.in/yaml.v2" ⋮---- const ( timeFormat = "[15:04:05.000]" reset = "\033[0m" black = 30 red = 31 green = 32 yellow = 33 blue = 34 magenta = 35 cyan = 36 lightGray = 37 darkGray = 90 lightRed = 91 lightGreen = 92 lightYellow = 93 lightBlue = 94 lightMagenta = 95 lightCyan = 96 white = 97 ) ⋮---- func colorizer(colorCode int, v string) string ⋮---- type Handler struct { h slog.Handler r func([]string, slog.Attr) slog.Attr b *bytes.Buffer m *sync.Mutex writer io.Writer colorize bool outputEmptyAttrs bool } ⋮---- func New(handlerOptions *slog.HandlerOptions, options ...Option) *Handler ⋮---- func NewHandler(opts *slog.HandlerOptions) *Handler ⋮---- func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool ⋮---- func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler ⋮---- func (h *Handler) WithGroup(name string) slog.Handler ⋮---- func (h *Handler) computeAttrs( ctx context.Context, r slog.Record, ) (map[string]any, error) ⋮---- var attrs map[string]any ⋮---- func (h *Handler) Handle(ctx context.Context, r slog.Record) error ⋮---- var level string ⋮---- var timestamp string ⋮---- var component string ⋮---- var msg string ⋮---- var attrsAsBytes []byte ⋮---- //attrsAsBytes, err = json.MarshalIndent(attrs, "", " ") ⋮---- func suppressDefaults( next func([]string, slog.Attr) slog.Attr, ) func([]string, slog.Attr) slog.Attr ⋮---- type Option func(h *Handler) ⋮---- func WithDestinationWriter(writer io.Writer) Option ⋮---- func WithColor() Option ⋮---- func WithOutputEmptyAttrs() Option ```` ## File: pkg/proof/circuit.go ````go package proof ⋮---- import ( "encoding/hex" "log/slog" "math/big" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/std/algebra/emulated/sw_bn254" "github.com/consensys/gnark/std/algebra/emulated/sw_emulated" "github.com/consensys/gnark/std/hash/mimc" gnarkSha3 "github.com/consensys/gnark/std/hash/sha3" "github.com/consensys/gnark/std/math/bits" "github.com/consensys/gnark/std/math/emulated" "github.com/consensys/gnark/std/math/uints" "github.com/ethereum/go-ethereum/crypto" ) ⋮---- "encoding/hex" "log/slog" "math/big" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/std/algebra/emulated/sw_bn254" "github.com/consensys/gnark/std/algebra/emulated/sw_emulated" "github.com/consensys/gnark/std/hash/mimc" gnarkSha3 "github.com/consensys/gnark/std/hash/sha3" "github.com/consensys/gnark/std/math/bits" "github.com/consensys/gnark/std/math/emulated" "github.com/consensys/gnark/std/math/uints" "github.com/ethereum/go-ethereum/crypto" ⋮---- // Circuit defines a pre-image knowledge proof type Circuit struct { InputHash frontend.Variable `gnark:",public"` // 254 bits SignersAggVotingPower frontend.Variable `gnark:",private"` // 254 bits, virtually public Message sw_bn254.G1Affine `gnark:",private"` // virtually public Signature sw_bn254.G1Affine `gnark:",private"` SignersAggKeyG2 sw_bn254.G2Affine `gnark:",private"` ValidatorData []ValidatorDataCircuit `gnark:",private"` } ⋮---- InputHash frontend.Variable `gnark:",public"` // 254 bits SignersAggVotingPower frontend.Variable `gnark:",private"` // 254 bits, virtually public Message sw_bn254.G1Affine `gnark:",private"` // virtually public ⋮---- type ValidatorDataCircuit struct { Key sw_bn254.G1Affine VotingPower frontend.Variable IsNonSigner frontend.Variable } ⋮---- type ProveInput struct { ValidatorData []ValidatorData MessageG1 bn254.G1Affine Signature bn254.G1Affine SignersAggKeyG2 bn254.G2Affine } ⋮---- // Define declares the circuit's constraints func (circuit *Circuit) Define(api frontend.API) error ⋮---- // --------------------------------------- Prove ValSet consistency --------------------------------------- ⋮---- // calc valset hash, agg key and agg voting power ⋮---- // hash data if VALIDATOR is not a filler ⋮---- // add power if VALIDATOR is not a filler and SIGNER ⋮---- // aggregate key if VALIDATOR is not a filler and SIGNER ⋮---- // compare with public inputs ⋮---- // --------------------------------------- Prove Input consistency --------------------------------------- ⋮---- // valset consistency checked against InputHash which is Hash{valset-hash|signers-vp|message} ⋮---- inputDataHash[0] = u64Api.ByteValueOf(u64Api.ToValue(u64Api.And(u64Api.ValueOf(inputDataHash[0].Val), uints.NewU64(0x1f)))) // zero three first bits ⋮---- // --------------------------------------- Verify Signature --------------------------------------- ⋮---- // calc alpha ⋮---- //TODO optimize ⋮---- // pairing check ⋮---- func setCircuitData(circuit *Circuit, proveInput ProveInput) ```` ## File: pkg/proof/helpers_test.go ````go package proof ⋮---- import ( "math/big" "os" "strings" "testing" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) ⋮---- "math/big" "os" "strings" "testing" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- // TestGetMaxValidators tests the GetMaxValidators function func TestGetMaxValidators(t *testing.T) ⋮---- // Set environment variable ⋮---- // TestGetOptimalN tests the getOptimalN function func TestGetOptimalN(t *testing.T) ⋮---- // Temporarily override max validators ⋮---- // TestNormalizeValset tests the NormalizeValset function func TestNormalizeValset(t *testing.T) ⋮---- // Set MAX_VALIDATORS to ensure we get a specific size ⋮---- // Should be sorted and padded to 10 ⋮---- // Check that first 3 are sorted (we need to verify sorting logic) // The sorting is done by key.X or key.Y comparison ⋮---- // Check that remaining slots are padded with zero points ⋮---- // All should be zero points ⋮---- // TestHashValset tests the HashValset function func TestHashValset(t *testing.T) ⋮---- // Add zero point validator ⋮---- // Hash should ignore the zero point validator ⋮---- // TestGetNonSignersData tests the getNonSignersData function func TestGetNonSignersData(t *testing.T) ⋮---- valset := genValset(5, []int{1, 3}) // Validators at index 1 and 3 are non-signers ⋮---- // Total voting power should be sum of all validators ⋮---- // Non-signers voting power should be sum of 2 validators ⋮---- // Aggregated key should not be infinity (we have non-signers) ⋮---- valset := genValset(3, []int{}) // All are signers ⋮---- // Total voting power ⋮---- // No non-signers ⋮---- // Aggregated key should be infinity ⋮---- valset := genValset(3, []int{0, 1, 2}) // All are non-signers ⋮---- // All voting power goes to non-signers ⋮---- // TestGetAggSignature tests the getAggSignature function func TestGetAggSignature(t *testing.T) ⋮---- valset := genValset(5, []int{1, 3}) // Validators 1 and 3 are non-signers ⋮---- // Use a simple message point for testing ⋮---- // Should not be infinity points (we have signers) ⋮---- // Should be infinity points (no signers) ⋮---- // TestGetPubkeyG1 tests the getPubkeyG1 function func TestGetPubkeyG1(t *testing.T) ⋮---- // Zero should give infinity point ⋮---- // One should give generator ⋮---- // TestGetPubkeyG2 tests the getPubkeyG2 function func TestGetPubkeyG2(t *testing.T) ⋮---- // TestProofDataMarshal tests the ProofData.Marshal function func TestProofDataMarshal(t *testing.T) ⋮---- // Fill with test data ⋮---- // Should be 256 + 64 + 64 + 32 = 416 bytes ⋮---- // Check that proof is at the beginning ⋮---- // Check commitments ⋮---- // Check commitment PoK ⋮---- // Check voting power (last 32 bytes) ⋮---- // Last 32 bytes should be zero ⋮---- // TestExists tests the exists function func TestExists(t *testing.T) ⋮---- // Create temp file ```` ## File: pkg/proof/helpers.go ````go package proof ⋮---- import ( "bytes" "math/big" "sort" "github.com/consensys/gnark-crypto/ecc/bn254" mimc_native "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/std/algebra/emulated/sw_bn254" "github.com/consensys/gnark/std/hash/mimc" "github.com/consensys/gnark/std/math/bits" "github.com/consensys/gnark/std/math/uints" ) ⋮---- "bytes" "math/big" "sort" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" mimc_native "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/std/algebra/emulated/sw_bn254" "github.com/consensys/gnark/std/hash/mimc" "github.com/consensys/gnark/std/math/bits" "github.com/consensys/gnark/std/math/uints" ⋮---- func (p ProofData) Marshal() []byte ⋮---- var result bytes.Buffer ⋮---- func hashAffineG1(h *mimc.MiMC, g1 *sw_bn254.G1Affine) ⋮---- func hashAffineG2(h *mimc.MiMC, g2 *sw_bn254.G2Affine) ⋮---- func variableToBytes(api frontend.API, u64api *uints.BinaryField[uints.U64], variable frontend.Variable) []uints.U8 ⋮---- func keyToBytes(u64api *uints.BinaryField[uints.U64], key *sw_bn254.G1Affine) []uints.U8 ⋮---- func limbsToBytes(u64api *uints.BinaryField[uints.U64], limbs []frontend.Variable) []uints.U8 ⋮---- func HashValset(valset []ValidatorData) []byte ⋮---- //nolint:gosec // G602: i is always in range as we iterate over valset ⋮---- // hash by limbs as it's done inside circuit ⋮---- // outerHash.Write(innerHash.Sum(nil)) ⋮---- func getPubkeyG1(pk *big.Int) bn254.G1Affine ⋮---- var p bn254.G1Affine ⋮---- func getPubkeyG2(pk *big.Int) bn254.G2Affine ⋮---- var p bn254.G2Affine ⋮---- func getNonSignersData(valset []ValidatorData) (aggKey *bn254.G1Affine, aggVotingPower *big.Int, totalVotingPower *big.Int) ⋮---- func getAggSignature(message bn254.G1Affine, valset *[]ValidatorData) (signature *bn254.G1Affine, aggKeyG2 *bn254.G2Affine, aggKeyG1 *bn254.G1Affine) ⋮---- msg := bn254.G1Affine{X: message.X, Y: message.Y} // have to copy msg since ScalarMultiplication rewrite it ⋮---- func NormalizeValset(valset []ValidatorData) []ValidatorData ⋮---- // Sort validators by key in ascending order ⋮---- // Compare keys (lower first) ⋮---- func getOptimalN(valsetLength int) int ⋮---- var capSize int ```` ## File: pkg/proof/proof_test.go ````go package proof ⋮---- import ( "encoding/hex" "fmt" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/constraint" ) ⋮---- "encoding/hex" "fmt" "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/require" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/constraint" ⋮---- func genValset(numValidators int, nonSigners []int) []ValidatorData ⋮---- //nolint:unused // will be used later func mockValset() []ValidatorData ⋮---- func calculateInputHash(validatorSetHash []byte, signersVotingPower *big.Int, messageG1 *bn254.G1Affine) common.Hash ⋮---- var packed []byte ⋮---- func TestProof(t *testing.T) ⋮---- // generate valset ⋮---- // valset := mockValset() ⋮---- func TestProofFailOnEmptyCircuitDir(t *testing.T) ⋮---- // TestNewZkProverInitialization tests the NewZkProver initialization func TestNewZkProverInitialization(t *testing.T) ⋮---- // Check all maps are initialized ⋮---- // Check maps are empty (no circuits loaded without dir) ⋮---- // Check maxValidators is set to default ⋮---- // Check circuitsDir is empty ⋮---- // We can't actually test NewZkProver with a real circuits dir // because it will try to load/compile circuits which is slow. // Instead, we manually create a prover to verify the field is set. ⋮---- // Maps should still be initialized ⋮---- // TestProveValidation tests the Prove validation paths func TestProveValidation(t *testing.T) ⋮---- // Create prover with circuits dir but no actual circuits loaded ⋮---- // Try with 25 validators (not in {10, 100, 1000}) ⋮---- // Even with 10 validators (which is in maxValidators), // we don't have actual circuit loaded ⋮---- // TestVerifyValidation tests the Verify validation paths func TestVerifyValidation(t *testing.T) ⋮---- // valsetLen = 5 should normalize to 10 // But since we don't have vk[10], it should error // Note: Verify needs at least 384 bytes for proof ⋮---- // valsetLen = 5000 exceeds all sizes, getOptimalN returns 0 ⋮---- // Even with exact match valsetLen=100, vk map is empty ⋮---- // TestPathHelpers tests the path generation helper functions func TestR1csPathTmp(t *testing.T) ⋮---- func TestPkPathTmp(t *testing.T) ⋮---- func TestVkPathTmp(t *testing.T) ⋮---- func TestSolPathTmp(t *testing.T) ```` ## File: pkg/proof/proof.go ````go package proof ⋮---- import ( "bytes" "crypto/sha256" "encoding/hex" "fmt" "log/slog" "math/big" "os" "strconv" "strings" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" ) ⋮---- "bytes" "crypto/sha256" "encoding/hex" "fmt" "log/slog" "math/big" "os" "strconv" "strings" ⋮---- "github.com/ethereum/go-ethereum/common" ⋮---- "github.com/go-errors/errors" ⋮---- "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/solidity" "github.com/consensys/gnark/constraint" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" ⋮---- var ( defaultMaxValidators = []int{10, 100, 1000} ) ⋮---- func GetMaxValidators() []int ⋮---- var newMaxValidators []int ⋮---- func r1csPathTmp(circuitsDir, suffix string) string ⋮---- func pkPathTmp(circuitsDir, suffix string) string ⋮---- func vkPathTmp(circuitsDir, suffix string) string ⋮---- func solPathTmp(circuitsDir, suffix string) string ⋮---- type ProofData struct { Proof []byte Commitments []byte CommitmentPok []byte SignersAggVotingPower *big.Int } ⋮---- type ValidatorData struct { PrivateKey *big.Int Key bn254.G1Affine KeyG2 bn254.G2Affine VotingPower *big.Int IsNonSigner bool } ⋮---- type ZkProver struct { cs map[int]constraint.ConstraintSystem pk map[int]groth16.ProvingKey vk map[int]groth16.VerifyingKey circuitsDir string maxValidators []int } ⋮---- func NewZkProver(circuitsDir string) *ZkProver ⋮---- func (p *ZkProver) init() ⋮---- func (p *ZkProver) Verify(valsetLen int, publicInputHash common.Hash, proofBytes []byte) (bool, error) ⋮---- //nolint:gosec // G602: proofBytes length is validated by caller, slicing is safe ⋮---- rawProofBytes = append(rawProofBytes, []byte{0, 0, 0, 1}...) //dirty hack ⋮---- func (p *ZkProver) Prove(proveInput ProveInput) (ProofData, error) ⋮---- // witness definition ⋮---- // groth16: Prove & Verify ⋮---- // Format for the specific Solidity interface ⋮---- // Format the vector of public inputs as hex strings ⋮---- // If more than 10 inputs (unlikely), you'll need to adapt the interface ⋮---- // verify proof ⋮---- // Serialize the proof var proofBuffer bytes.Buffer ⋮---- // Assuming fpSize is 32 bytes for BN254 const fpSize = 32 ⋮---- standardProof[0] = new(big.Int).SetBytes(proofBytes[fpSize*0 : fpSize*1]) // Ar.x standardProof[1] = new(big.Int).SetBytes(proofBytes[fpSize*1 : fpSize*2]) // Ar.y standardProof[2] = new(big.Int).SetBytes(proofBytes[fpSize*2 : fpSize*3]) // Bs.x[0] standardProof[3] = new(big.Int).SetBytes(proofBytes[fpSize*3 : fpSize*4]) // Bs.x[1] standardProof[4] = new(big.Int).SetBytes(proofBytes[fpSize*4 : fpSize*5]) // Bs.y[0] standardProof[5] = new(big.Int).SetBytes(proofBytes[fpSize*5 : fpSize*6]) // Bs.y[1] standardProof[6] = new(big.Int).SetBytes(proofBytes[fpSize*6 : fpSize*7]) // Krs.x standardProof[7] = new(big.Int).SetBytes(proofBytes[fpSize*7 : fpSize*8]) // Krs.y ⋮---- commitments[0] = new(big.Int).SetBytes(proofBytes[4+fpSize*8 : 4+fpSize*9]) // Commitment.x commitments[1] = new(big.Int).SetBytes(proofBytes[4+fpSize*9 : 4+fpSize*10]) // Commitment.y ⋮---- commitmentPok[0] = new(big.Int).SetBytes(proofBytes[4+fpSize*10 : 4+fpSize*11]) // CommitmentPok.x commitmentPok[1] = new(big.Int).SetBytes(proofBytes[4+fpSize*11 : 4+fpSize*12]) // CommitmentPok.y ⋮---- //nolint:revive // function-result-limit: This function needs to return multiple complex types for cryptographic operations func (p *ZkProver) loadOrInit(valsetLen int) (constraint.ConstraintSystem, groth16.ProvingKey, groth16.VerifyingKey, error) ⋮---- var buf bytes.Buffer ⋮---- func exists(path string) bool ```` ## File: pkg/server/interceptors.go ````go package server ⋮---- import ( "context" "log/slog" "time" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/symbioticfi/relay/pkg/log" ) ⋮---- "context" "log/slog" "time" ⋮---- "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ⋮---- "github.com/symbioticfi/relay/pkg/log" ⋮---- // LoggingInterceptor provides request logging for unary RPCs func LoggingInterceptor(verboseLogging bool) grpc.UnaryServerInterceptor ⋮---- // wrappedStream wraps grpc.ServerStream to inject context type wrappedStream struct { grpc.ServerStream ctx context.Context } ⋮---- func (w *wrappedStream) Context() context.Context ⋮---- // StreamLoggingInterceptor provides request logging for streaming RPCs func StreamLoggingInterceptor(verboseLogging bool) grpc.StreamServerInterceptor ⋮---- // PanicRecoveryInterceptor recovers from panics in unary gRPC handlers func PanicRecoveryInterceptor() grpc.UnaryServerInterceptor ⋮---- // StreamPanicRecoveryInterceptor recovers from panics in streaming gRPC handlers func StreamPanicRecoveryInterceptor() grpc.StreamServerInterceptor ```` ## File: pkg/server/metrics_server.go ````go package server ⋮---- import ( "context" "log/slog" "net/http" "time" "github.com/go-chi/chi/v5" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/prometheus/client_golang/prometheus/promhttp" ) ⋮---- "context" "log/slog" "net/http" "time" ⋮---- "github.com/go-chi/chi/v5" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/prometheus/client_golang/prometheus/promhttp" ⋮---- type MetricsConfig struct { Address string ReadHeaderTimeout time.Duration } ⋮---- func (c MetricsConfig) Validate() error ⋮---- type MetricsServer struct { srv *http.Server cfg MetricsConfig } ⋮---- func NewMetricsServer(cfg MetricsConfig) (*MetricsServer, error) ⋮---- func initMetricsHandler(_ MetricsConfig) http.Handler ⋮---- func (s *MetricsServer) Serve(ctx context.Context) error ⋮---- if err := s.srv.Shutdown(ctxShutdown); err != nil { //nolint:contextcheck // we must use separate context for shutdown ```` ## File: pkg/signals/signal_test.go ````go package signals ⋮---- import ( "context" "errors" "sync" "sync/atomic" "testing" "time" "github.com/stretchr/testify/require" ) ⋮---- "context" "errors" "sync" "sync/atomic" "testing" "time" ⋮---- "github.com/stretchr/testify/require" ⋮---- func TestNew(t *testing.T) ⋮---- func TestDefaultConfig(t *testing.T) ⋮---- func TestSetHandler_Success(t *testing.T) ⋮---- func TestSetHandler_FailsWhenHandlersAlreadySet(t *testing.T) ⋮---- func TestSetHandler_FailsWhenWorkersAlreadyStarted(t *testing.T) ⋮---- func TestSetHandler_FailsWhenAllHandlersAreNil(t *testing.T) ⋮---- func TestSetHandler_FiltersNilHandlers(t *testing.T) ⋮---- func TestEmit_SuccessWithHandlers(t *testing.T) ⋮---- func TestEmit_ReturnsNilWhenNoHandlersSet(t *testing.T) ⋮---- func TestEmit_FailsWhenSignalIsStopped(t *testing.T) ⋮---- func TestEmitWithTimeout_SuccessWithinTimeout(t *testing.T) ⋮---- func TestEmitWithTimeout_TimesOutWhenQueueIsFull(t *testing.T) ⋮---- // Fill the queue ⋮---- func TestEmitWithTimeout_ReturnsNilWhenNoHandlersSet(t *testing.T) ⋮---- func TestEmitNonBlocking_SuccessWhenQueueHasSpace(t *testing.T) ⋮---- func TestEmitNonBlocking_ReturnsFalseWhenQueueIsFull(t *testing.T) ⋮---- func TestEmitNonBlocking_ReturnsFalseWhenSignalIsStopped(t *testing.T) ⋮---- func TestStartWorkers_Success(t *testing.T) ⋮---- func TestStartWorkers_FailsWhenNoHandlersSet(t *testing.T) ⋮---- func TestStartWorkers_FailsWhenWorkersAlreadyStarted(t *testing.T) ⋮---- func TestWorkerProcessing_ProcessesEventsSuccessfully(t *testing.T) ⋮---- var callCount atomic.Int32 ⋮---- // Emit events ⋮---- // Wait for processing ⋮---- func TestWorkerProcessing_ExecutesMultipleHandlersSequentially(t *testing.T) ⋮---- require.Equal(t, int32(4), callCount.Load()) // 2 events * 2 handlers ⋮---- func TestWorkerProcessing_ContinuesOnHandlerError(t *testing.T) ⋮---- // Emit event ⋮---- require.Equal(t, int32(2), callCount.Load()) // Both handlers should be called despite first one erroring ⋮---- func TestWorkerShutdown_OnContextCancellation(t *testing.T) ⋮---- // Emit an event ⋮---- // Wait for processing to start ⋮---- // Cancel context ⋮---- // Unblock handler ⋮---- // Wait for shutdown ⋮---- func TestWorkerShutdown_MultipleWorkersGracefully(t *testing.T) ⋮---- var wg sync.WaitGroup ⋮---- // Emit multiple events ⋮---- // Cancel and wait for shutdown ⋮---- func TestConcurrency_ConcurrentEmitsAreSafe(t *testing.T) ```` ## File: pkg/signals/signal.go ````go package signals ⋮---- import ( "context" "log/slog" "sync" "sync/atomic" "time" "github.com/go-errors/errors" ) ⋮---- "context" "log/slog" "sync" "sync/atomic" "time" ⋮---- "github.com/go-errors/errors" ⋮---- const ( // EmitTimeout is the default timeout for emitting events to the signal queue. EmitTimeout = 10 * time.Second ) ⋮---- // EmitTimeout is the default timeout for emitting events to the signal queue. ⋮---- // Signal provides a type-safe, concurrent event processing system with configurable worker pools. // It uses a buffered channel queue to handle events and multiple worker goroutines for parallel processing. type Signal[T any] struct { queue chan Event[T] handlers []SignalListener[T] maxWorkers int id string // Internal state started bool stopped atomic.Bool mutex sync.RWMutex } ⋮---- // Internal state ⋮---- // Config defines the configuration for a Signal instance. type Config struct { // BufferSize sets the size of the internal event queue buffer (minimum 5) BufferSize int `mapstructure:"buffer-size" validate:"gte=5"` // WorkerCount sets the number of worker goroutines to process events (5-100) WorkerCount int `mapstructure:"worker-count" validate:"gte=5,lte=100"` } ⋮---- // BufferSize sets the size of the internal event queue buffer (minimum 5) ⋮---- // WorkerCount sets the number of worker goroutines to process events (5-100) ⋮---- func DefaultConfig() Config ⋮---- // Event represents a signal event containing both payload data and execution context. type Event[T any] struct { // Payload contains the actual event data Payload T // Ctx is the context associated with this event for cancellation and timeout handling Ctx context.Context } ⋮---- // Payload contains the actual event data ⋮---- // Ctx is the context associated with this event for cancellation and timeout handling ⋮---- // SignalListener defines the function signature for handling signal events. // It receives the event context and payload, returning an error if processing fails. type SignalListener[T any] func(context.Context, T) error ⋮---- // New creates a new Signal instance with the specified configuration. // Handlers can be provided during construction or set later using SetHandlers. // The id is used for logging and error identification. // Nil handlers are automatically filtered out. func New[T any](cfg Config, id string, handlers ...SignalListener[T]) *Signal[T] ⋮---- // Filter out nil handlers var validHandlers []SignalListener[T] ⋮---- // SetHandlers sets the event handlers for this signal. // Returns an error if workers are started or handlers are already set, as handlers cannot be replaced. // This method is thread-safe and should be called before starting workers. // Accepts one or more handlers which will be executed sequentially in the order provided. ⋮---- func (s *Signal[T]) SetHandlers(handlers ...SignalListener[T]) error ⋮---- // Emit sends an event to the signal queue using the default EmitTimeout. // It will block if the queue is full until the timeout is reached. // Returns an error if workers have stopped. // Use EmitNonBlocking if you want non-blocking behavior or EmitWithTimeout for custom timeouts. func (s *Signal[T]) Emit(payload T) error ⋮---- // EmitWithTimeout sends an event to the signal queue with a custom timeout. // Returns an error if the event cannot be queued within the timeout period or if workers have stopped. func (s *Signal[T]) EmitWithTimeout(payload T, timeout time.Duration) error ⋮---- // We might not have handlers set for specific signals like the signals dealing // with aggregation on non aggregator nodes in such case we ignore the event completely // if we don't ignore the queue will get full and requests will timeout ⋮---- // EmitNonBlocking attempts to send an event without blocking. // Returns true if the event was sent, false if the queue is full or workers have stopped. func (s *Signal[T]) EmitNonBlocking(ctx context.Context, payload T) bool ⋮---- // StartWorkers starts the configured number of worker goroutines to process events from the queue. // It should be called once during application startup and cannot be called again. // All workers will gracefully shut down when the provided context is cancelled. // The signal automatically marks itself as stopped and closes the queue when all workers exit. // Returns an error if workers are already started or if no signal handler is set. func (s *Signal[T]) StartWorkers(ctx context.Context) error ⋮---- var shutdownWG sync.WaitGroup ⋮---- // Execute all handlers regardless of errors ⋮---- // Continue executing remaining handlers ⋮---- // wait for all workers to finish ```` ## File: symbiotic/client/evm/abi/IKeyRegistry.abi.json ````json [ { "type": "function", "name": "getKey", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "tag", "type": "uint8", "internalType": "uint8" } ], "outputs": [ { "name": "", "type": "bytes", "internalType": "bytes" } ], "stateMutability": "view" }, { "type": "function", "name": "getKeyAt", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "tag", "type": "uint8", "internalType": "uint8" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bytes", "internalType": "bytes" } ], "stateMutability": "view" }, { "type": "function", "name": "getKeys", "inputs": [], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IKeyRegistry.OperatorWithKeys[]", "components": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "keys", "type": "tuple[]", "internalType": "struct IKeyRegistry.Key[]", "components": [ { "name": "tag", "type": "uint8", "internalType": "uint8" }, { "name": "payload", "type": "bytes", "internalType": "bytes" } ] } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getKeys", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IKeyRegistry.Key[]", "components": [ { "name": "tag", "type": "uint8", "internalType": "uint8" }, { "name": "payload", "type": "bytes", "internalType": "bytes" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getKeysAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IKeyRegistry.OperatorWithKeys[]", "components": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "keys", "type": "tuple[]", "internalType": "struct IKeyRegistry.Key[]", "components": [ { "name": "tag", "type": "uint8", "internalType": "uint8" }, { "name": "payload", "type": "bytes", "internalType": "bytes" } ] } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getKeysAt", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IKeyRegistry.Key[]", "components": [ { "name": "tag", "type": "uint8", "internalType": "uint8" }, { "name": "payload", "type": "bytes", "internalType": "bytes" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getKeysOperators", "inputs": [], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getKeysOperatorsAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getKeysOperatorsLength", "inputs": [], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getOperator", "inputs": [ { "name": "key", "type": "bytes", "internalType": "bytes" } ], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "setKey", "inputs": [ { "name": "tag", "type": "uint8", "internalType": "uint8" }, { "name": "key", "type": "bytes", "internalType": "bytes" }, { "name": "signature", "type": "bytes", "internalType": "bytes" }, { "name": "extraData", "type": "bytes", "internalType": "bytes" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "event", "name": "SetKey", "inputs": [ { "name": "operator", "type": "address", "indexed": true, "internalType": "address" }, { "name": "tag", "type": "uint8", "indexed": true, "internalType": "uint8" }, { "name": "key", "type": "bytes", "indexed": true, "internalType": "bytes" }, { "name": "extraData", "type": "bytes", "indexed": false, "internalType": "bytes" } ], "anonymous": false }, { "type": "error", "name": "KeyRegistry_AlreadyUsed", "inputs": [] }, { "type": "error", "name": "KeyRegistry_InvalidKeySignature", "inputs": [] }, { "type": "error", "name": "KeyRegistry_InvalidKeyType", "inputs": [] } ] ```` ## File: symbiotic/client/evm/abi/ISettlement.abi.json ````json [ { "type": "function", "name": "NETWORK", "inputs": [], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "SUBNETWORK", "inputs": [], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "SUBNETWORK_IDENTIFIER", "inputs": [], "outputs": [ { "name": "", "type": "uint96", "internalType": "uint96" } ], "stateMutability": "view" }, { "type": "function", "name": "VALIDATOR_SET_VERSION", "inputs": [], "outputs": [ { "name": "", "type": "uint8", "internalType": "uint8" } ], "stateMutability": "view" }, { "type": "function", "name": "commitValSetHeader", "inputs": [ { "name": "header", "type": "tuple", "internalType": "struct ISettlement.ValSetHeader", "components": [ { "name": "version", "type": "uint8", "internalType": "uint8" }, { "name": "requiredKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "captureTimestamp", "type": "uint48", "internalType": "uint48" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "totalVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "validatorsSszMRoot", "type": "bytes32", "internalType": "bytes32" } ] }, { "name": "extraData", "type": "tuple[]", "internalType": "struct ISettlement.ExtraData[]", "components": [ { "name": "key", "type": "bytes32", "internalType": "bytes32" }, { "name": "value", "type": "bytes32", "internalType": "bytes32" } ] }, { "name": "proof", "type": "bytes", "internalType": "bytes" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "eip712Domain", "inputs": [], "outputs": [ { "name": "fields", "type": "bytes1", "internalType": "bytes1" }, { "name": "name", "type": "string", "internalType": "string" }, { "name": "version", "type": "string", "internalType": "string" }, { "name": "chainId", "type": "uint256", "internalType": "uint256" }, { "name": "verifyingContract", "type": "address", "internalType": "address" }, { "name": "salt", "type": "bytes32", "internalType": "bytes32" }, { "name": "extensions", "type": "uint256[]", "internalType": "uint256[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getCaptureTimestampFromValSetHeader", "inputs": [], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getCaptureTimestampFromValSetHeaderAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getExtraData", "inputs": [ { "name": "key", "type": "bytes32", "internalType": "bytes32" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "getExtraDataAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "key", "type": "bytes32", "internalType": "bytes32" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "getLastCommittedHeaderEpoch", "inputs": [], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getQuorumThresholdFromValSetHeader", "inputs": [], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getQuorumThresholdFromValSetHeaderAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getRequiredKeyTagFromValSetHeader", "inputs": [], "outputs": [ { "name": "", "type": "uint8", "internalType": "uint8" } ], "stateMutability": "view" }, { "type": "function", "name": "getRequiredKeyTagFromValSetHeaderAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint8", "internalType": "uint8" } ], "stateMutability": "view" }, { "type": "function", "name": "getSigVerifier", "inputs": [], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "getSigVerifierAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "hint", "type": "bytes", "internalType": "bytes" } ], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "getTotalVotingPowerFromValSetHeader", "inputs": [], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getTotalVotingPowerFromValSetHeaderAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getValSetHeader", "inputs": [], "outputs": [ { "name": "header", "type": "tuple", "internalType": "struct ISettlement.ValSetHeader", "components": [ { "name": "version", "type": "uint8", "internalType": "uint8" }, { "name": "requiredKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "captureTimestamp", "type": "uint48", "internalType": "uint48" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "totalVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "validatorsSszMRoot", "type": "bytes32", "internalType": "bytes32" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getValSetHeaderAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple", "internalType": "struct ISettlement.ValSetHeader", "components": [ { "name": "version", "type": "uint8", "internalType": "uint8" }, { "name": "requiredKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "captureTimestamp", "type": "uint48", "internalType": "uint48" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "totalVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "validatorsSszMRoot", "type": "bytes32", "internalType": "bytes32" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getValSetHeaderHash", "inputs": [], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "getValSetHeaderHashAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "getValidatorsSszMRootFromValSetHeader", "inputs": [], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "getValidatorsSszMRootFromValSetHeaderAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "getVersionFromValSetHeader", "inputs": [], "outputs": [ { "name": "", "type": "uint8", "internalType": "uint8" } ], "stateMutability": "view" }, { "type": "function", "name": "getVersionFromValSetHeaderAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint8", "internalType": "uint8" } ], "stateMutability": "view" }, { "type": "function", "name": "hashTypedDataV4", "inputs": [ { "name": "structHash", "type": "bytes32", "internalType": "bytes32" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "hashTypedDataV4CrossChain", "inputs": [ { "name": "structHash", "type": "bytes32", "internalType": "bytes32" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "isValSetHeaderCommittedAt", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "setGenesis", "inputs": [ { "name": "valSetHeader", "type": "tuple", "internalType": "struct ISettlement.ValSetHeader", "components": [ { "name": "version", "type": "uint8", "internalType": "uint8" }, { "name": "requiredKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "captureTimestamp", "type": "uint48", "internalType": "uint48" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "totalVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "validatorsSszMRoot", "type": "bytes32", "internalType": "bytes32" } ] }, { "name": "extraData", "type": "tuple[]", "internalType": "struct ISettlement.ExtraData[]", "components": [ { "name": "key", "type": "bytes32", "internalType": "bytes32" }, { "name": "value", "type": "bytes32", "internalType": "bytes32" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setSigVerifier", "inputs": [ { "name": "sigVerifier", "type": "address", "internalType": "address" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "staticDelegateCall", "inputs": [ { "name": "target", "type": "address", "internalType": "address" }, { "name": "data", "type": "bytes", "internalType": "bytes" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "verifyQuorumSig", "inputs": [ { "name": "message", "type": "bytes", "internalType": "bytes" }, { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "proof", "type": "bytes", "internalType": "bytes" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "verifyQuorumSigAt", "inputs": [ { "name": "message", "type": "bytes", "internalType": "bytes" }, { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "proof", "type": "bytes", "internalType": "bytes" }, { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "hint", "type": "bytes", "internalType": "bytes" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "event", "name": "CommitValSetHeader", "inputs": [ { "name": "valSetHeader", "type": "tuple", "indexed": false, "internalType": "struct ISettlement.ValSetHeader", "components": [ { "name": "version", "type": "uint8", "internalType": "uint8" }, { "name": "requiredKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "captureTimestamp", "type": "uint48", "internalType": "uint48" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "totalVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "validatorsSszMRoot", "type": "bytes32", "internalType": "bytes32" } ] }, { "name": "extraData", "type": "tuple[]", "indexed": false, "internalType": "struct ISettlement.ExtraData[]", "components": [ { "name": "key", "type": "bytes32", "internalType": "bytes32" }, { "name": "value", "type": "bytes32", "internalType": "bytes32" } ] } ], "anonymous": false }, { "type": "event", "name": "EIP712DomainChanged", "inputs": [], "anonymous": false }, { "type": "event", "name": "InitEIP712", "inputs": [ { "name": "name", "type": "string", "indexed": false, "internalType": "string" }, { "name": "version", "type": "string", "indexed": false, "internalType": "string" } ], "anonymous": false }, { "type": "event", "name": "InitSigVerifier", "inputs": [ { "name": "sigVerifier", "type": "address", "indexed": false, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "InitSubnetwork", "inputs": [ { "name": "network", "type": "address", "indexed": false, "internalType": "address" }, { "name": "subnetworkId", "type": "uint96", "indexed": false, "internalType": "uint96" } ], "anonymous": false }, { "type": "event", "name": "Initialized", "inputs": [ { "name": "version", "type": "uint64", "indexed": false, "internalType": "uint64" } ], "anonymous": false }, { "type": "event", "name": "SetGenesis", "inputs": [ { "name": "valSetHeader", "type": "tuple", "indexed": false, "internalType": "struct ISettlement.ValSetHeader", "components": [ { "name": "version", "type": "uint8", "internalType": "uint8" }, { "name": "requiredKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "epoch", "type": "uint48", "internalType": "uint48" }, { "name": "captureTimestamp", "type": "uint48", "internalType": "uint48" }, { "name": "quorumThreshold", "type": "uint256", "internalType": "uint256" }, { "name": "totalVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "validatorsSszMRoot", "type": "bytes32", "internalType": "bytes32" } ] }, { "name": "extraData", "type": "tuple[]", "indexed": false, "internalType": "struct ISettlement.ExtraData[]", "components": [ { "name": "key", "type": "bytes32", "internalType": "bytes32" }, { "name": "value", "type": "bytes32", "internalType": "bytes32" } ] } ], "anonymous": false }, { "type": "event", "name": "SetSigVerifier", "inputs": [ { "name": "sigVerifier", "type": "address", "indexed": false, "internalType": "address" } ], "anonymous": false }, { "type": "error", "name": "CheckpointUnorderedInsertion", "inputs": [] }, { "type": "error", "name": "InvalidInitialization", "inputs": [] }, { "type": "error", "name": "InvalidKeyTag", "inputs": [] }, { "type": "error", "name": "NetworkManager_InvalidNetwork", "inputs": [] }, { "type": "error", "name": "NotInitializing", "inputs": [] }, { "type": "error", "name": "Settlement_DuplicateExtraDataKey", "inputs": [] }, { "type": "error", "name": "Settlement_InvalidCaptureTimestamp", "inputs": [] }, { "type": "error", "name": "Settlement_InvalidEpoch", "inputs": [] }, { "type": "error", "name": "Settlement_InvalidSigVerifier", "inputs": [] }, { "type": "error", "name": "Settlement_InvalidValidatorsSszMRoot", "inputs": [] }, { "type": "error", "name": "Settlement_InvalidVersion", "inputs": [] }, { "type": "error", "name": "Settlement_QuorumThresholdGtTotalVotingPower", "inputs": [] }, { "type": "error", "name": "Settlement_ValSetHeaderAlreadyCommitted", "inputs": [] }, { "type": "error", "name": "Settlement_VerificationFailed", "inputs": [] } ] ```` ## File: symbiotic/client/evm/abi/IValSetDriver.abi.json ````json [ { "type": "function", "name": "MAX_QUORUM_THRESHOLD", "inputs": [], "outputs": [ { "name": "", "type": "uint248", "internalType": "uint248" } ], "stateMutability": "view" }, { "type": "function", "name": "NETWORK", "inputs": [], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "SUBNETWORK", "inputs": [], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "SUBNETWORK_IDENTIFIER", "inputs": [], "outputs": [ { "name": "", "type": "uint96", "internalType": "uint96" } ], "stateMutability": "view" }, { "type": "function", "name": "addQuorumThreshold", "inputs": [ { "name": "quorumThreshold", "type": "tuple", "internalType": "struct IValSetDriver.QuorumThreshold", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "addSettlement", "inputs": [ { "name": "settlement", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "addVotingPowerProvider", "inputs": [ { "name": "votingPowerProvider", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "getConfig", "inputs": [], "outputs": [ { "name": "", "type": "tuple", "internalType": "struct IValSetDriver.Config", "components": [ { "name": "numAggregators", "type": "uint208", "internalType": "uint208" }, { "name": "numCommitters", "type": "uint208", "internalType": "uint208" }, { "name": "votingPowerProviders", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "keysProvider", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "settlements", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "maxVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "minInclusionVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "maxValidatorsCount", "type": "uint208", "internalType": "uint208" }, { "name": "requiredKeyTags", "type": "uint8[]", "internalType": "uint8[]" }, { "name": "quorumThresholds", "type": "tuple[]", "internalType": "struct IValSetDriver.QuorumThreshold[]", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] }, { "name": "requiredHeaderKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "verificationType", "type": "uint32", "internalType": "uint32" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getConfigAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple", "internalType": "struct IValSetDriver.Config", "components": [ { "name": "numAggregators", "type": "uint208", "internalType": "uint208" }, { "name": "numCommitters", "type": "uint208", "internalType": "uint208" }, { "name": "votingPowerProviders", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "keysProvider", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "settlements", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "maxVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "minInclusionVotingPower", "type": "uint256", "internalType": "uint256" }, { "name": "maxValidatorsCount", "type": "uint208", "internalType": "uint208" }, { "name": "requiredKeyTags", "type": "uint8[]", "internalType": "uint8[]" }, { "name": "quorumThresholds", "type": "tuple[]", "internalType": "struct IValSetDriver.QuorumThreshold[]", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] }, { "name": "requiredHeaderKeyTag", "type": "uint8", "internalType": "uint8" }, { "name": "verificationType", "type": "uint32", "internalType": "uint32" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getCurrentEpoch", "inputs": [], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getCurrentEpochDuration", "inputs": [], "outputs": [ { "name": "epochDuration", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getCurrentEpochStart", "inputs": [], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getEpochDuration", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "epochDuration", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getEpochIndex", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getEpochStart", "inputs": [ { "name": "epoch", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getKeysProvider", "inputs": [], "outputs": [ { "name": "", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getKeysProviderAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getMaxValidatorsCount", "inputs": [], "outputs": [ { "name": "", "type": "uint208", "internalType": "uint208" } ], "stateMutability": "view" }, { "type": "function", "name": "getMaxValidatorsCountAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint208", "internalType": "uint208" } ], "stateMutability": "view" }, { "type": "function", "name": "getMaxVotingPower", "inputs": [], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getMaxVotingPowerAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getMinInclusionVotingPower", "inputs": [], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getMinInclusionVotingPowerAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "getNextEpoch", "inputs": [], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getNextEpochDuration", "inputs": [], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getNextEpochStart", "inputs": [], "outputs": [ { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getNumAggregators", "inputs": [], "outputs": [ { "name": "", "type": "uint208", "internalType": "uint208" } ], "stateMutability": "view" }, { "type": "function", "name": "getNumAggregatorsAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint208", "internalType": "uint208" } ], "stateMutability": "view" }, { "type": "function", "name": "getNumCommitters", "inputs": [], "outputs": [ { "name": "", "type": "uint208", "internalType": "uint208" } ], "stateMutability": "view" }, { "type": "function", "name": "getNumCommittersAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint208", "internalType": "uint208" } ], "stateMutability": "view" }, { "type": "function", "name": "getQuorumThresholds", "inputs": [], "outputs": [ { "name": "quorumThresholds", "type": "tuple[]", "internalType": "struct IValSetDriver.QuorumThreshold[]", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getQuorumThresholdsAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "quorumThresholds", "type": "tuple[]", "internalType": "struct IValSetDriver.QuorumThreshold[]", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getRequiredHeaderKeyTag", "inputs": [], "outputs": [ { "name": "", "type": "uint8", "internalType": "uint8" } ], "stateMutability": "view" }, { "type": "function", "name": "getRequiredHeaderKeyTagAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint8", "internalType": "uint8" } ], "stateMutability": "view" }, { "type": "function", "name": "getRequiredKeyTags", "inputs": [], "outputs": [ { "name": "requiredKeyTags", "type": "uint8[]", "internalType": "uint8[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getRequiredKeyTagsAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "requiredKeyTags", "type": "uint8[]", "internalType": "uint8[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getSettlements", "inputs": [], "outputs": [ { "name": "settlements", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getSettlementsAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "settlements", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getVerificationType", "inputs": [], "outputs": [ { "name": "", "type": "uint32", "internalType": "uint32" } ], "stateMutability": "view" }, { "type": "function", "name": "getVerificationTypeAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "uint32", "internalType": "uint32" } ], "stateMutability": "view" }, { "type": "function", "name": "getVotingPowerProviders", "inputs": [], "outputs": [ { "name": "votingPowerProviders", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getVotingPowerProvidersAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "votingPowerProviders", "type": "tuple[]", "internalType": "struct IValSetDriver.CrossChainAddress[]", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "isQuorumThresholdRegistered", "inputs": [ { "name": "quorumThreshold", "type": "tuple", "internalType": "struct IValSetDriver.QuorumThreshold", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isQuorumThresholdRegisteredAt", "inputs": [ { "name": "quorumThreshold", "type": "tuple", "internalType": "struct IValSetDriver.QuorumThreshold", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isSettlementRegistered", "inputs": [ { "name": "settlement", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isSettlementRegisteredAt", "inputs": [ { "name": "settlement", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isVotingPowerProviderRegistered", "inputs": [ { "name": "votingPowerProvider", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isVotingPowerProviderRegisteredAt", "inputs": [ { "name": "votingPowerProvider", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "multicall", "inputs": [ { "name": "data", "type": "bytes[]", "internalType": "bytes[]" } ], "outputs": [ { "name": "results", "type": "bytes[]", "internalType": "bytes[]" } ], "stateMutability": "nonpayable" }, { "type": "function", "name": "removeQuorumThreshold", "inputs": [ { "name": "quorumThreshold", "type": "tuple", "internalType": "struct IValSetDriver.QuorumThreshold", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "removeSettlement", "inputs": [ { "name": "settlement", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "removeVotingPowerProvider", "inputs": [ { "name": "votingPowerProvider", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setEpochDuration", "inputs": [ { "name": "epochDuration", "type": "uint48", "internalType": "uint48" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setKeysProvider", "inputs": [ { "name": "keysProvider", "type": "tuple", "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setMaxValidatorsCount", "inputs": [ { "name": "maxValidatorsCount", "type": "uint208", "internalType": "uint208" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setMaxVotingPower", "inputs": [ { "name": "maxVotingPower", "type": "uint256", "internalType": "uint256" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setMinInclusionVotingPower", "inputs": [ { "name": "minInclusionVotingPower", "type": "uint256", "internalType": "uint256" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setNumAggregators", "inputs": [ { "name": "numAggregators", "type": "uint208", "internalType": "uint208" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setNumCommitters", "inputs": [ { "name": "numCommitters", "type": "uint208", "internalType": "uint208" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setRequiredHeaderKeyTag", "inputs": [ { "name": "requiredHeaderKeyTag", "type": "uint8", "internalType": "uint8" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setRequiredKeyTags", "inputs": [ { "name": "requiredKeyTags", "type": "uint8[]", "internalType": "uint8[]" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "setVerificationType", "inputs": [ { "name": "verificationType", "type": "uint32", "internalType": "uint32" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "staticDelegateCall", "inputs": [ { "name": "target", "type": "address", "internalType": "address" }, { "name": "data", "type": "bytes", "internalType": "bytes" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "event", "name": "AddQuorumThreshold", "inputs": [ { "name": "quorumThreshold", "type": "tuple", "indexed": false, "internalType": "struct IValSetDriver.QuorumThreshold", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] } ], "anonymous": false }, { "type": "event", "name": "AddSettlement", "inputs": [ { "name": "settlement", "type": "tuple", "indexed": false, "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "anonymous": false }, { "type": "event", "name": "AddVotingPowerProvider", "inputs": [ { "name": "votingPowerProvider", "type": "tuple", "indexed": false, "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "anonymous": false }, { "type": "event", "name": "InitEpochDuration", "inputs": [ { "name": "epochDuration", "type": "uint48", "indexed": false, "internalType": "uint48" }, { "name": "epochDurationTimestamp", "type": "uint48", "indexed": false, "internalType": "uint48" } ], "anonymous": false }, { "type": "event", "name": "InitSubnetwork", "inputs": [ { "name": "network", "type": "address", "indexed": false, "internalType": "address" }, { "name": "subnetworkId", "type": "uint96", "indexed": false, "internalType": "uint96" } ], "anonymous": false }, { "type": "event", "name": "Initialized", "inputs": [ { "name": "version", "type": "uint64", "indexed": false, "internalType": "uint64" } ], "anonymous": false }, { "type": "event", "name": "RemoveQuorumThreshold", "inputs": [ { "name": "quorumThreshold", "type": "tuple", "indexed": false, "internalType": "struct IValSetDriver.QuorumThreshold", "components": [ { "name": "keyTag", "type": "uint8", "internalType": "uint8" }, { "name": "quorumThreshold", "type": "uint248", "internalType": "uint248" } ] } ], "anonymous": false }, { "type": "event", "name": "RemoveSettlement", "inputs": [ { "name": "settlement", "type": "tuple", "indexed": false, "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "anonymous": false }, { "type": "event", "name": "RemoveVotingPowerProvider", "inputs": [ { "name": "votingPowerProvider", "type": "tuple", "indexed": false, "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "anonymous": false }, { "type": "event", "name": "SetEpochDuration", "inputs": [ { "name": "epochDuration", "type": "uint48", "indexed": false, "internalType": "uint48" } ], "anonymous": false }, { "type": "event", "name": "SetKeysProvider", "inputs": [ { "name": "keysProvider", "type": "tuple", "indexed": false, "internalType": "struct IValSetDriver.CrossChainAddress", "components": [ { "name": "chainId", "type": "uint64", "internalType": "uint64" }, { "name": "addr", "type": "address", "internalType": "address" } ] } ], "anonymous": false }, { "type": "event", "name": "SetMaxValidatorsCount", "inputs": [ { "name": "maxValidatorsCount", "type": "uint208", "indexed": false, "internalType": "uint208" } ], "anonymous": false }, { "type": "event", "name": "SetMaxVotingPower", "inputs": [ { "name": "maxVotingPower", "type": "uint256", "indexed": false, "internalType": "uint256" } ], "anonymous": false }, { "type": "event", "name": "SetMinInclusionVotingPower", "inputs": [ { "name": "minInclusionVotingPower", "type": "uint256", "indexed": false, "internalType": "uint256" } ], "anonymous": false }, { "type": "event", "name": "SetNumAggregators", "inputs": [ { "name": "numAggregators", "type": "uint208", "indexed": false, "internalType": "uint208" } ], "anonymous": false }, { "type": "event", "name": "SetNumCommitters", "inputs": [ { "name": "numCommitters", "type": "uint208", "indexed": false, "internalType": "uint208" } ], "anonymous": false }, { "type": "event", "name": "SetRequiredHeaderKeyTag", "inputs": [ { "name": "requiredHeaderKeyTag", "type": "uint8", "indexed": false, "internalType": "uint8" } ], "anonymous": false }, { "type": "event", "name": "SetRequiredKeyTags", "inputs": [ { "name": "requiredKeyTags", "type": "uint8[]", "indexed": false, "internalType": "uint8[]" } ], "anonymous": false }, { "type": "event", "name": "SetVerificationType", "inputs": [ { "name": "verificationType", "type": "uint32", "indexed": false, "internalType": "uint32" } ], "anonymous": false }, { "type": "error", "name": "AddressEmptyCode", "inputs": [ { "name": "target", "type": "address", "internalType": "address" } ] }, { "type": "error", "name": "CheckpointUnorderedInsertion", "inputs": [] }, { "type": "error", "name": "DuplicateKeyTag", "inputs": [] }, { "type": "error", "name": "EpochManager_InvalidEpochDuration", "inputs": [] }, { "type": "error", "name": "EpochManager_InvalidEpochDurationTimestamp", "inputs": [] }, { "type": "error", "name": "EpochManager_TooOldTimestamp", "inputs": [] }, { "type": "error", "name": "FailedCall", "inputs": [] }, { "type": "error", "name": "InvalidInitialization", "inputs": [] }, { "type": "error", "name": "InvalidKey", "inputs": [] }, { "type": "error", "name": "InvalidKeyTag", "inputs": [] }, { "type": "error", "name": "NetworkManager_InvalidNetwork", "inputs": [] }, { "type": "error", "name": "NotInitializing", "inputs": [] }, { "type": "error", "name": "ValSetDriver_ChainAlreadyAdded", "inputs": [] }, { "type": "error", "name": "ValSetDriver_InvalidCrossChainAddress", "inputs": [] }, { "type": "error", "name": "ValSetDriver_InvalidMaxValidatorsCount", "inputs": [] }, { "type": "error", "name": "ValSetDriver_InvalidQuorumThreshold", "inputs": [] }, { "type": "error", "name": "ValSetDriver_KeyTagAlreadyAdded", "inputs": [] }, { "type": "error", "name": "ValSetDriver_NotAdded", "inputs": [] }, { "type": "error", "name": "ValSetDriver_ZeroNumAggregators", "inputs": [] }, { "type": "error", "name": "ValSetDriver_ZeroNumCommitters", "inputs": [] } ] ```` ## File: symbiotic/client/evm/abi/IVotingPowerProvider.abi.json ````json [ { "type": "function", "name": "NETWORK", "inputs": [], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "OPERATOR_REGISTRY", "inputs": [], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "SUBNETWORK", "inputs": [], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "SUBNETWORK_IDENTIFIER", "inputs": [], "outputs": [ { "name": "", "type": "uint96", "internalType": "uint96" } ], "stateMutability": "view" }, { "type": "function", "name": "VAULT_FACTORY", "inputs": [], "outputs": [ { "name": "", "type": "address", "internalType": "address" } ], "stateMutability": "view" }, { "type": "function", "name": "eip712Domain", "inputs": [], "outputs": [ { "name": "fields", "type": "bytes1", "internalType": "bytes1" }, { "name": "name", "type": "string", "internalType": "string" }, { "name": "version", "type": "string", "internalType": "string" }, { "name": "chainId", "type": "uint256", "internalType": "uint256" }, { "name": "verifyingContract", "type": "address", "internalType": "address" }, { "name": "salt", "type": "bytes32", "internalType": "bytes32" }, { "name": "extensions", "type": "uint256[]", "internalType": "uint256[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getOperatorStakes", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.VaultValue[]", "components": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "value", "type": "uint256", "internalType": "uint256" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getOperatorStakesAt", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.VaultValue[]", "components": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "value", "type": "uint256", "internalType": "uint256" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getOperatorVaults", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getOperatorVaultsAt", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getOperatorVotingPowers", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "extraData", "type": "bytes", "internalType": "bytes" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.VaultValue[]", "components": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "value", "type": "uint256", "internalType": "uint256" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getOperatorVotingPowersAt", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "extraData", "type": "bytes", "internalType": "bytes" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.VaultValue[]", "components": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "value", "type": "uint256", "internalType": "uint256" } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getOperators", "inputs": [], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getOperatorsAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getSharedVaults", "inputs": [], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getSharedVaultsAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getSlashingData", "inputs": [], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" }, { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getSlashingDataAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" }, { "name": "hint", "type": "bytes", "internalType": "bytes" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" }, { "name": "", "type": "uint48", "internalType": "uint48" } ], "stateMutability": "view" }, { "type": "function", "name": "getTokens", "inputs": [], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getTokensAt", "inputs": [ { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "view" }, { "type": "function", "name": "getVotingPowers", "inputs": [ { "name": "extraData", "type": "bytes[]", "internalType": "bytes[]" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.OperatorVotingPower[]", "components": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "vaults", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.VaultValue[]", "components": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "value", "type": "uint256", "internalType": "uint256" } ] } ] } ], "stateMutability": "view" }, { "type": "function", "name": "getVotingPowersAt", "inputs": [ { "name": "extraData", "type": "bytes[]", "internalType": "bytes[]" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.OperatorVotingPower[]", "components": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "vaults", "type": "tuple[]", "internalType": "struct IVotingPowerProvider.VaultValue[]", "components": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "value", "type": "uint256", "internalType": "uint256" } ] } ] } ], "stateMutability": "view" }, { "type": "function", "name": "hashTypedDataV4", "inputs": [ { "name": "structHash", "type": "bytes32", "internalType": "bytes32" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "hashTypedDataV4CrossChain", "inputs": [ { "name": "structHash", "type": "bytes32", "internalType": "bytes32" } ], "outputs": [ { "name": "", "type": "bytes32", "internalType": "bytes32" } ], "stateMutability": "view" }, { "type": "function", "name": "invalidateOldSignatures", "inputs": [], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "isOperatorRegistered", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isOperatorRegisteredAt", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isOperatorVaultRegistered", "inputs": [ { "name": "vault", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isOperatorVaultRegistered", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "vault", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isOperatorVaultRegisteredAt", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "vault", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isOperatorVaultRegisteredAt", "inputs": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isSharedVaultRegistered", "inputs": [ { "name": "vault", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isSharedVaultRegisteredAt", "inputs": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isTokenRegistered", "inputs": [ { "name": "token", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "isTokenRegisteredAt", "inputs": [ { "name": "token", "type": "address", "internalType": "address" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "", "type": "bool", "internalType": "bool" } ], "stateMutability": "view" }, { "type": "function", "name": "multicall", "inputs": [ { "name": "data", "type": "bytes[]", "internalType": "bytes[]" } ], "outputs": [ { "name": "results", "type": "bytes[]", "internalType": "bytes[]" } ], "stateMutability": "nonpayable" }, { "type": "function", "name": "nonces", "inputs": [ { "name": "owner", "type": "address", "internalType": "address" } ], "outputs": [ { "name": "", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "registerOperator", "inputs": [], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "registerOperatorWithSignature", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "signature", "type": "bytes", "internalType": "bytes" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "stakeToVotingPower", "inputs": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "stake", "type": "uint256", "internalType": "uint256" }, { "name": "extraData", "type": "bytes", "internalType": "bytes" } ], "outputs": [ { "name": "power", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "stakeToVotingPowerAt", "inputs": [ { "name": "vault", "type": "address", "internalType": "address" }, { "name": "stake", "type": "uint256", "internalType": "uint256" }, { "name": "extraData", "type": "bytes", "internalType": "bytes" }, { "name": "timestamp", "type": "uint48", "internalType": "uint48" } ], "outputs": [ { "name": "power", "type": "uint256", "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", "name": "staticDelegateCall", "inputs": [ { "name": "target", "type": "address", "internalType": "address" }, { "name": "data", "type": "bytes", "internalType": "bytes" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "unregisterOperator", "inputs": [], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "unregisterOperatorWithSignature", "inputs": [ { "name": "operator", "type": "address", "internalType": "address" }, { "name": "signature", "type": "bytes", "internalType": "bytes" } ], "outputs": [], "stateMutability": "nonpayable" }, { "type": "event", "name": "EIP712DomainChanged", "inputs": [], "anonymous": false }, { "type": "event", "name": "InitEIP712", "inputs": [ { "name": "name", "type": "string", "indexed": false, "internalType": "string" }, { "name": "version", "type": "string", "indexed": false, "internalType": "string" } ], "anonymous": false }, { "type": "event", "name": "InitSubnetwork", "inputs": [ { "name": "network", "type": "address", "indexed": false, "internalType": "address" }, { "name": "subnetworkId", "type": "uint96", "indexed": false, "internalType": "uint96" } ], "anonymous": false }, { "type": "event", "name": "Initialized", "inputs": [ { "name": "version", "type": "uint64", "indexed": false, "internalType": "uint64" } ], "anonymous": false }, { "type": "event", "name": "RegisterOperator", "inputs": [ { "name": "operator", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "RegisterOperatorVault", "inputs": [ { "name": "operator", "type": "address", "indexed": true, "internalType": "address" }, { "name": "vault", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "RegisterSharedVault", "inputs": [ { "name": "vault", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "RegisterToken", "inputs": [ { "name": "token", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "SetSlashingData", "inputs": [ { "name": "requireSlasher", "type": "bool", "indexed": false, "internalType": "bool" }, { "name": "minVaultEpochDuration", "type": "uint48", "indexed": false, "internalType": "uint48" } ], "anonymous": false }, { "type": "event", "name": "UnregisterOperator", "inputs": [ { "name": "operator", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "UnregisterOperatorVault", "inputs": [ { "name": "operator", "type": "address", "indexed": true, "internalType": "address" }, { "name": "vault", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "UnregisterSharedVault", "inputs": [ { "name": "vault", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "event", "name": "UnregisterToken", "inputs": [ { "name": "token", "type": "address", "indexed": true, "internalType": "address" } ], "anonymous": false }, { "type": "error", "name": "AddressEmptyCode", "inputs": [ { "name": "target", "type": "address", "internalType": "address" } ] }, { "type": "error", "name": "FailedCall", "inputs": [] }, { "type": "error", "name": "InvalidAccountNonce", "inputs": [ { "name": "account", "type": "address", "internalType": "address" }, { "name": "currentNonce", "type": "uint256", "internalType": "uint256" } ] }, { "type": "error", "name": "InvalidInitialization", "inputs": [] }, { "type": "error", "name": "NetworkManager_InvalidNetwork", "inputs": [] }, { "type": "error", "name": "NotInitializing", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_InvalidOperator", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_InvalidOperatorVault", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_InvalidSharedVault", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_InvalidSignature", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_InvalidToken", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_InvalidVault", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_OperatorAlreadyRegistered", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_OperatorNotRegistered", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_OperatorVaultAlreadyIsRegistered", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_OperatorVaultNotRegistered", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_SharedVaultAlreadyIsRegistered", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_SharedVaultNotRegistered", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_TokenAlreadyIsRegistered", "inputs": [] }, { "type": "error", "name": "VotingPowerProvider_TokenNotRegistered", "inputs": [] } ] ```` ## File: symbiotic/client/evm/gen/keyRegistry.go ````go // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. ⋮---- package gen ⋮---- import ( "errors" "math/big" "strings" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ) ⋮---- "errors" "math/big" "strings" ⋮---- ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ⋮---- // Reference imports to suppress errors if they are not otherwise used. var ( _ = errors.New _ = big.NewInt _ = strings.NewReader _ = ethereum.NotFound _ = bind.Bind _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription _ = abi.ConvertType ) ⋮---- // IKeyRegistryKey is an auto generated low-level Go binding around an user-defined struct. type IKeyRegistryKey struct { Tag uint8 Payload []byte } ⋮---- // IKeyRegistryOperatorWithKeys is an auto generated low-level Go binding around an user-defined struct. type IKeyRegistryOperatorWithKeys struct { Operator common.Address Keys []IKeyRegistryKey } ⋮---- // IKeyRegistryMetaData contains all meta data concerning the IKeyRegistry contract. var IKeyRegistryMetaData = &bind.MetaData{ ABI: "[{\"type\":\"function\",\"name\":\"getKey\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tag\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeyAt\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeys\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIKeyRegistry.OperatorWithKeys[]\",\"components\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"keys\",\"type\":\"tuple[]\",\"internalType\":\"structIKeyRegistry.Key[]\",\"components\":[{\"name\":\"tag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"payload\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeys\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIKeyRegistry.Key[]\",\"components\":[{\"name\":\"tag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"payload\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeysAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIKeyRegistry.OperatorWithKeys[]\",\"components\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"keys\",\"type\":\"tuple[]\",\"internalType\":\"structIKeyRegistry.Key[]\",\"components\":[{\"name\":\"tag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"payload\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeysAt\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIKeyRegistry.Key[]\",\"components\":[{\"name\":\"tag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"payload\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeysOperators\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeysOperatorsAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeysOperatorsLength\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperator\",\"inputs\":[{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setKey\",\"inputs\":[{\"name\":\"tag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"key\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"SetKey\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tag\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"},{\"name\":\"key\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"KeyRegistry_AlreadyUsed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"KeyRegistry_InvalidKeySignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"KeyRegistry_InvalidKeyType\",\"inputs\":[]}]", } ⋮---- // IKeyRegistryABI is the input ABI used to generate the binding from. // Deprecated: Use IKeyRegistryMetaData.ABI instead. var IKeyRegistryABI = IKeyRegistryMetaData.ABI ⋮---- // IKeyRegistry is an auto generated Go binding around an Ethereum contract. type IKeyRegistry struct { IKeyRegistryCaller // Read-only binding to the contract IKeyRegistryTransactor // Write-only binding to the contract IKeyRegistryFilterer // Log filterer for contract events } ⋮---- IKeyRegistryCaller // Read-only binding to the contract IKeyRegistryTransactor // Write-only binding to the contract IKeyRegistryFilterer // Log filterer for contract events ⋮---- // IKeyRegistryCaller is an auto generated read-only Go binding around an Ethereum contract. type IKeyRegistryCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- contract *bind.BoundContract // Generic contract wrapper for the low level calls ⋮---- // IKeyRegistryTransactor is an auto generated write-only Go binding around an Ethereum contract. type IKeyRegistryTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // IKeyRegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. type IKeyRegistryFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // IKeyRegistrySession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. type IKeyRegistrySession struct { Contract *IKeyRegistry // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *IKeyRegistry // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // IKeyRegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. type IKeyRegistryCallerSession struct { Contract *IKeyRegistryCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } ⋮---- Contract *IKeyRegistryCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session ⋮---- // IKeyRegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. type IKeyRegistryTransactorSession struct { Contract *IKeyRegistryTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *IKeyRegistryTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // IKeyRegistryRaw is an auto generated low-level Go binding around an Ethereum contract. type IKeyRegistryRaw struct { Contract *IKeyRegistry // Generic contract binding to access the raw methods on } ⋮---- Contract *IKeyRegistry // Generic contract binding to access the raw methods on ⋮---- // IKeyRegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. type IKeyRegistryCallerRaw struct { Contract *IKeyRegistryCaller // Generic read-only contract binding to access the raw methods on } ⋮---- Contract *IKeyRegistryCaller // Generic read-only contract binding to access the raw methods on ⋮---- // IKeyRegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. type IKeyRegistryTransactorRaw struct { Contract *IKeyRegistryTransactor // Generic write-only contract binding to access the raw methods on } ⋮---- Contract *IKeyRegistryTransactor // Generic write-only contract binding to access the raw methods on ⋮---- // NewIKeyRegistry creates a new instance of IKeyRegistry, bound to a specific deployed contract. func NewIKeyRegistry(address common.Address, backend bind.ContractBackend) (*IKeyRegistry, error) ⋮---- // NewIKeyRegistryCaller creates a new read-only instance of IKeyRegistry, bound to a specific deployed contract. func NewIKeyRegistryCaller(address common.Address, caller bind.ContractCaller) (*IKeyRegistryCaller, error) ⋮---- // NewIKeyRegistryTransactor creates a new write-only instance of IKeyRegistry, bound to a specific deployed contract. func NewIKeyRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*IKeyRegistryTransactor, error) ⋮---- // NewIKeyRegistryFilterer creates a new log filterer instance of IKeyRegistry, bound to a specific deployed contract. func NewIKeyRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*IKeyRegistryFilterer, error) ⋮---- // bindIKeyRegistry binds a generic wrapper to an already deployed contract. func bindIKeyRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) ⋮---- // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. func (_IKeyRegistry *IKeyRegistryRaw) Call(opts *bind.CallOpts, result *[]interface ⋮---- // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. func (_IKeyRegistry *IKeyRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // Transact invokes the (paid) contract method with params as input values. func (_IKeyRegistry *IKeyRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface ⋮---- // GetKey is a free data retrieval call binding the contract method 0xb6e1a1e2. // // Solidity: function getKey(address operator, uint8 tag) view returns(bytes) func (_IKeyRegistry *IKeyRegistryCaller) GetKey(opts *bind.CallOpts, operator common.Address, tag uint8) ([]byte, error) ⋮---- var out []interface{} ⋮---- // GetKeyAt is a free data retrieval call binding the contract method 0xb1dab20f. ⋮---- // Solidity: function getKeyAt(address operator, uint8 tag, uint48 timestamp) view returns(bytes) func (_IKeyRegistry *IKeyRegistryCaller) GetKeyAt(opts *bind.CallOpts, operator common.Address, tag uint8, timestamp *big.Int) ([]byte, error) ⋮---- // GetKeys is a free data retrieval call binding the contract method 0x2150c518. ⋮---- // Solidity: function getKeys() view returns((address,(uint8,bytes)[])[]) func (_IKeyRegistry *IKeyRegistryCaller) GetKeys(opts *bind.CallOpts) ([]IKeyRegistryOperatorWithKeys, error) ⋮---- // GetKeys0 is a free data retrieval call binding the contract method 0x34e80c34. ⋮---- // Solidity: function getKeys(address operator) view returns((uint8,bytes)[]) func (_IKeyRegistry *IKeyRegistryCaller) GetKeys0(opts *bind.CallOpts, operator common.Address) ([]IKeyRegistryKey, error) ⋮---- // GetKeysAt is a free data retrieval call binding the contract method 0x256d1be5. ⋮---- // Solidity: function getKeysAt(uint48 timestamp) view returns((address,(uint8,bytes)[])[]) func (_IKeyRegistry *IKeyRegistryCaller) GetKeysAt(opts *bind.CallOpts, timestamp *big.Int) ([]IKeyRegistryOperatorWithKeys, error) ⋮---- // GetKeysAt0 is a free data retrieval call binding the contract method 0x26cb1f1c. ⋮---- // Solidity: function getKeysAt(address operator, uint48 timestamp) view returns((uint8,bytes)[]) func (_IKeyRegistry *IKeyRegistryCaller) GetKeysAt0(opts *bind.CallOpts, operator common.Address, timestamp *big.Int) ([]IKeyRegistryKey, error) ⋮---- // GetKeysOperators is a free data retrieval call binding the contract method 0x20d268de. ⋮---- // Solidity: function getKeysOperators() view returns(address[]) func (_IKeyRegistry *IKeyRegistryCaller) GetKeysOperators(opts *bind.CallOpts) ([]common.Address, error) ⋮---- // GetKeysOperatorsAt is a free data retrieval call binding the contract method 0xf493b5f3. ⋮---- // Solidity: function getKeysOperatorsAt(uint48 timestamp) view returns(address[]) func (_IKeyRegistry *IKeyRegistryCaller) GetKeysOperatorsAt(opts *bind.CallOpts, timestamp *big.Int) ([]common.Address, error) ⋮---- // GetKeysOperatorsLength is a free data retrieval call binding the contract method 0xd201ab93. ⋮---- // Solidity: function getKeysOperatorsLength() view returns(uint256) func (_IKeyRegistry *IKeyRegistryCaller) GetKeysOperatorsLength(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetOperator is a free data retrieval call binding the contract method 0x9eaffa96. ⋮---- // Solidity: function getOperator(bytes key) view returns(address) func (_IKeyRegistry *IKeyRegistryCaller) GetOperator(opts *bind.CallOpts, key []byte) (common.Address, error) ⋮---- // SetKey is a paid mutator transaction binding the contract method 0xc1ef9aca. ⋮---- // Solidity: function setKey(uint8 tag, bytes key, bytes signature, bytes extraData) returns() func (_IKeyRegistry *IKeyRegistryTransactor) SetKey(opts *bind.TransactOpts, tag uint8, key []byte, signature []byte, extraData []byte) (*types.Transaction, error) ⋮---- // IKeyRegistrySetKeyIterator is returned from FilterSetKey and is used to iterate over the raw logs and unpacked data for SetKey events raised by the IKeyRegistry contract. type IKeyRegistrySetKeyIterator struct { Event *IKeyRegistrySetKey // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IKeyRegistrySetKey // Event containing the contract specifics and raw log ⋮---- contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data ⋮---- logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration ⋮---- // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. func (it *IKeyRegistrySetKeyIterator) Next() bool ⋮---- // If the iterator failed, stop iterating ⋮---- // If the iterator completed, deliver directly whatever's available ⋮---- // Iterator still in progress, wait for either a data or an error event ⋮---- // Error returns any retrieval or parsing error occurred during filtering. func (it *IKeyRegistrySetKeyIterator) Error() error ⋮---- // Close terminates the iteration process, releasing any pending underlying // resources. func (it *IKeyRegistrySetKeyIterator) Close() error ⋮---- // IKeyRegistrySetKey represents a SetKey event raised by the IKeyRegistry contract. type IKeyRegistrySetKey struct { Operator common.Address Tag uint8 Key common.Hash ExtraData []byte Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetKey is a free log retrieval operation binding the contract event 0x980cfe4e76cbf6d3ba24c2161089e5e1b2f98e31821b6afdf5a4d596bee91fcd. ⋮---- // Solidity: event SetKey(address indexed operator, uint8 indexed tag, bytes indexed key, bytes extraData) func (_IKeyRegistry *IKeyRegistryFilterer) FilterSetKey(opts *bind.FilterOpts, operator []common.Address, tag []uint8, key [][]byte) (*IKeyRegistrySetKeyIterator, error) ⋮---- var operatorRule []interface{} ⋮---- var tagRule []interface{} ⋮---- var keyRule []interface{} ⋮---- // WatchSetKey is a free log subscription operation binding the contract event 0x980cfe4e76cbf6d3ba24c2161089e5e1b2f98e31821b6afdf5a4d596bee91fcd. ⋮---- func (_IKeyRegistry *IKeyRegistryFilterer) WatchSetKey(opts *bind.WatchOpts, sink chan<- *IKeyRegistrySetKey, operator []common.Address, tag []uint8, key [][]byte) (event.Subscription, error) ⋮---- // New log arrived, parse the event and forward to the user ⋮---- // ParseSetKey is a log parse operation binding the contract event 0x980cfe4e76cbf6d3ba24c2161089e5e1b2f98e31821b6afdf5a4d596bee91fcd. ⋮---- func (_IKeyRegistry *IKeyRegistryFilterer) ParseSetKey(log types.Log) (*IKeyRegistrySetKey, error) ```` ## File: symbiotic/client/evm/gen/multicall3.go ````go // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. ⋮---- package gen ⋮---- import ( "errors" "math/big" "strings" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ) ⋮---- "errors" "math/big" "strings" ⋮---- ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ⋮---- // Reference imports to suppress errors if they are not otherwise used. var ( _ = errors.New _ = big.NewInt _ = strings.NewReader _ = ethereum.NotFound _ = bind.Bind _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription _ = abi.ConvertType ) ⋮---- // Multicall3Call is an auto generated low-level Go binding around an user-defined struct. type Multicall3Call struct { Target common.Address CallData []byte } ⋮---- // Multicall3Call3 is an auto generated low-level Go binding around an user-defined struct. type Multicall3Call3 struct { Target common.Address AllowFailure bool CallData []byte } ⋮---- // Multicall3Call3Value is an auto generated low-level Go binding around an user-defined struct. type Multicall3Call3Value struct { Target common.Address AllowFailure bool Value *big.Int CallData []byte } ⋮---- // Multicall3Result is an auto generated low-level Go binding around an user-defined struct. type Multicall3Result struct { Success bool ReturnData []byte } ⋮---- // Multicall3MetaData contains all meta data concerning the Multicall3 contract. var Multicall3MetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call3[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call3Value[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3Value\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"basefee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainid\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", } ⋮---- // Multicall3ABI is the input ABI used to generate the binding from. // Deprecated: Use Multicall3MetaData.ABI instead. var Multicall3ABI = Multicall3MetaData.ABI ⋮---- // Multicall3 is an auto generated Go binding around an Ethereum contract. type Multicall3 struct { Multicall3Caller // Read-only binding to the contract Multicall3Transactor // Write-only binding to the contract Multicall3Filterer // Log filterer for contract events } ⋮---- Multicall3Caller // Read-only binding to the contract Multicall3Transactor // Write-only binding to the contract Multicall3Filterer // Log filterer for contract events ⋮---- // Multicall3Caller is an auto generated read-only Go binding around an Ethereum contract. type Multicall3Caller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- contract *bind.BoundContract // Generic contract wrapper for the low level calls ⋮---- // Multicall3Transactor is an auto generated write-only Go binding around an Ethereum contract. type Multicall3Transactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // Multicall3Filterer is an auto generated log filtering Go binding around an Ethereum contract events. type Multicall3Filterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // Multicall3Session is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. type Multicall3Session struct { Contract *Multicall3 // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *Multicall3 // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // Multicall3CallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. type Multicall3CallerSession struct { Contract *Multicall3Caller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } ⋮---- Contract *Multicall3Caller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session ⋮---- // Multicall3TransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. type Multicall3TransactorSession struct { Contract *Multicall3Transactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *Multicall3Transactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // Multicall3Raw is an auto generated low-level Go binding around an Ethereum contract. type Multicall3Raw struct { Contract *Multicall3 // Generic contract binding to access the raw methods on } ⋮---- Contract *Multicall3 // Generic contract binding to access the raw methods on ⋮---- // Multicall3CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. type Multicall3CallerRaw struct { Contract *Multicall3Caller // Generic read-only contract binding to access the raw methods on } ⋮---- Contract *Multicall3Caller // Generic read-only contract binding to access the raw methods on ⋮---- // Multicall3TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. type Multicall3TransactorRaw struct { Contract *Multicall3Transactor // Generic write-only contract binding to access the raw methods on } ⋮---- Contract *Multicall3Transactor // Generic write-only contract binding to access the raw methods on ⋮---- // NewMulticall3 creates a new instance of Multicall3, bound to a specific deployed contract. func NewMulticall3(address common.Address, backend bind.ContractBackend) (*Multicall3, error) ⋮---- // NewMulticall3Caller creates a new read-only instance of Multicall3, bound to a specific deployed contract. func NewMulticall3Caller(address common.Address, caller bind.ContractCaller) (*Multicall3Caller, error) ⋮---- // NewMulticall3Transactor creates a new write-only instance of Multicall3, bound to a specific deployed contract. func NewMulticall3Transactor(address common.Address, transactor bind.ContractTransactor) (*Multicall3Transactor, error) ⋮---- // NewMulticall3Filterer creates a new log filterer instance of Multicall3, bound to a specific deployed contract. func NewMulticall3Filterer(address common.Address, filterer bind.ContractFilterer) (*Multicall3Filterer, error) ⋮---- // bindMulticall3 binds a generic wrapper to an already deployed contract. func bindMulticall3(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) ⋮---- // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. func (_Multicall3 *Multicall3Raw) Call(opts *bind.CallOpts, result *[]interface ⋮---- // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. func (_Multicall3 *Multicall3Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // Transact invokes the (paid) contract method with params as input values. func (_Multicall3 *Multicall3Raw) Transact(opts *bind.TransactOpts, method string, params ...interface ⋮---- // Aggregate is a free data retrieval call binding the contract method 0x252dba42. // // Solidity: function aggregate((address,bytes)[] calls) view returns(uint256 blockNumber, bytes[] returnData) func (_Multicall3 *Multicall3Caller) Aggregate(opts *bind.CallOpts, calls []Multicall3Call) (struct ⋮---- var out []interface{} ⋮---- // Aggregate3 is a free data retrieval call binding the contract method 0x82ad56cb. ⋮---- // Solidity: function aggregate3((address,bool,bytes)[] calls) view returns((bool,bytes)[] returnData) func (_Multicall3 *Multicall3Caller) Aggregate3(opts *bind.CallOpts, calls []Multicall3Call3) ([]Multicall3Result, error) ⋮---- // Aggregate3Value is a free data retrieval call binding the contract method 0x174dea71. ⋮---- // Solidity: function aggregate3Value((address,bool,uint256,bytes)[] calls) view returns((bool,bytes)[] returnData) func (_Multicall3 *Multicall3Caller) Aggregate3Value(opts *bind.CallOpts, calls []Multicall3Call3Value) ([]Multicall3Result, error) ⋮---- // BlockAndAggregate is a free data retrieval call binding the contract method 0xc3077fa9. ⋮---- // Solidity: function blockAndAggregate((address,bytes)[] calls) view returns(uint256 blockNumber, bytes32 blockHash, (bool,bytes)[] returnData) func (_Multicall3 *Multicall3Caller) BlockAndAggregate(opts *bind.CallOpts, calls []Multicall3Call) (struct ⋮---- // GetBasefee is a free data retrieval call binding the contract method 0x3e64a696. ⋮---- // Solidity: function getBasefee() view returns(uint256 basefee) func (_Multicall3 *Multicall3Caller) GetBasefee(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetBlockHash is a free data retrieval call binding the contract method 0xee82ac5e. ⋮---- // Solidity: function getBlockHash(uint256 blockNumber) view returns(bytes32 blockHash) func (_Multicall3 *Multicall3Caller) GetBlockHash(opts *bind.CallOpts, blockNumber *big.Int) ([32]byte, error) ⋮---- // GetBlockNumber is a free data retrieval call binding the contract method 0x42cbb15c. ⋮---- // Solidity: function getBlockNumber() view returns(uint256 blockNumber) func (_Multicall3 *Multicall3Caller) GetBlockNumber(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetChainId is a free data retrieval call binding the contract method 0x3408e470. ⋮---- // Solidity: function getChainId() view returns(uint256 chainid) func (_Multicall3 *Multicall3Caller) GetChainId(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetCurrentBlockCoinbase is a free data retrieval call binding the contract method 0xa8b0574e. ⋮---- // Solidity: function getCurrentBlockCoinbase() view returns(address coinbase) func (_Multicall3 *Multicall3Caller) GetCurrentBlockCoinbase(opts *bind.CallOpts) (common.Address, error) ⋮---- // GetCurrentBlockDifficulty is a free data retrieval call binding the contract method 0x72425d9d. ⋮---- // Solidity: function getCurrentBlockDifficulty() view returns(uint256 difficulty) func (_Multicall3 *Multicall3Caller) GetCurrentBlockDifficulty(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetCurrentBlockGasLimit is a free data retrieval call binding the contract method 0x86d516e8. ⋮---- // Solidity: function getCurrentBlockGasLimit() view returns(uint256 gaslimit) func (_Multicall3 *Multicall3Caller) GetCurrentBlockGasLimit(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetCurrentBlockTimestamp is a free data retrieval call binding the contract method 0x0f28c97d. ⋮---- // Solidity: function getCurrentBlockTimestamp() view returns(uint256 timestamp) func (_Multicall3 *Multicall3Caller) GetCurrentBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetEthBalance is a free data retrieval call binding the contract method 0x4d2301cc. ⋮---- // Solidity: function getEthBalance(address addr) view returns(uint256 balance) func (_Multicall3 *Multicall3Caller) GetEthBalance(opts *bind.CallOpts, addr common.Address) (*big.Int, error) ⋮---- // GetLastBlockHash is a free data retrieval call binding the contract method 0x27e86d6e. ⋮---- // Solidity: function getLastBlockHash() view returns(bytes32 blockHash) func (_Multicall3 *Multicall3Caller) GetLastBlockHash(opts *bind.CallOpts) ([32]byte, error) ⋮---- // TryAggregate is a free data retrieval call binding the contract method 0xbce38bd7. ⋮---- // Solidity: function tryAggregate(bool requireSuccess, (address,bytes)[] calls) view returns((bool,bytes)[] returnData) func (_Multicall3 *Multicall3Caller) TryAggregate(opts *bind.CallOpts, requireSuccess bool, calls []Multicall3Call) ([]Multicall3Result, error) ⋮---- // TryBlockAndAggregate is a free data retrieval call binding the contract method 0x399542e9. ⋮---- // Solidity: function tryBlockAndAggregate(bool requireSuccess, (address,bytes)[] calls) view returns(uint256 blockNumber, bytes32 blockHash, (bool,bytes)[] returnData) func (_Multicall3 *Multicall3Caller) TryBlockAndAggregate(opts *bind.CallOpts, requireSuccess bool, calls []Multicall3Call) (struct ```` ## File: symbiotic/client/evm/gen/operatorRegistry.go ````go // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. ⋮---- package gen ⋮---- import ( "errors" "math/big" "strings" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ) ⋮---- "errors" "math/big" "strings" ⋮---- ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ⋮---- // Reference imports to suppress errors if they are not otherwise used. var ( _ = errors.New _ = big.NewInt _ = strings.NewReader _ = ethereum.NotFound _ = bind.Bind _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription _ = abi.ConvertType ) ⋮---- // OperatorRegistryMetaData contains all meta data concerning the OperatorRegistry contract. var OperatorRegistryMetaData = &bind.MetaData{ ABI: "[{\"type\":\"function\",\"name\":\"entity\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isEntity\",\"inputs\":[{\"name\":\"entity_\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"registerOperator\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"totalEntities\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AddEntity\",\"inputs\":[{\"name\":\"entity\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"EntityNotExist\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OperatorAlreadyRegistered\",\"inputs\":[]}]", } ⋮---- // OperatorRegistryABI is the input ABI used to generate the binding from. // Deprecated: Use OperatorRegistryMetaData.ABI instead. var OperatorRegistryABI = OperatorRegistryMetaData.ABI ⋮---- // OperatorRegistry is an auto generated Go binding around an Ethereum contract. type OperatorRegistry struct { OperatorRegistryCaller // Read-only binding to the contract OperatorRegistryTransactor // Write-only binding to the contract OperatorRegistryFilterer // Log filterer for contract events } ⋮---- OperatorRegistryCaller // Read-only binding to the contract OperatorRegistryTransactor // Write-only binding to the contract OperatorRegistryFilterer // Log filterer for contract events ⋮---- // OperatorRegistryCaller is an auto generated read-only Go binding around an Ethereum contract. type OperatorRegistryCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- contract *bind.BoundContract // Generic contract wrapper for the low level calls ⋮---- // OperatorRegistryTransactor is an auto generated write-only Go binding around an Ethereum contract. type OperatorRegistryTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // OperatorRegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. type OperatorRegistryFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // OperatorRegistrySession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. type OperatorRegistrySession struct { Contract *OperatorRegistry // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *OperatorRegistry // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // OperatorRegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. type OperatorRegistryCallerSession struct { Contract *OperatorRegistryCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } ⋮---- Contract *OperatorRegistryCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session ⋮---- // OperatorRegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. type OperatorRegistryTransactorSession struct { Contract *OperatorRegistryTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *OperatorRegistryTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // OperatorRegistryRaw is an auto generated low-level Go binding around an Ethereum contract. type OperatorRegistryRaw struct { Contract *OperatorRegistry // Generic contract binding to access the raw methods on } ⋮---- Contract *OperatorRegistry // Generic contract binding to access the raw methods on ⋮---- // OperatorRegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. type OperatorRegistryCallerRaw struct { Contract *OperatorRegistryCaller // Generic read-only contract binding to access the raw methods on } ⋮---- Contract *OperatorRegistryCaller // Generic read-only contract binding to access the raw methods on ⋮---- // OperatorRegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. type OperatorRegistryTransactorRaw struct { Contract *OperatorRegistryTransactor // Generic write-only contract binding to access the raw methods on } ⋮---- Contract *OperatorRegistryTransactor // Generic write-only contract binding to access the raw methods on ⋮---- // NewOperatorRegistry creates a new instance of OperatorRegistry, bound to a specific deployed contract. func NewOperatorRegistry(address common.Address, backend bind.ContractBackend) (*OperatorRegistry, error) ⋮---- // NewOperatorRegistryCaller creates a new read-only instance of OperatorRegistry, bound to a specific deployed contract. func NewOperatorRegistryCaller(address common.Address, caller bind.ContractCaller) (*OperatorRegistryCaller, error) ⋮---- // NewOperatorRegistryTransactor creates a new write-only instance of OperatorRegistry, bound to a specific deployed contract. func NewOperatorRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*OperatorRegistryTransactor, error) ⋮---- // NewOperatorRegistryFilterer creates a new log filterer instance of OperatorRegistry, bound to a specific deployed contract. func NewOperatorRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*OperatorRegistryFilterer, error) ⋮---- // bindOperatorRegistry binds a generic wrapper to an already deployed contract. func bindOperatorRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) ⋮---- // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. func (_OperatorRegistry *OperatorRegistryRaw) Call(opts *bind.CallOpts, result *[]interface ⋮---- // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. func (_OperatorRegistry *OperatorRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // Transact invokes the (paid) contract method with params as input values. func (_OperatorRegistry *OperatorRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface ⋮---- // Entity is a free data retrieval call binding the contract method 0xb42ba2a2. // // Solidity: function entity(uint256 index) view returns(address) func (_OperatorRegistry *OperatorRegistryCaller) Entity(opts *bind.CallOpts, index *big.Int) (common.Address, error) ⋮---- var out []interface{} ⋮---- // IsEntity is a free data retrieval call binding the contract method 0x14887c58. ⋮---- // Solidity: function isEntity(address entity_) view returns(bool) func (_OperatorRegistry *OperatorRegistryCaller) IsEntity(opts *bind.CallOpts, entity_ common.Address) (bool, error) ⋮---- // TotalEntities is a free data retrieval call binding the contract method 0x5cd8b15e. ⋮---- // Solidity: function totalEntities() view returns(uint256) func (_OperatorRegistry *OperatorRegistryCaller) TotalEntities(opts *bind.CallOpts) (*big.Int, error) ⋮---- // RegisterOperator is a paid mutator transaction binding the contract method 0x2acde098. ⋮---- // Solidity: function registerOperator() returns() func (_OperatorRegistry *OperatorRegistryTransactor) RegisterOperator(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // OperatorRegistryAddEntityIterator is returned from FilterAddEntity and is used to iterate over the raw logs and unpacked data for AddEntity events raised by the OperatorRegistry contract. type OperatorRegistryAddEntityIterator struct { Event *OperatorRegistryAddEntity // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *OperatorRegistryAddEntity // Event containing the contract specifics and raw log ⋮---- contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data ⋮---- logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration ⋮---- // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. func (it *OperatorRegistryAddEntityIterator) Next() bool ⋮---- // If the iterator failed, stop iterating ⋮---- // If the iterator completed, deliver directly whatever's available ⋮---- // Iterator still in progress, wait for either a data or an error event ⋮---- // Error returns any retrieval or parsing error occurred during filtering. func (it *OperatorRegistryAddEntityIterator) Error() error ⋮---- // Close terminates the iteration process, releasing any pending underlying // resources. func (it *OperatorRegistryAddEntityIterator) Close() error ⋮---- // OperatorRegistryAddEntity represents a AddEntity event raised by the OperatorRegistry contract. type OperatorRegistryAddEntity struct { Entity common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterAddEntity is a free log retrieval operation binding the contract event 0xb919910dcefbf753bfd926ab3b1d3f85d877190c3d01ba1bd585047b99b99f0b. ⋮---- // Solidity: event AddEntity(address indexed entity) func (_OperatorRegistry *OperatorRegistryFilterer) FilterAddEntity(opts *bind.FilterOpts, entity []common.Address) (*OperatorRegistryAddEntityIterator, error) ⋮---- var entityRule []interface{} ⋮---- // WatchAddEntity is a free log subscription operation binding the contract event 0xb919910dcefbf753bfd926ab3b1d3f85d877190c3d01ba1bd585047b99b99f0b. ⋮---- func (_OperatorRegistry *OperatorRegistryFilterer) WatchAddEntity(opts *bind.WatchOpts, sink chan<- *OperatorRegistryAddEntity, entity []common.Address) (event.Subscription, error) ⋮---- // New log arrived, parse the event and forward to the user ⋮---- // ParseAddEntity is a log parse operation binding the contract event 0xb919910dcefbf753bfd926ab3b1d3f85d877190c3d01ba1bd585047b99b99f0b. ⋮---- func (_OperatorRegistry *OperatorRegistryFilterer) ParseAddEntity(log types.Log) (*OperatorRegistryAddEntity, error) ```` ## File: symbiotic/client/evm/gen/settlement.go ````go // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. ⋮---- package gen ⋮---- import ( "errors" "math/big" "strings" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ) ⋮---- "errors" "math/big" "strings" ⋮---- ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ⋮---- // Reference imports to suppress errors if they are not otherwise used. var ( _ = errors.New _ = big.NewInt _ = strings.NewReader _ = ethereum.NotFound _ = bind.Bind _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription _ = abi.ConvertType ) ⋮---- // ISettlementExtraData is an auto generated low-level Go binding around an user-defined struct. type ISettlementExtraData struct { Key [32]byte Value [32]byte } ⋮---- // ISettlementValSetHeader is an auto generated low-level Go binding around an user-defined struct. type ISettlementValSetHeader struct { Version uint8 RequiredKeyTag uint8 Epoch *big.Int CaptureTimestamp *big.Int QuorumThreshold *big.Int TotalVotingPower *big.Int ValidatorsSszMRoot [32]byte } ⋮---- // ISettlementMetaData contains all meta data concerning the ISettlement contract. var ISettlementMetaData = &bind.MetaData{ ABI: "[{\"type\":\"function\",\"name\":\"NETWORK\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SUBNETWORK\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SUBNETWORK_IDENTIFIER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint96\",\"internalType\":\"uint96\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VALIDATOR_SET_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"commitValSetHeader\",\"inputs\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structISettlement.ValSetHeader\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"requiredKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"captureTimestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"totalVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"validatorsSszMRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"extraData\",\"type\":\"tuple[]\",\"internalType\":\"structISettlement.ExtraData[]\",\"components\":[{\"name\":\"key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"value\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"eip712Domain\",\"inputs\":[],\"outputs\":[{\"name\":\"fields\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"},{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"salt\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"extensions\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCaptureTimestampFromValSetHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCaptureTimestampFromValSetHeaderAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getExtraData\",\"inputs\":[{\"name\":\"key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getExtraDataAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getLastCommittedHeaderEpoch\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getQuorumThresholdFromValSetHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getQuorumThresholdFromValSetHeaderAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredKeyTagFromValSetHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredKeyTagFromValSetHeaderAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSigVerifier\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSigVerifierAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"hint\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTotalVotingPowerFromValSetHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTotalVotingPowerFromValSetHeaderAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValSetHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structISettlement.ValSetHeader\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"requiredKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"captureTimestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"totalVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"validatorsSszMRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValSetHeaderAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structISettlement.ValSetHeader\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"requiredKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"captureTimestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"totalVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"validatorsSszMRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValSetHeaderHash\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValSetHeaderHashAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValidatorsSszMRootFromValSetHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValidatorsSszMRootFromValSetHeaderAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVersionFromValSetHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVersionFromValSetHeaderAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hashTypedDataV4\",\"inputs\":[{\"name\":\"structHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hashTypedDataV4CrossChain\",\"inputs\":[{\"name\":\"structHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isValSetHeaderCommittedAt\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setGenesis\",\"inputs\":[{\"name\":\"valSetHeader\",\"type\":\"tuple\",\"internalType\":\"structISettlement.ValSetHeader\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"requiredKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"captureTimestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"totalVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"validatorsSszMRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"extraData\",\"type\":\"tuple[]\",\"internalType\":\"structISettlement.ExtraData[]\",\"components\":[{\"name\":\"key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"value\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setSigVerifier\",\"inputs\":[{\"name\":\"sigVerifier\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"staticDelegateCall\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verifyQuorumSig\",\"inputs\":[{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyQuorumSigAt\",\"inputs\":[{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"hint\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"CommitValSetHeader\",\"inputs\":[{\"name\":\"valSetHeader\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structISettlement.ValSetHeader\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"requiredKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"captureTimestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"totalVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"validatorsSszMRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"extraData\",\"type\":\"tuple[]\",\"indexed\":false,\"internalType\":\"structISettlement.ExtraData[]\",\"components\":[{\"name\":\"key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"value\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"EIP712DomainChanged\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitEIP712\",\"inputs\":[{\"name\":\"name\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitSigVerifier\",\"inputs\":[{\"name\":\"sigVerifier\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitSubnetwork\",\"inputs\":[{\"name\":\"network\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"subnetworkId\",\"type\":\"uint96\",\"indexed\":false,\"internalType\":\"uint96\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetGenesis\",\"inputs\":[{\"name\":\"valSetHeader\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structISettlement.ValSetHeader\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"requiredKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"captureTimestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"quorumThreshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"totalVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"validatorsSszMRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"extraData\",\"type\":\"tuple[]\",\"indexed\":false,\"internalType\":\"structISettlement.ExtraData[]\",\"components\":[{\"name\":\"key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"value\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetSigVerifier\",\"inputs\":[{\"name\":\"sigVerifier\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CheckpointUnorderedInsertion\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidKeyTag\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NetworkManager_InvalidNetwork\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_DuplicateExtraDataKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_InvalidCaptureTimestamp\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_InvalidEpoch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_InvalidSigVerifier\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_InvalidValidatorsSszMRoot\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_InvalidVersion\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_QuorumThresholdGtTotalVotingPower\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_ValSetHeaderAlreadyCommitted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Settlement_VerificationFailed\",\"inputs\":[]}]", } ⋮---- // ISettlementABI is the input ABI used to generate the binding from. // Deprecated: Use ISettlementMetaData.ABI instead. var ISettlementABI = ISettlementMetaData.ABI ⋮---- // ISettlement is an auto generated Go binding around an Ethereum contract. type ISettlement struct { ISettlementCaller // Read-only binding to the contract ISettlementTransactor // Write-only binding to the contract ISettlementFilterer // Log filterer for contract events } ⋮---- ISettlementCaller // Read-only binding to the contract ISettlementTransactor // Write-only binding to the contract ISettlementFilterer // Log filterer for contract events ⋮---- // ISettlementCaller is an auto generated read-only Go binding around an Ethereum contract. type ISettlementCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- contract *bind.BoundContract // Generic contract wrapper for the low level calls ⋮---- // ISettlementTransactor is an auto generated write-only Go binding around an Ethereum contract. type ISettlementTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // ISettlementFilterer is an auto generated log filtering Go binding around an Ethereum contract events. type ISettlementFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // ISettlementSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. type ISettlementSession struct { Contract *ISettlement // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *ISettlement // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // ISettlementCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. type ISettlementCallerSession struct { Contract *ISettlementCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } ⋮---- Contract *ISettlementCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session ⋮---- // ISettlementTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. type ISettlementTransactorSession struct { Contract *ISettlementTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *ISettlementTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // ISettlementRaw is an auto generated low-level Go binding around an Ethereum contract. type ISettlementRaw struct { Contract *ISettlement // Generic contract binding to access the raw methods on } ⋮---- Contract *ISettlement // Generic contract binding to access the raw methods on ⋮---- // ISettlementCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. type ISettlementCallerRaw struct { Contract *ISettlementCaller // Generic read-only contract binding to access the raw methods on } ⋮---- Contract *ISettlementCaller // Generic read-only contract binding to access the raw methods on ⋮---- // ISettlementTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. type ISettlementTransactorRaw struct { Contract *ISettlementTransactor // Generic write-only contract binding to access the raw methods on } ⋮---- Contract *ISettlementTransactor // Generic write-only contract binding to access the raw methods on ⋮---- // NewISettlement creates a new instance of ISettlement, bound to a specific deployed contract. func NewISettlement(address common.Address, backend bind.ContractBackend) (*ISettlement, error) ⋮---- // NewISettlementCaller creates a new read-only instance of ISettlement, bound to a specific deployed contract. func NewISettlementCaller(address common.Address, caller bind.ContractCaller) (*ISettlementCaller, error) ⋮---- // NewISettlementTransactor creates a new write-only instance of ISettlement, bound to a specific deployed contract. func NewISettlementTransactor(address common.Address, transactor bind.ContractTransactor) (*ISettlementTransactor, error) ⋮---- // NewISettlementFilterer creates a new log filterer instance of ISettlement, bound to a specific deployed contract. func NewISettlementFilterer(address common.Address, filterer bind.ContractFilterer) (*ISettlementFilterer, error) ⋮---- // bindISettlement binds a generic wrapper to an already deployed contract. func bindISettlement(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) ⋮---- // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. func (_ISettlement *ISettlementRaw) Call(opts *bind.CallOpts, result *[]interface ⋮---- // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. func (_ISettlement *ISettlementRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // Transact invokes the (paid) contract method with params as input values. func (_ISettlement *ISettlementRaw) Transact(opts *bind.TransactOpts, method string, params ...interface ⋮---- // NETWORK is a free data retrieval call binding the contract method 0x8759e6d1. // // Solidity: function NETWORK() view returns(address) func (_ISettlement *ISettlementCaller) NETWORK(opts *bind.CallOpts) (common.Address, error) ⋮---- var out []interface{} ⋮---- // SUBNETWORK is a free data retrieval call binding the contract method 0x773e6b54. ⋮---- // Solidity: function SUBNETWORK() view returns(bytes32) func (_ISettlement *ISettlementCaller) SUBNETWORK(opts *bind.CallOpts) ([32]byte, error) ⋮---- // SUBNETWORKIDENTIFIER is a free data retrieval call binding the contract method 0xabacb807. ⋮---- // Solidity: function SUBNETWORK_IDENTIFIER() view returns(uint96) func (_ISettlement *ISettlementCaller) SUBNETWORKIDENTIFIER(opts *bind.CallOpts) (*big.Int, error) ⋮---- // VALIDATORSETVERSION is a free data retrieval call binding the contract method 0x321d7b8d. ⋮---- // Solidity: function VALIDATOR_SET_VERSION() view returns(uint8) func (_ISettlement *ISettlementCaller) VALIDATORSETVERSION(opts *bind.CallOpts) (uint8, error) ⋮---- // Eip712Domain is a free data retrieval call binding the contract method 0x84b0196e. ⋮---- // Solidity: function eip712Domain() view returns(bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions) func (_ISettlement *ISettlementCaller) Eip712Domain(opts *bind.CallOpts) (struct ⋮---- // GetCaptureTimestampFromValSetHeader is a free data retrieval call binding the contract method 0xf4935d39. ⋮---- // Solidity: function getCaptureTimestampFromValSetHeader() view returns(uint48) func (_ISettlement *ISettlementCaller) GetCaptureTimestampFromValSetHeader(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetCaptureTimestampFromValSetHeaderAt is a free data retrieval call binding the contract method 0x5485b549. ⋮---- // Solidity: function getCaptureTimestampFromValSetHeaderAt(uint48 epoch) view returns(uint48) func (_ISettlement *ISettlementCaller) GetCaptureTimestampFromValSetHeaderAt(opts *bind.CallOpts, epoch *big.Int) (*big.Int, error) ⋮---- // GetExtraData is a free data retrieval call binding the contract method 0xecae6344. ⋮---- // Solidity: function getExtraData(bytes32 key) view returns(bytes32) func (_ISettlement *ISettlementCaller) GetExtraData(opts *bind.CallOpts, key [32]byte) ([32]byte, error) ⋮---- // GetExtraDataAt is a free data retrieval call binding the contract method 0x52bb038a. ⋮---- // Solidity: function getExtraDataAt(uint48 epoch, bytes32 key) view returns(bytes32) func (_ISettlement *ISettlementCaller) GetExtraDataAt(opts *bind.CallOpts, epoch *big.Int, key [32]byte) ([32]byte, error) ⋮---- // GetLastCommittedHeaderEpoch is a free data retrieval call binding the contract method 0x65b0849b. ⋮---- // Solidity: function getLastCommittedHeaderEpoch() view returns(uint48) func (_ISettlement *ISettlementCaller) GetLastCommittedHeaderEpoch(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetQuorumThresholdFromValSetHeader is a free data retrieval call binding the contract method 0xe586b38e. ⋮---- // Solidity: function getQuorumThresholdFromValSetHeader() view returns(uint256) func (_ISettlement *ISettlementCaller) GetQuorumThresholdFromValSetHeader(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetQuorumThresholdFromValSetHeaderAt is a free data retrieval call binding the contract method 0x1d86bd88. ⋮---- // Solidity: function getQuorumThresholdFromValSetHeaderAt(uint48 epoch) view returns(uint256) func (_ISettlement *ISettlementCaller) GetQuorumThresholdFromValSetHeaderAt(opts *bind.CallOpts, epoch *big.Int) (*big.Int, error) ⋮---- // GetRequiredKeyTagFromValSetHeader is a free data retrieval call binding the contract method 0xb91a434a. ⋮---- // Solidity: function getRequiredKeyTagFromValSetHeader() view returns(uint8) func (_ISettlement *ISettlementCaller) GetRequiredKeyTagFromValSetHeader(opts *bind.CallOpts) (uint8, error) ⋮---- // GetRequiredKeyTagFromValSetHeaderAt is a free data retrieval call binding the contract method 0xe4378ed2. ⋮---- // Solidity: function getRequiredKeyTagFromValSetHeaderAt(uint48 epoch) view returns(uint8) func (_ISettlement *ISettlementCaller) GetRequiredKeyTagFromValSetHeaderAt(opts *bind.CallOpts, epoch *big.Int) (uint8, error) ⋮---- // GetSigVerifier is a free data retrieval call binding the contract method 0x5b28556d. ⋮---- // Solidity: function getSigVerifier() view returns(address) func (_ISettlement *ISettlementCaller) GetSigVerifier(opts *bind.CallOpts) (common.Address, error) ⋮---- // GetSigVerifierAt is a free data retrieval call binding the contract method 0xa54ce263. ⋮---- // Solidity: function getSigVerifierAt(uint48 epoch, bytes hint) view returns(address) func (_ISettlement *ISettlementCaller) GetSigVerifierAt(opts *bind.CallOpts, epoch *big.Int, hint []byte) (common.Address, error) ⋮---- // GetTotalVotingPowerFromValSetHeader is a free data retrieval call binding the contract method 0xc38de37f. ⋮---- // Solidity: function getTotalVotingPowerFromValSetHeader() view returns(uint256) func (_ISettlement *ISettlementCaller) GetTotalVotingPowerFromValSetHeader(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetTotalVotingPowerFromValSetHeaderAt is a free data retrieval call binding the contract method 0xf7e5b491. ⋮---- // Solidity: function getTotalVotingPowerFromValSetHeaderAt(uint48 epoch) view returns(uint256) func (_ISettlement *ISettlementCaller) GetTotalVotingPowerFromValSetHeaderAt(opts *bind.CallOpts, epoch *big.Int) (*big.Int, error) ⋮---- // GetValSetHeader is a free data retrieval call binding the contract method 0xadc91fc8. ⋮---- // Solidity: function getValSetHeader() view returns((uint8,uint8,uint48,uint48,uint256,uint256,bytes32) header) func (_ISettlement *ISettlementCaller) GetValSetHeader(opts *bind.CallOpts) (ISettlementValSetHeader, error) ⋮---- // GetValSetHeaderAt is a free data retrieval call binding the contract method 0x4addaee7. ⋮---- // Solidity: function getValSetHeaderAt(uint48 epoch) view returns((uint8,uint8,uint48,uint48,uint256,uint256,bytes32)) func (_ISettlement *ISettlementCaller) GetValSetHeaderAt(opts *bind.CallOpts, epoch *big.Int) (ISettlementValSetHeader, error) ⋮---- // GetValSetHeaderHash is a free data retrieval call binding the contract method 0x32624bf3. ⋮---- // Solidity: function getValSetHeaderHash() view returns(bytes32) func (_ISettlement *ISettlementCaller) GetValSetHeaderHash(opts *bind.CallOpts) ([32]byte, error) ⋮---- // GetValSetHeaderHashAt is a free data retrieval call binding the contract method 0xf35d12a3. ⋮---- // Solidity: function getValSetHeaderHashAt(uint48 epoch) view returns(bytes32) func (_ISettlement *ISettlementCaller) GetValSetHeaderHashAt(opts *bind.CallOpts, epoch *big.Int) ([32]byte, error) ⋮---- // GetValidatorsSszMRootFromValSetHeader is a free data retrieval call binding the contract method 0x0167166e. ⋮---- // Solidity: function getValidatorsSszMRootFromValSetHeader() view returns(bytes32) func (_ISettlement *ISettlementCaller) GetValidatorsSszMRootFromValSetHeader(opts *bind.CallOpts) ([32]byte, error) ⋮---- // GetValidatorsSszMRootFromValSetHeaderAt is a free data retrieval call binding the contract method 0x230ae408. ⋮---- // Solidity: function getValidatorsSszMRootFromValSetHeaderAt(uint48 epoch) view returns(bytes32) func (_ISettlement *ISettlementCaller) GetValidatorsSszMRootFromValSetHeaderAt(opts *bind.CallOpts, epoch *big.Int) ([32]byte, error) ⋮---- // GetVersionFromValSetHeader is a free data retrieval call binding the contract method 0xd2df9fb6. ⋮---- // Solidity: function getVersionFromValSetHeader() view returns(uint8) func (_ISettlement *ISettlementCaller) GetVersionFromValSetHeader(opts *bind.CallOpts) (uint8, error) ⋮---- // GetVersionFromValSetHeaderAt is a free data retrieval call binding the contract method 0x548202ad. ⋮---- // Solidity: function getVersionFromValSetHeaderAt(uint48 epoch) view returns(uint8) func (_ISettlement *ISettlementCaller) GetVersionFromValSetHeaderAt(opts *bind.CallOpts, epoch *big.Int) (uint8, error) ⋮---- // HashTypedDataV4 is a free data retrieval call binding the contract method 0x4980f288. ⋮---- // Solidity: function hashTypedDataV4(bytes32 structHash) view returns(bytes32) func (_ISettlement *ISettlementCaller) HashTypedDataV4(opts *bind.CallOpts, structHash [32]byte) ([32]byte, error) ⋮---- // HashTypedDataV4CrossChain is a free data retrieval call binding the contract method 0x518dcf3b. ⋮---- // Solidity: function hashTypedDataV4CrossChain(bytes32 structHash) view returns(bytes32) func (_ISettlement *ISettlementCaller) HashTypedDataV4CrossChain(opts *bind.CallOpts, structHash [32]byte) ([32]byte, error) ⋮---- // IsValSetHeaderCommittedAt is a free data retrieval call binding the contract method 0x5fa4bbd2. ⋮---- // Solidity: function isValSetHeaderCommittedAt(uint48 epoch) view returns(bool) func (_ISettlement *ISettlementCaller) IsValSetHeaderCommittedAt(opts *bind.CallOpts, epoch *big.Int) (bool, error) ⋮---- // VerifyQuorumSig is a free data retrieval call binding the contract method 0x1dc1898b. ⋮---- // Solidity: function verifyQuorumSig(bytes message, uint8 keyTag, uint256 quorumThreshold, bytes proof) view returns(bool) func (_ISettlement *ISettlementCaller) VerifyQuorumSig(opts *bind.CallOpts, message []byte, keyTag uint8, quorumThreshold *big.Int, proof []byte) (bool, error) ⋮---- // VerifyQuorumSigAt is a free data retrieval call binding the contract method 0xacaa2269. ⋮---- // Solidity: function verifyQuorumSigAt(bytes message, uint8 keyTag, uint256 quorumThreshold, bytes proof, uint48 epoch, bytes hint) view returns(bool) func (_ISettlement *ISettlementCaller) VerifyQuorumSigAt(opts *bind.CallOpts, message []byte, keyTag uint8, quorumThreshold *big.Int, proof []byte, epoch *big.Int, hint []byte) (bool, error) ⋮---- // CommitValSetHeader is a paid mutator transaction binding the contract method 0x6f5f058e. ⋮---- // Solidity: function commitValSetHeader((uint8,uint8,uint48,uint48,uint256,uint256,bytes32) header, (bytes32,bytes32)[] extraData, bytes proof) returns() func (_ISettlement *ISettlementTransactor) CommitValSetHeader(opts *bind.TransactOpts, header ISettlementValSetHeader, extraData []ISettlementExtraData, proof []byte) (*types.Transaction, error) ⋮---- // SetGenesis is a paid mutator transaction binding the contract method 0xec3be7e4. ⋮---- // Solidity: function setGenesis((uint8,uint8,uint48,uint48,uint256,uint256,bytes32) valSetHeader, (bytes32,bytes32)[] extraData) returns() func (_ISettlement *ISettlementTransactor) SetGenesis(opts *bind.TransactOpts, valSetHeader ISettlementValSetHeader, extraData []ISettlementExtraData) (*types.Transaction, error) ⋮---- // SetSigVerifier is a paid mutator transaction binding the contract method 0xbd7e9980. ⋮---- // Solidity: function setSigVerifier(address sigVerifier) returns() func (_ISettlement *ISettlementTransactor) SetSigVerifier(opts *bind.TransactOpts, sigVerifier common.Address) (*types.Transaction, error) ⋮---- // StaticDelegateCall is a paid mutator transaction binding the contract method 0x9f86fd85. ⋮---- // Solidity: function staticDelegateCall(address target, bytes data) returns() func (_ISettlement *ISettlementTransactor) StaticDelegateCall(opts *bind.TransactOpts, target common.Address, data []byte) (*types.Transaction, error) ⋮---- // ISettlementCommitValSetHeaderIterator is returned from FilterCommitValSetHeader and is used to iterate over the raw logs and unpacked data for CommitValSetHeader events raised by the ISettlement contract. type ISettlementCommitValSetHeaderIterator struct { Event *ISettlementCommitValSetHeader // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementCommitValSetHeader // Event containing the contract specifics and raw log ⋮---- contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data ⋮---- logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration ⋮---- // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. func (it *ISettlementCommitValSetHeaderIterator) Next() bool ⋮---- // If the iterator failed, stop iterating ⋮---- // If the iterator completed, deliver directly whatever's available ⋮---- // Iterator still in progress, wait for either a data or an error event ⋮---- // Error returns any retrieval or parsing error occurred during filtering. func (it *ISettlementCommitValSetHeaderIterator) Error() error ⋮---- // Close terminates the iteration process, releasing any pending underlying // resources. func (it *ISettlementCommitValSetHeaderIterator) Close() error ⋮---- // ISettlementCommitValSetHeader represents a CommitValSetHeader event raised by the ISettlement contract. type ISettlementCommitValSetHeader struct { ValSetHeader ISettlementValSetHeader ExtraData []ISettlementExtraData Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterCommitValSetHeader is a free log retrieval operation binding the contract event 0x9ed1f51eddfff95a70fd993c30da7d26fc67bda21c9145aafc7d0a510a405558. ⋮---- // Solidity: event CommitValSetHeader((uint8,uint8,uint48,uint48,uint256,uint256,bytes32) valSetHeader, (bytes32,bytes32)[] extraData) func (_ISettlement *ISettlementFilterer) FilterCommitValSetHeader(opts *bind.FilterOpts) (*ISettlementCommitValSetHeaderIterator, error) ⋮---- // WatchCommitValSetHeader is a free log subscription operation binding the contract event 0x9ed1f51eddfff95a70fd993c30da7d26fc67bda21c9145aafc7d0a510a405558. ⋮---- func (_ISettlement *ISettlementFilterer) WatchCommitValSetHeader(opts *bind.WatchOpts, sink chan<- *ISettlementCommitValSetHeader) (event.Subscription, error) ⋮---- // New log arrived, parse the event and forward to the user ⋮---- // ParseCommitValSetHeader is a log parse operation binding the contract event 0x9ed1f51eddfff95a70fd993c30da7d26fc67bda21c9145aafc7d0a510a405558. ⋮---- func (_ISettlement *ISettlementFilterer) ParseCommitValSetHeader(log types.Log) (*ISettlementCommitValSetHeader, error) ⋮---- // ISettlementEIP712DomainChangedIterator is returned from FilterEIP712DomainChanged and is used to iterate over the raw logs and unpacked data for EIP712DomainChanged events raised by the ISettlement contract. type ISettlementEIP712DomainChangedIterator struct { Event *ISettlementEIP712DomainChanged // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementEIP712DomainChanged // Event containing the contract specifics and raw log ⋮---- // ISettlementEIP712DomainChanged represents a EIP712DomainChanged event raised by the ISettlement contract. type ISettlementEIP712DomainChanged struct { Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterEIP712DomainChanged is a free log retrieval operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. ⋮---- // Solidity: event EIP712DomainChanged() func (_ISettlement *ISettlementFilterer) FilterEIP712DomainChanged(opts *bind.FilterOpts) (*ISettlementEIP712DomainChangedIterator, error) ⋮---- // WatchEIP712DomainChanged is a free log subscription operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. ⋮---- func (_ISettlement *ISettlementFilterer) WatchEIP712DomainChanged(opts *bind.WatchOpts, sink chan<- *ISettlementEIP712DomainChanged) (event.Subscription, error) ⋮---- // ParseEIP712DomainChanged is a log parse operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. ⋮---- func (_ISettlement *ISettlementFilterer) ParseEIP712DomainChanged(log types.Log) (*ISettlementEIP712DomainChanged, error) ⋮---- // ISettlementInitEIP712Iterator is returned from FilterInitEIP712 and is used to iterate over the raw logs and unpacked data for InitEIP712 events raised by the ISettlement contract. type ISettlementInitEIP712Iterator struct { Event *ISettlementInitEIP712 // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementInitEIP712 // Event containing the contract specifics and raw log ⋮---- // ISettlementInitEIP712 represents a InitEIP712 event raised by the ISettlement contract. type ISettlementInitEIP712 struct { Name string Version string Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterInitEIP712 is a free log retrieval operation binding the contract event 0x98790bb3996c909e6f4279ffabdfe70fa6c0d49b8fa04656d6161decfc442e0a. ⋮---- // Solidity: event InitEIP712(string name, string version) func (_ISettlement *ISettlementFilterer) FilterInitEIP712(opts *bind.FilterOpts) (*ISettlementInitEIP712Iterator, error) ⋮---- // WatchInitEIP712 is a free log subscription operation binding the contract event 0x98790bb3996c909e6f4279ffabdfe70fa6c0d49b8fa04656d6161decfc442e0a. ⋮---- func (_ISettlement *ISettlementFilterer) WatchInitEIP712(opts *bind.WatchOpts, sink chan<- *ISettlementInitEIP712) (event.Subscription, error) ⋮---- // ParseInitEIP712 is a log parse operation binding the contract event 0x98790bb3996c909e6f4279ffabdfe70fa6c0d49b8fa04656d6161decfc442e0a. ⋮---- func (_ISettlement *ISettlementFilterer) ParseInitEIP712(log types.Log) (*ISettlementInitEIP712, error) ⋮---- // ISettlementInitSigVerifierIterator is returned from FilterInitSigVerifier and is used to iterate over the raw logs and unpacked data for InitSigVerifier events raised by the ISettlement contract. type ISettlementInitSigVerifierIterator struct { Event *ISettlementInitSigVerifier // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementInitSigVerifier // Event containing the contract specifics and raw log ⋮---- // ISettlementInitSigVerifier represents a InitSigVerifier event raised by the ISettlement contract. type ISettlementInitSigVerifier struct { SigVerifier common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterInitSigVerifier is a free log retrieval operation binding the contract event 0x8c698070f0c9ef92ff032a24e5c83ef7783fd360fde9c6af8ed5fca9fa5abbb7. ⋮---- // Solidity: event InitSigVerifier(address sigVerifier) func (_ISettlement *ISettlementFilterer) FilterInitSigVerifier(opts *bind.FilterOpts) (*ISettlementInitSigVerifierIterator, error) ⋮---- // WatchInitSigVerifier is a free log subscription operation binding the contract event 0x8c698070f0c9ef92ff032a24e5c83ef7783fd360fde9c6af8ed5fca9fa5abbb7. ⋮---- func (_ISettlement *ISettlementFilterer) WatchInitSigVerifier(opts *bind.WatchOpts, sink chan<- *ISettlementInitSigVerifier) (event.Subscription, error) ⋮---- // ParseInitSigVerifier is a log parse operation binding the contract event 0x8c698070f0c9ef92ff032a24e5c83ef7783fd360fde9c6af8ed5fca9fa5abbb7. ⋮---- func (_ISettlement *ISettlementFilterer) ParseInitSigVerifier(log types.Log) (*ISettlementInitSigVerifier, error) ⋮---- // ISettlementInitSubnetworkIterator is returned from FilterInitSubnetwork and is used to iterate over the raw logs and unpacked data for InitSubnetwork events raised by the ISettlement contract. type ISettlementInitSubnetworkIterator struct { Event *ISettlementInitSubnetwork // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementInitSubnetwork // Event containing the contract specifics and raw log ⋮---- // ISettlementInitSubnetwork represents a InitSubnetwork event raised by the ISettlement contract. type ISettlementInitSubnetwork struct { Network common.Address SubnetworkId *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterInitSubnetwork is a free log retrieval operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- // Solidity: event InitSubnetwork(address network, uint96 subnetworkId) func (_ISettlement *ISettlementFilterer) FilterInitSubnetwork(opts *bind.FilterOpts) (*ISettlementInitSubnetworkIterator, error) ⋮---- // WatchInitSubnetwork is a free log subscription operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- func (_ISettlement *ISettlementFilterer) WatchInitSubnetwork(opts *bind.WatchOpts, sink chan<- *ISettlementInitSubnetwork) (event.Subscription, error) ⋮---- // ParseInitSubnetwork is a log parse operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- func (_ISettlement *ISettlementFilterer) ParseInitSubnetwork(log types.Log) (*ISettlementInitSubnetwork, error) ⋮---- // ISettlementInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the ISettlement contract. type ISettlementInitializedIterator struct { Event *ISettlementInitialized // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementInitialized // Event containing the contract specifics and raw log ⋮---- // ISettlementInitialized represents a Initialized event raised by the ISettlement contract. type ISettlementInitialized struct { Version uint64 Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- // Solidity: event Initialized(uint64 version) func (_ISettlement *ISettlementFilterer) FilterInitialized(opts *bind.FilterOpts) (*ISettlementInitializedIterator, error) ⋮---- // WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- func (_ISettlement *ISettlementFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *ISettlementInitialized) (event.Subscription, error) ⋮---- // ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- func (_ISettlement *ISettlementFilterer) ParseInitialized(log types.Log) (*ISettlementInitialized, error) ⋮---- // ISettlementSetGenesisIterator is returned from FilterSetGenesis and is used to iterate over the raw logs and unpacked data for SetGenesis events raised by the ISettlement contract. type ISettlementSetGenesisIterator struct { Event *ISettlementSetGenesis // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementSetGenesis // Event containing the contract specifics and raw log ⋮---- // ISettlementSetGenesis represents a SetGenesis event raised by the ISettlement contract. type ISettlementSetGenesis struct { ValSetHeader ISettlementValSetHeader ExtraData []ISettlementExtraData Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterSetGenesis is a free log retrieval operation binding the contract event 0xd4b7365d7a7dd369f40b249f48684bd7e51524b3ab56a9eb188ac339d574bbc0. ⋮---- // Solidity: event SetGenesis((uint8,uint8,uint48,uint48,uint256,uint256,bytes32) valSetHeader, (bytes32,bytes32)[] extraData) func (_ISettlement *ISettlementFilterer) FilterSetGenesis(opts *bind.FilterOpts) (*ISettlementSetGenesisIterator, error) ⋮---- // WatchSetGenesis is a free log subscription operation binding the contract event 0xd4b7365d7a7dd369f40b249f48684bd7e51524b3ab56a9eb188ac339d574bbc0. ⋮---- func (_ISettlement *ISettlementFilterer) WatchSetGenesis(opts *bind.WatchOpts, sink chan<- *ISettlementSetGenesis) (event.Subscription, error) ⋮---- // ParseSetGenesis is a log parse operation binding the contract event 0xd4b7365d7a7dd369f40b249f48684bd7e51524b3ab56a9eb188ac339d574bbc0. ⋮---- func (_ISettlement *ISettlementFilterer) ParseSetGenesis(log types.Log) (*ISettlementSetGenesis, error) ⋮---- // ISettlementSetSigVerifierIterator is returned from FilterSetSigVerifier and is used to iterate over the raw logs and unpacked data for SetSigVerifier events raised by the ISettlement contract. type ISettlementSetSigVerifierIterator struct { Event *ISettlementSetSigVerifier // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *ISettlementSetSigVerifier // Event containing the contract specifics and raw log ⋮---- // ISettlementSetSigVerifier represents a SetSigVerifier event raised by the ISettlement contract. type ISettlementSetSigVerifier struct { SigVerifier common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterSetSigVerifier is a free log retrieval operation binding the contract event 0x3cb2fcfd41e182e933eb967bdeaac4f8ff69c80b6fd24fea9561dfbdec127942. ⋮---- // Solidity: event SetSigVerifier(address sigVerifier) func (_ISettlement *ISettlementFilterer) FilterSetSigVerifier(opts *bind.FilterOpts) (*ISettlementSetSigVerifierIterator, error) ⋮---- // WatchSetSigVerifier is a free log subscription operation binding the contract event 0x3cb2fcfd41e182e933eb967bdeaac4f8ff69c80b6fd24fea9561dfbdec127942. ⋮---- func (_ISettlement *ISettlementFilterer) WatchSetSigVerifier(opts *bind.WatchOpts, sink chan<- *ISettlementSetSigVerifier) (event.Subscription, error) ⋮---- // ParseSetSigVerifier is a log parse operation binding the contract event 0x3cb2fcfd41e182e933eb967bdeaac4f8ff69c80b6fd24fea9561dfbdec127942. ⋮---- func (_ISettlement *ISettlementFilterer) ParseSetSigVerifier(log types.Log) (*ISettlementSetSigVerifier, error) ```` ## File: symbiotic/client/evm/gen/valsetDriver.go ````go // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. ⋮---- package gen ⋮---- import ( "errors" "math/big" "strings" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ) ⋮---- "errors" "math/big" "strings" ⋮---- ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ⋮---- // Reference imports to suppress errors if they are not otherwise used. var ( _ = errors.New _ = big.NewInt _ = strings.NewReader _ = ethereum.NotFound _ = bind.Bind _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription _ = abi.ConvertType ) ⋮---- // IValSetDriverConfig is an auto generated low-level Go binding around an user-defined struct. type IValSetDriverConfig struct { NumAggregators *big.Int NumCommitters *big.Int VotingPowerProviders []IValSetDriverCrossChainAddress KeysProvider IValSetDriverCrossChainAddress Settlements []IValSetDriverCrossChainAddress MaxVotingPower *big.Int MinInclusionVotingPower *big.Int MaxValidatorsCount *big.Int RequiredKeyTags []uint8 QuorumThresholds []IValSetDriverQuorumThreshold RequiredHeaderKeyTag uint8 VerificationType uint32 } ⋮---- // IValSetDriverCrossChainAddress is an auto generated low-level Go binding around an user-defined struct. type IValSetDriverCrossChainAddress struct { ChainId uint64 Addr common.Address } ⋮---- // IValSetDriverQuorumThreshold is an auto generated low-level Go binding around an user-defined struct. type IValSetDriverQuorumThreshold struct { KeyTag uint8 QuorumThreshold *big.Int } ⋮---- // IValSetDriverMetaData contains all meta data concerning the IValSetDriver contract. var IValSetDriverMetaData = &bind.MetaData{ ABI: "[{\"type\":\"function\",\"name\":\"MAX_QUORUM_THRESHOLD\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint248\",\"internalType\":\"uint248\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"NETWORK\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SUBNETWORK\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SUBNETWORK_IDENTIFIER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint96\",\"internalType\":\"uint96\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addQuorumThreshold\",\"inputs\":[{\"name\":\"quorumThreshold\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.QuorumThreshold\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addSettlement\",\"inputs\":[{\"name\":\"settlement\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addVotingPowerProvider\",\"inputs\":[{\"name\":\"votingPowerProvider\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.Config\",\"components\":[{\"name\":\"numAggregators\",\"type\":\"uint208\",\"internalType\":\"uint208\"},{\"name\":\"numCommitters\",\"type\":\"uint208\",\"internalType\":\"uint208\"},{\"name\":\"votingPowerProviders\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"keysProvider\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"settlements\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"maxVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minInclusionVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxValidatorsCount\",\"type\":\"uint208\",\"internalType\":\"uint208\"},{\"name\":\"requiredKeyTags\",\"type\":\"uint8[]\",\"internalType\":\"uint8[]\"},{\"name\":\"quorumThresholds\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.QuorumThreshold[]\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]},{\"name\":\"requiredHeaderKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"verificationType\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getConfigAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.Config\",\"components\":[{\"name\":\"numAggregators\",\"type\":\"uint208\",\"internalType\":\"uint208\"},{\"name\":\"numCommitters\",\"type\":\"uint208\",\"internalType\":\"uint208\"},{\"name\":\"votingPowerProviders\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"keysProvider\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"settlements\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"maxVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minInclusionVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxValidatorsCount\",\"type\":\"uint208\",\"internalType\":\"uint208\"},{\"name\":\"requiredKeyTags\",\"type\":\"uint8[]\",\"internalType\":\"uint8[]\"},{\"name\":\"quorumThresholds\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.QuorumThreshold[]\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]},{\"name\":\"requiredHeaderKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"verificationType\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentEpoch\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentEpochDuration\",\"inputs\":[],\"outputs\":[{\"name\":\"epochDuration\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentEpochStart\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getEpochDuration\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"epochDuration\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getEpochIndex\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getEpochStart\",\"inputs\":[{\"name\":\"epoch\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeysProvider\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeysProviderAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMaxValidatorsCount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMaxValidatorsCountAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMaxVotingPower\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMaxVotingPowerAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMinInclusionVotingPower\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMinInclusionVotingPowerAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNextEpoch\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNextEpochDuration\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNextEpochStart\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumAggregators\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumAggregatorsAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumCommitters\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumCommittersAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getQuorumThresholds\",\"inputs\":[],\"outputs\":[{\"name\":\"quorumThresholds\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.QuorumThreshold[]\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getQuorumThresholdsAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"quorumThresholds\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.QuorumThreshold[]\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredHeaderKeyTag\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredHeaderKeyTagAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredKeyTags\",\"inputs\":[],\"outputs\":[{\"name\":\"requiredKeyTags\",\"type\":\"uint8[]\",\"internalType\":\"uint8[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredKeyTagsAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"requiredKeyTags\",\"type\":\"uint8[]\",\"internalType\":\"uint8[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSettlements\",\"inputs\":[],\"outputs\":[{\"name\":\"settlements\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSettlementsAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"settlements\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVerificationType\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVerificationTypeAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVotingPowerProviders\",\"inputs\":[],\"outputs\":[{\"name\":\"votingPowerProviders\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVotingPowerProvidersAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"votingPowerProviders\",\"type\":\"tuple[]\",\"internalType\":\"structIValSetDriver.CrossChainAddress[]\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isQuorumThresholdRegistered\",\"inputs\":[{\"name\":\"quorumThreshold\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.QuorumThreshold\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isQuorumThresholdRegisteredAt\",\"inputs\":[{\"name\":\"quorumThreshold\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.QuorumThreshold\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSettlementRegistered\",\"inputs\":[{\"name\":\"settlement\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSettlementRegisteredAt\",\"inputs\":[{\"name\":\"settlement\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isVotingPowerProviderRegistered\",\"inputs\":[{\"name\":\"votingPowerProvider\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isVotingPowerProviderRegisteredAt\",\"inputs\":[{\"name\":\"votingPowerProvider\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"multicall\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[{\"name\":\"results\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeQuorumThreshold\",\"inputs\":[{\"name\":\"quorumThreshold\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.QuorumThreshold\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeSettlement\",\"inputs\":[{\"name\":\"settlement\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeVotingPowerProvider\",\"inputs\":[{\"name\":\"votingPowerProvider\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setEpochDuration\",\"inputs\":[{\"name\":\"epochDuration\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setKeysProvider\",\"inputs\":[{\"name\":\"keysProvider\",\"type\":\"tuple\",\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxValidatorsCount\",\"inputs\":[{\"name\":\"maxValidatorsCount\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxVotingPower\",\"inputs\":[{\"name\":\"maxVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMinInclusionVotingPower\",\"inputs\":[{\"name\":\"minInclusionVotingPower\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setNumAggregators\",\"inputs\":[{\"name\":\"numAggregators\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setNumCommitters\",\"inputs\":[{\"name\":\"numCommitters\",\"type\":\"uint208\",\"internalType\":\"uint208\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRequiredHeaderKeyTag\",\"inputs\":[{\"name\":\"requiredHeaderKeyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRequiredKeyTags\",\"inputs\":[{\"name\":\"requiredKeyTags\",\"type\":\"uint8[]\",\"internalType\":\"uint8[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setVerificationType\",\"inputs\":[{\"name\":\"verificationType\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"staticDelegateCall\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AddQuorumThreshold\",\"inputs\":[{\"name\":\"quorumThreshold\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIValSetDriver.QuorumThreshold\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AddSettlement\",\"inputs\":[{\"name\":\"settlement\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AddVotingPowerProvider\",\"inputs\":[{\"name\":\"votingPowerProvider\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitEpochDuration\",\"inputs\":[{\"name\":\"epochDuration\",\"type\":\"uint48\",\"indexed\":false,\"internalType\":\"uint48\"},{\"name\":\"epochDurationTimestamp\",\"type\":\"uint48\",\"indexed\":false,\"internalType\":\"uint48\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitSubnetwork\",\"inputs\":[{\"name\":\"network\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"subnetworkId\",\"type\":\"uint96\",\"indexed\":false,\"internalType\":\"uint96\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemoveQuorumThreshold\",\"inputs\":[{\"name\":\"quorumThreshold\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIValSetDriver.QuorumThreshold\",\"components\":[{\"name\":\"keyTag\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"quorumThreshold\",\"type\":\"uint248\",\"internalType\":\"uint248\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemoveSettlement\",\"inputs\":[{\"name\":\"settlement\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemoveVotingPowerProvider\",\"inputs\":[{\"name\":\"votingPowerProvider\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetEpochDuration\",\"inputs\":[{\"name\":\"epochDuration\",\"type\":\"uint48\",\"indexed\":false,\"internalType\":\"uint48\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetKeysProvider\",\"inputs\":[{\"name\":\"keysProvider\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIValSetDriver.CrossChainAddress\",\"components\":[{\"name\":\"chainId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetMaxValidatorsCount\",\"inputs\":[{\"name\":\"maxValidatorsCount\",\"type\":\"uint208\",\"indexed\":false,\"internalType\":\"uint208\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetMaxVotingPower\",\"inputs\":[{\"name\":\"maxVotingPower\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetMinInclusionVotingPower\",\"inputs\":[{\"name\":\"minInclusionVotingPower\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetNumAggregators\",\"inputs\":[{\"name\":\"numAggregators\",\"type\":\"uint208\",\"indexed\":false,\"internalType\":\"uint208\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetNumCommitters\",\"inputs\":[{\"name\":\"numCommitters\",\"type\":\"uint208\",\"indexed\":false,\"internalType\":\"uint208\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetRequiredHeaderKeyTag\",\"inputs\":[{\"name\":\"requiredHeaderKeyTag\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetRequiredKeyTags\",\"inputs\":[{\"name\":\"requiredKeyTags\",\"type\":\"uint8[]\",\"indexed\":false,\"internalType\":\"uint8[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetVerificationType\",\"inputs\":[{\"name\":\"verificationType\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CheckpointUnorderedInsertion\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DuplicateKeyTag\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EpochManager_InvalidEpochDuration\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EpochManager_InvalidEpochDurationTimestamp\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EpochManager_TooOldTimestamp\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidKeyTag\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NetworkManager_InvalidNetwork\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_ChainAlreadyAdded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_InvalidCrossChainAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_InvalidMaxValidatorsCount\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_InvalidQuorumThreshold\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_KeyTagAlreadyAdded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_NotAdded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_ZeroNumAggregators\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ValSetDriver_ZeroNumCommitters\",\"inputs\":[]}]", } ⋮---- // IValSetDriverABI is the input ABI used to generate the binding from. // Deprecated: Use IValSetDriverMetaData.ABI instead. var IValSetDriverABI = IValSetDriverMetaData.ABI ⋮---- // IValSetDriver is an auto generated Go binding around an Ethereum contract. type IValSetDriver struct { IValSetDriverCaller // Read-only binding to the contract IValSetDriverTransactor // Write-only binding to the contract IValSetDriverFilterer // Log filterer for contract events } ⋮---- IValSetDriverCaller // Read-only binding to the contract IValSetDriverTransactor // Write-only binding to the contract IValSetDriverFilterer // Log filterer for contract events ⋮---- // IValSetDriverCaller is an auto generated read-only Go binding around an Ethereum contract. type IValSetDriverCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- contract *bind.BoundContract // Generic contract wrapper for the low level calls ⋮---- // IValSetDriverTransactor is an auto generated write-only Go binding around an Ethereum contract. type IValSetDriverTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // IValSetDriverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. type IValSetDriverFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // IValSetDriverSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. type IValSetDriverSession struct { Contract *IValSetDriver // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *IValSetDriver // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // IValSetDriverCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. type IValSetDriverCallerSession struct { Contract *IValSetDriverCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } ⋮---- Contract *IValSetDriverCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session ⋮---- // IValSetDriverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. type IValSetDriverTransactorSession struct { Contract *IValSetDriverTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *IValSetDriverTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // IValSetDriverRaw is an auto generated low-level Go binding around an Ethereum contract. type IValSetDriverRaw struct { Contract *IValSetDriver // Generic contract binding to access the raw methods on } ⋮---- Contract *IValSetDriver // Generic contract binding to access the raw methods on ⋮---- // IValSetDriverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. type IValSetDriverCallerRaw struct { Contract *IValSetDriverCaller // Generic read-only contract binding to access the raw methods on } ⋮---- Contract *IValSetDriverCaller // Generic read-only contract binding to access the raw methods on ⋮---- // IValSetDriverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. type IValSetDriverTransactorRaw struct { Contract *IValSetDriverTransactor // Generic write-only contract binding to access the raw methods on } ⋮---- Contract *IValSetDriverTransactor // Generic write-only contract binding to access the raw methods on ⋮---- // NewIValSetDriver creates a new instance of IValSetDriver, bound to a specific deployed contract. func NewIValSetDriver(address common.Address, backend bind.ContractBackend) (*IValSetDriver, error) ⋮---- // NewIValSetDriverCaller creates a new read-only instance of IValSetDriver, bound to a specific deployed contract. func NewIValSetDriverCaller(address common.Address, caller bind.ContractCaller) (*IValSetDriverCaller, error) ⋮---- // NewIValSetDriverTransactor creates a new write-only instance of IValSetDriver, bound to a specific deployed contract. func NewIValSetDriverTransactor(address common.Address, transactor bind.ContractTransactor) (*IValSetDriverTransactor, error) ⋮---- // NewIValSetDriverFilterer creates a new log filterer instance of IValSetDriver, bound to a specific deployed contract. func NewIValSetDriverFilterer(address common.Address, filterer bind.ContractFilterer) (*IValSetDriverFilterer, error) ⋮---- // bindIValSetDriver binds a generic wrapper to an already deployed contract. func bindIValSetDriver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) ⋮---- // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. func (_IValSetDriver *IValSetDriverRaw) Call(opts *bind.CallOpts, result *[]interface ⋮---- // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. func (_IValSetDriver *IValSetDriverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // Transact invokes the (paid) contract method with params as input values. func (_IValSetDriver *IValSetDriverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface ⋮---- // MAXQUORUMTHRESHOLD is a free data retrieval call binding the contract method 0x127ec283. // // Solidity: function MAX_QUORUM_THRESHOLD() view returns(uint248) func (_IValSetDriver *IValSetDriverCaller) MAXQUORUMTHRESHOLD(opts *bind.CallOpts) (*big.Int, error) ⋮---- var out []interface{} ⋮---- // NETWORK is a free data retrieval call binding the contract method 0x8759e6d1. ⋮---- // Solidity: function NETWORK() view returns(address) func (_IValSetDriver *IValSetDriverCaller) NETWORK(opts *bind.CallOpts) (common.Address, error) ⋮---- // SUBNETWORK is a free data retrieval call binding the contract method 0x773e6b54. ⋮---- // Solidity: function SUBNETWORK() view returns(bytes32) func (_IValSetDriver *IValSetDriverCaller) SUBNETWORK(opts *bind.CallOpts) ([32]byte, error) ⋮---- // SUBNETWORKIDENTIFIER is a free data retrieval call binding the contract method 0xabacb807. ⋮---- // Solidity: function SUBNETWORK_IDENTIFIER() view returns(uint96) func (_IValSetDriver *IValSetDriverCaller) SUBNETWORKIDENTIFIER(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetConfig is a free data retrieval call binding the contract method 0xc3f909d4. ⋮---- // Solidity: function getConfig() view returns((uint208,uint208,(uint64,address)[],(uint64,address),(uint64,address)[],uint256,uint256,uint208,uint8[],(uint8,uint248)[],uint8,uint32)) func (_IValSetDriver *IValSetDriverCaller) GetConfig(opts *bind.CallOpts) (IValSetDriverConfig, error) ⋮---- // GetConfigAt is a free data retrieval call binding the contract method 0x13fb0877. ⋮---- // Solidity: function getConfigAt(uint48 timestamp) view returns((uint208,uint208,(uint64,address)[],(uint64,address),(uint64,address)[],uint256,uint256,uint208,uint8[],(uint8,uint248)[],uint8,uint32)) func (_IValSetDriver *IValSetDriverCaller) GetConfigAt(opts *bind.CallOpts, timestamp *big.Int) (IValSetDriverConfig, error) ⋮---- // GetCurrentEpoch is a free data retrieval call binding the contract method 0xb97dd9e2. ⋮---- // Solidity: function getCurrentEpoch() view returns(uint48) func (_IValSetDriver *IValSetDriverCaller) GetCurrentEpoch(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetCurrentEpochDuration is a free data retrieval call binding the contract method 0x558e2eb6. ⋮---- // Solidity: function getCurrentEpochDuration() view returns(uint48 epochDuration) func (_IValSetDriver *IValSetDriverCaller) GetCurrentEpochDuration(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetCurrentEpochStart is a free data retrieval call binding the contract method 0xa6e16c4d. ⋮---- // Solidity: function getCurrentEpochStart() view returns(uint48) func (_IValSetDriver *IValSetDriverCaller) GetCurrentEpochStart(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetEpochDuration is a free data retrieval call binding the contract method 0xf6fd6f14. ⋮---- // Solidity: function getEpochDuration(uint48 epoch) view returns(uint48 epochDuration) func (_IValSetDriver *IValSetDriverCaller) GetEpochDuration(opts *bind.CallOpts, epoch *big.Int) (*big.Int, error) ⋮---- // GetEpochIndex is a free data retrieval call binding the contract method 0xccafd209. ⋮---- // Solidity: function getEpochIndex(uint48 timestamp) view returns(uint48) func (_IValSetDriver *IValSetDriverCaller) GetEpochIndex(opts *bind.CallOpts, timestamp *big.Int) (*big.Int, error) ⋮---- // GetEpochStart is a free data retrieval call binding the contract method 0x246e158f. ⋮---- // Solidity: function getEpochStart(uint48 epoch) view returns(uint48) func (_IValSetDriver *IValSetDriverCaller) GetEpochStart(opts *bind.CallOpts, epoch *big.Int) (*big.Int, error) ⋮---- // GetKeysProvider is a free data retrieval call binding the contract method 0x297d29b8. ⋮---- // Solidity: function getKeysProvider() view returns((uint64,address)) func (_IValSetDriver *IValSetDriverCaller) GetKeysProvider(opts *bind.CallOpts) (IValSetDriverCrossChainAddress, error) ⋮---- // GetKeysProviderAt is a free data retrieval call binding the contract method 0x10a49295. ⋮---- // Solidity: function getKeysProviderAt(uint48 timestamp) view returns((uint64,address)) func (_IValSetDriver *IValSetDriverCaller) GetKeysProviderAt(opts *bind.CallOpts, timestamp *big.Int) (IValSetDriverCrossChainAddress, error) ⋮---- // GetMaxValidatorsCount is a free data retrieval call binding the contract method 0x06ce894d. ⋮---- // Solidity: function getMaxValidatorsCount() view returns(uint208) func (_IValSetDriver *IValSetDriverCaller) GetMaxValidatorsCount(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetMaxValidatorsCountAt is a free data retrieval call binding the contract method 0x4f938edc. ⋮---- // Solidity: function getMaxValidatorsCountAt(uint48 timestamp) view returns(uint208) func (_IValSetDriver *IValSetDriverCaller) GetMaxValidatorsCountAt(opts *bind.CallOpts, timestamp *big.Int) (*big.Int, error) ⋮---- // GetMaxVotingPower is a free data retrieval call binding the contract method 0x9f9c3080. ⋮---- // Solidity: function getMaxVotingPower() view returns(uint256) func (_IValSetDriver *IValSetDriverCaller) GetMaxVotingPower(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetMaxVotingPowerAt is a free data retrieval call binding the contract method 0x848b3040. ⋮---- // Solidity: function getMaxVotingPowerAt(uint48 timestamp) view returns(uint256) func (_IValSetDriver *IValSetDriverCaller) GetMaxVotingPowerAt(opts *bind.CallOpts, timestamp *big.Int) (*big.Int, error) ⋮---- // GetMinInclusionVotingPower is a free data retrieval call binding the contract method 0xb6a94695. ⋮---- // Solidity: function getMinInclusionVotingPower() view returns(uint256) func (_IValSetDriver *IValSetDriverCaller) GetMinInclusionVotingPower(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetMinInclusionVotingPowerAt is a free data retrieval call binding the contract method 0x456705a2. ⋮---- // Solidity: function getMinInclusionVotingPowerAt(uint48 timestamp) view returns(uint256) func (_IValSetDriver *IValSetDriverCaller) GetMinInclusionVotingPowerAt(opts *bind.CallOpts, timestamp *big.Int) (*big.Int, error) ⋮---- // GetNextEpoch is a free data retrieval call binding the contract method 0xefe97d05. ⋮---- // Solidity: function getNextEpoch() view returns(uint48) func (_IValSetDriver *IValSetDriverCaller) GetNextEpoch(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetNextEpochDuration is a free data retrieval call binding the contract method 0x038cf1c0. ⋮---- // Solidity: function getNextEpochDuration() view returns(uint48) func (_IValSetDriver *IValSetDriverCaller) GetNextEpochDuration(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetNextEpochStart is a free data retrieval call binding the contract method 0x65c5f94a. ⋮---- // Solidity: function getNextEpochStart() view returns(uint48) func (_IValSetDriver *IValSetDriverCaller) GetNextEpochStart(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetNumAggregators is a free data retrieval call binding the contract method 0x21fbfe0d. ⋮---- // Solidity: function getNumAggregators() view returns(uint208) func (_IValSetDriver *IValSetDriverCaller) GetNumAggregators(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetNumAggregatorsAt is a free data retrieval call binding the contract method 0x6bb7e08a. ⋮---- // Solidity: function getNumAggregatorsAt(uint48 timestamp) view returns(uint208) func (_IValSetDriver *IValSetDriverCaller) GetNumAggregatorsAt(opts *bind.CallOpts, timestamp *big.Int) (*big.Int, error) ⋮---- // GetNumCommitters is a free data retrieval call binding the contract method 0x7861db16. ⋮---- // Solidity: function getNumCommitters() view returns(uint208) func (_IValSetDriver *IValSetDriverCaller) GetNumCommitters(opts *bind.CallOpts) (*big.Int, error) ⋮---- // GetNumCommittersAt is a free data retrieval call binding the contract method 0xe0078c64. ⋮---- // Solidity: function getNumCommittersAt(uint48 timestamp) view returns(uint208) func (_IValSetDriver *IValSetDriverCaller) GetNumCommittersAt(opts *bind.CallOpts, timestamp *big.Int) (*big.Int, error) ⋮---- // GetQuorumThresholds is a free data retrieval call binding the contract method 0x5796148c. ⋮---- // Solidity: function getQuorumThresholds() view returns((uint8,uint248)[] quorumThresholds) func (_IValSetDriver *IValSetDriverCaller) GetQuorumThresholds(opts *bind.CallOpts) ([]IValSetDriverQuorumThreshold, error) ⋮---- // GetQuorumThresholdsAt is a free data retrieval call binding the contract method 0xf2f46b83. ⋮---- // Solidity: function getQuorumThresholdsAt(uint48 timestamp) view returns((uint8,uint248)[] quorumThresholds) func (_IValSetDriver *IValSetDriverCaller) GetQuorumThresholdsAt(opts *bind.CallOpts, timestamp *big.Int) ([]IValSetDriverQuorumThreshold, error) ⋮---- // GetRequiredHeaderKeyTag is a free data retrieval call binding the contract method 0x6582e9f7. ⋮---- // Solidity: function getRequiredHeaderKeyTag() view returns(uint8) func (_IValSetDriver *IValSetDriverCaller) GetRequiredHeaderKeyTag(opts *bind.CallOpts) (uint8, error) ⋮---- // GetRequiredHeaderKeyTagAt is a free data retrieval call binding the contract method 0xbc12e1fd. ⋮---- // Solidity: function getRequiredHeaderKeyTagAt(uint48 timestamp) view returns(uint8) func (_IValSetDriver *IValSetDriverCaller) GetRequiredHeaderKeyTagAt(opts *bind.CallOpts, timestamp *big.Int) (uint8, error) ⋮---- // GetRequiredKeyTags is a free data retrieval call binding the contract method 0xf9bfa78a. ⋮---- // Solidity: function getRequiredKeyTags() view returns(uint8[] requiredKeyTags) func (_IValSetDriver *IValSetDriverCaller) GetRequiredKeyTags(opts *bind.CallOpts) ([]uint8, error) ⋮---- // GetRequiredKeyTagsAt is a free data retrieval call binding the contract method 0x1161fc83. ⋮---- // Solidity: function getRequiredKeyTagsAt(uint48 timestamp) view returns(uint8[] requiredKeyTags) func (_IValSetDriver *IValSetDriverCaller) GetRequiredKeyTagsAt(opts *bind.CallOpts, timestamp *big.Int) ([]uint8, error) ⋮---- // GetSettlements is a free data retrieval call binding the contract method 0xa0c2bc25. ⋮---- // Solidity: function getSettlements() view returns((uint64,address)[] settlements) func (_IValSetDriver *IValSetDriverCaller) GetSettlements(opts *bind.CallOpts) ([]IValSetDriverCrossChainAddress, error) ⋮---- // GetSettlementsAt is a free data retrieval call binding the contract method 0x763d255a. ⋮---- // Solidity: function getSettlementsAt(uint48 timestamp) view returns((uint64,address)[] settlements) func (_IValSetDriver *IValSetDriverCaller) GetSettlementsAt(opts *bind.CallOpts, timestamp *big.Int) ([]IValSetDriverCrossChainAddress, error) ⋮---- // GetVerificationType is a free data retrieval call binding the contract method 0x24acc119. ⋮---- // Solidity: function getVerificationType() view returns(uint32) func (_IValSetDriver *IValSetDriverCaller) GetVerificationType(opts *bind.CallOpts) (uint32, error) ⋮---- // GetVerificationTypeAt is a free data retrieval call binding the contract method 0x3a0ad9ec. ⋮---- // Solidity: function getVerificationTypeAt(uint48 timestamp) view returns(uint32) func (_IValSetDriver *IValSetDriverCaller) GetVerificationTypeAt(opts *bind.CallOpts, timestamp *big.Int) (uint32, error) ⋮---- // GetVotingPowerProviders is a free data retrieval call binding the contract method 0x3e39b8db. ⋮---- // Solidity: function getVotingPowerProviders() view returns((uint64,address)[] votingPowerProviders) func (_IValSetDriver *IValSetDriverCaller) GetVotingPowerProviders(opts *bind.CallOpts) ([]IValSetDriverCrossChainAddress, error) ⋮---- // GetVotingPowerProvidersAt is a free data retrieval call binding the contract method 0x09bba5ca. ⋮---- // Solidity: function getVotingPowerProvidersAt(uint48 timestamp) view returns((uint64,address)[] votingPowerProviders) func (_IValSetDriver *IValSetDriverCaller) GetVotingPowerProvidersAt(opts *bind.CallOpts, timestamp *big.Int) ([]IValSetDriverCrossChainAddress, error) ⋮---- // IsQuorumThresholdRegistered is a free data retrieval call binding the contract method 0x79a4c359. ⋮---- // Solidity: function isQuorumThresholdRegistered((uint8,uint248) quorumThreshold) view returns(bool) func (_IValSetDriver *IValSetDriverCaller) IsQuorumThresholdRegistered(opts *bind.CallOpts, quorumThreshold IValSetDriverQuorumThreshold) (bool, error) ⋮---- // IsQuorumThresholdRegisteredAt is a free data retrieval call binding the contract method 0x80c2fc48. ⋮---- // Solidity: function isQuorumThresholdRegisteredAt((uint8,uint248) quorumThreshold, uint48 timestamp) view returns(bool) func (_IValSetDriver *IValSetDriverCaller) IsQuorumThresholdRegisteredAt(opts *bind.CallOpts, quorumThreshold IValSetDriverQuorumThreshold, timestamp *big.Int) (bool, error) ⋮---- // IsSettlementRegistered is a free data retrieval call binding the contract method 0x965c0768. ⋮---- // Solidity: function isSettlementRegistered((uint64,address) settlement) view returns(bool) func (_IValSetDriver *IValSetDriverCaller) IsSettlementRegistered(opts *bind.CallOpts, settlement IValSetDriverCrossChainAddress) (bool, error) ⋮---- // IsSettlementRegisteredAt is a free data retrieval call binding the contract method 0x01749b26. ⋮---- // Solidity: function isSettlementRegisteredAt((uint64,address) settlement, uint48 timestamp) view returns(bool) func (_IValSetDriver *IValSetDriverCaller) IsSettlementRegisteredAt(opts *bind.CallOpts, settlement IValSetDriverCrossChainAddress, timestamp *big.Int) (bool, error) ⋮---- // IsVotingPowerProviderRegistered is a free data retrieval call binding the contract method 0x1265b3be. ⋮---- // Solidity: function isVotingPowerProviderRegistered((uint64,address) votingPowerProvider) view returns(bool) func (_IValSetDriver *IValSetDriverCaller) IsVotingPowerProviderRegistered(opts *bind.CallOpts, votingPowerProvider IValSetDriverCrossChainAddress) (bool, error) ⋮---- // IsVotingPowerProviderRegisteredAt is a free data retrieval call binding the contract method 0xc16ccb73. ⋮---- // Solidity: function isVotingPowerProviderRegisteredAt((uint64,address) votingPowerProvider, uint48 timestamp) view returns(bool) func (_IValSetDriver *IValSetDriverCaller) IsVotingPowerProviderRegisteredAt(opts *bind.CallOpts, votingPowerProvider IValSetDriverCrossChainAddress, timestamp *big.Int) (bool, error) ⋮---- // AddQuorumThreshold is a paid mutator transaction binding the contract method 0x0fe5e0c2. ⋮---- // Solidity: function addQuorumThreshold((uint8,uint248) quorumThreshold) returns() func (_IValSetDriver *IValSetDriverTransactor) AddQuorumThreshold(opts *bind.TransactOpts, quorumThreshold IValSetDriverQuorumThreshold) (*types.Transaction, error) ⋮---- // AddSettlement is a paid mutator transaction binding the contract method 0x52ab8872. ⋮---- // Solidity: function addSettlement((uint64,address) settlement) returns() func (_IValSetDriver *IValSetDriverTransactor) AddSettlement(opts *bind.TransactOpts, settlement IValSetDriverCrossChainAddress) (*types.Transaction, error) ⋮---- // AddVotingPowerProvider is a paid mutator transaction binding the contract method 0x6940ed80. ⋮---- // Solidity: function addVotingPowerProvider((uint64,address) votingPowerProvider) returns() func (_IValSetDriver *IValSetDriverTransactor) AddVotingPowerProvider(opts *bind.TransactOpts, votingPowerProvider IValSetDriverCrossChainAddress) (*types.Transaction, error) ⋮---- // Multicall is a paid mutator transaction binding the contract method 0xac9650d8. ⋮---- // Solidity: function multicall(bytes[] data) returns(bytes[] results) func (_IValSetDriver *IValSetDriverTransactor) Multicall(opts *bind.TransactOpts, data [][]byte) (*types.Transaction, error) ⋮---- // RemoveQuorumThreshold is a paid mutator transaction binding the contract method 0xf388db18. ⋮---- // Solidity: function removeQuorumThreshold((uint8,uint248) quorumThreshold) returns() func (_IValSetDriver *IValSetDriverTransactor) RemoveQuorumThreshold(opts *bind.TransactOpts, quorumThreshold IValSetDriverQuorumThreshold) (*types.Transaction, error) ⋮---- // RemoveSettlement is a paid mutator transaction binding the contract method 0x502bb1ad. ⋮---- // Solidity: function removeSettlement((uint64,address) settlement) returns() func (_IValSetDriver *IValSetDriverTransactor) RemoveSettlement(opts *bind.TransactOpts, settlement IValSetDriverCrossChainAddress) (*types.Transaction, error) ⋮---- // RemoveVotingPowerProvider is a paid mutator transaction binding the contract method 0x325234d5. ⋮---- // Solidity: function removeVotingPowerProvider((uint64,address) votingPowerProvider) returns() func (_IValSetDriver *IValSetDriverTransactor) RemoveVotingPowerProvider(opts *bind.TransactOpts, votingPowerProvider IValSetDriverCrossChainAddress) (*types.Transaction, error) ⋮---- // SetEpochDuration is a paid mutator transaction binding the contract method 0x2f53d5ff. ⋮---- // Solidity: function setEpochDuration(uint48 epochDuration) returns() func (_IValSetDriver *IValSetDriverTransactor) SetEpochDuration(opts *bind.TransactOpts, epochDuration *big.Int) (*types.Transaction, error) ⋮---- // SetKeysProvider is a paid mutator transaction binding the contract method 0xdd08bbff. ⋮---- // Solidity: function setKeysProvider((uint64,address) keysProvider) returns() func (_IValSetDriver *IValSetDriverTransactor) SetKeysProvider(opts *bind.TransactOpts, keysProvider IValSetDriverCrossChainAddress) (*types.Transaction, error) ⋮---- // SetMaxValidatorsCount is a paid mutator transaction binding the contract method 0xd2384cd3. ⋮---- // Solidity: function setMaxValidatorsCount(uint208 maxValidatorsCount) returns() func (_IValSetDriver *IValSetDriverTransactor) SetMaxValidatorsCount(opts *bind.TransactOpts, maxValidatorsCount *big.Int) (*types.Transaction, error) ⋮---- // SetMaxVotingPower is a paid mutator transaction binding the contract method 0xf6af258c. ⋮---- // Solidity: function setMaxVotingPower(uint256 maxVotingPower) returns() func (_IValSetDriver *IValSetDriverTransactor) SetMaxVotingPower(opts *bind.TransactOpts, maxVotingPower *big.Int) (*types.Transaction, error) ⋮---- // SetMinInclusionVotingPower is a paid mutator transaction binding the contract method 0xfaae42d7. ⋮---- // Solidity: function setMinInclusionVotingPower(uint256 minInclusionVotingPower) returns() func (_IValSetDriver *IValSetDriverTransactor) SetMinInclusionVotingPower(opts *bind.TransactOpts, minInclusionVotingPower *big.Int) (*types.Transaction, error) ⋮---- // SetNumAggregators is a paid mutator transaction binding the contract method 0x0dec288b. ⋮---- // Solidity: function setNumAggregators(uint208 numAggregators) returns() func (_IValSetDriver *IValSetDriverTransactor) SetNumAggregators(opts *bind.TransactOpts, numAggregators *big.Int) (*types.Transaction, error) ⋮---- // SetNumCommitters is a paid mutator transaction binding the contract method 0x15ddbbe8. ⋮---- // Solidity: function setNumCommitters(uint208 numCommitters) returns() func (_IValSetDriver *IValSetDriverTransactor) SetNumCommitters(opts *bind.TransactOpts, numCommitters *big.Int) (*types.Transaction, error) ⋮---- // SetRequiredHeaderKeyTag is a paid mutator transaction binding the contract method 0xd9736e12. ⋮---- // Solidity: function setRequiredHeaderKeyTag(uint8 requiredHeaderKeyTag) returns() func (_IValSetDriver *IValSetDriverTransactor) SetRequiredHeaderKeyTag(opts *bind.TransactOpts, requiredHeaderKeyTag uint8) (*types.Transaction, error) ⋮---- // SetRequiredKeyTags is a paid mutator transaction binding the contract method 0x4678a284. ⋮---- // Solidity: function setRequiredKeyTags(uint8[] requiredKeyTags) returns() func (_IValSetDriver *IValSetDriverTransactor) SetRequiredKeyTags(opts *bind.TransactOpts, requiredKeyTags []uint8) (*types.Transaction, error) ⋮---- // SetVerificationType is a paid mutator transaction binding the contract method 0x7b8ef42d. ⋮---- // Solidity: function setVerificationType(uint32 verificationType) returns() func (_IValSetDriver *IValSetDriverTransactor) SetVerificationType(opts *bind.TransactOpts, verificationType uint32) (*types.Transaction, error) ⋮---- // StaticDelegateCall is a paid mutator transaction binding the contract method 0x9f86fd85. ⋮---- // Solidity: function staticDelegateCall(address target, bytes data) returns() func (_IValSetDriver *IValSetDriverTransactor) StaticDelegateCall(opts *bind.TransactOpts, target common.Address, data []byte) (*types.Transaction, error) ⋮---- // IValSetDriverAddQuorumThresholdIterator is returned from FilterAddQuorumThreshold and is used to iterate over the raw logs and unpacked data for AddQuorumThreshold events raised by the IValSetDriver contract. type IValSetDriverAddQuorumThresholdIterator struct { Event *IValSetDriverAddQuorumThreshold // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverAddQuorumThreshold // Event containing the contract specifics and raw log ⋮---- contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data ⋮---- logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration ⋮---- // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. func (it *IValSetDriverAddQuorumThresholdIterator) Next() bool ⋮---- // If the iterator failed, stop iterating ⋮---- // If the iterator completed, deliver directly whatever's available ⋮---- // Iterator still in progress, wait for either a data or an error event ⋮---- // Error returns any retrieval or parsing error occurred during filtering. func (it *IValSetDriverAddQuorumThresholdIterator) Error() error ⋮---- // Close terminates the iteration process, releasing any pending underlying // resources. func (it *IValSetDriverAddQuorumThresholdIterator) Close() error ⋮---- // IValSetDriverAddQuorumThreshold represents a AddQuorumThreshold event raised by the IValSetDriver contract. type IValSetDriverAddQuorumThreshold struct { QuorumThreshold IValSetDriverQuorumThreshold Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterAddQuorumThreshold is a free log retrieval operation binding the contract event 0x88ee37bfc079201d8493557f757c8ff6b14222ae13a8393747fb3c74b8ddf06f. ⋮---- // Solidity: event AddQuorumThreshold((uint8,uint248) quorumThreshold) func (_IValSetDriver *IValSetDriverFilterer) FilterAddQuorumThreshold(opts *bind.FilterOpts) (*IValSetDriverAddQuorumThresholdIterator, error) ⋮---- // WatchAddQuorumThreshold is a free log subscription operation binding the contract event 0x88ee37bfc079201d8493557f757c8ff6b14222ae13a8393747fb3c74b8ddf06f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchAddQuorumThreshold(opts *bind.WatchOpts, sink chan<- *IValSetDriverAddQuorumThreshold) (event.Subscription, error) ⋮---- // New log arrived, parse the event and forward to the user ⋮---- // ParseAddQuorumThreshold is a log parse operation binding the contract event 0x88ee37bfc079201d8493557f757c8ff6b14222ae13a8393747fb3c74b8ddf06f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseAddQuorumThreshold(log types.Log) (*IValSetDriverAddQuorumThreshold, error) ⋮---- // IValSetDriverAddSettlementIterator is returned from FilterAddSettlement and is used to iterate over the raw logs and unpacked data for AddSettlement events raised by the IValSetDriver contract. type IValSetDriverAddSettlementIterator struct { Event *IValSetDriverAddSettlement // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverAddSettlement // Event containing the contract specifics and raw log ⋮---- // IValSetDriverAddSettlement represents a AddSettlement event raised by the IValSetDriver contract. type IValSetDriverAddSettlement struct { Settlement IValSetDriverCrossChainAddress Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterAddSettlement is a free log retrieval operation binding the contract event 0xd66c27144960b789ff7b5514538e3d85a3623c1669b8d6db4eb85658df2aad57. ⋮---- // Solidity: event AddSettlement((uint64,address) settlement) func (_IValSetDriver *IValSetDriverFilterer) FilterAddSettlement(opts *bind.FilterOpts) (*IValSetDriverAddSettlementIterator, error) ⋮---- // WatchAddSettlement is a free log subscription operation binding the contract event 0xd66c27144960b789ff7b5514538e3d85a3623c1669b8d6db4eb85658df2aad57. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchAddSettlement(opts *bind.WatchOpts, sink chan<- *IValSetDriverAddSettlement) (event.Subscription, error) ⋮---- // ParseAddSettlement is a log parse operation binding the contract event 0xd66c27144960b789ff7b5514538e3d85a3623c1669b8d6db4eb85658df2aad57. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseAddSettlement(log types.Log) (*IValSetDriverAddSettlement, error) ⋮---- // IValSetDriverAddVotingPowerProviderIterator is returned from FilterAddVotingPowerProvider and is used to iterate over the raw logs and unpacked data for AddVotingPowerProvider events raised by the IValSetDriver contract. type IValSetDriverAddVotingPowerProviderIterator struct { Event *IValSetDriverAddVotingPowerProvider // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverAddVotingPowerProvider // Event containing the contract specifics and raw log ⋮---- // IValSetDriverAddVotingPowerProvider represents a AddVotingPowerProvider event raised by the IValSetDriver contract. type IValSetDriverAddVotingPowerProvider struct { VotingPowerProvider IValSetDriverCrossChainAddress Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterAddVotingPowerProvider is a free log retrieval operation binding the contract event 0xa8ba28fa43d2ebdcd4f5c29ee4f5e5fb568e9986ae8be7c6ae54540176d6147f. ⋮---- // Solidity: event AddVotingPowerProvider((uint64,address) votingPowerProvider) func (_IValSetDriver *IValSetDriverFilterer) FilterAddVotingPowerProvider(opts *bind.FilterOpts) (*IValSetDriverAddVotingPowerProviderIterator, error) ⋮---- // WatchAddVotingPowerProvider is a free log subscription operation binding the contract event 0xa8ba28fa43d2ebdcd4f5c29ee4f5e5fb568e9986ae8be7c6ae54540176d6147f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchAddVotingPowerProvider(opts *bind.WatchOpts, sink chan<- *IValSetDriverAddVotingPowerProvider) (event.Subscription, error) ⋮---- // ParseAddVotingPowerProvider is a log parse operation binding the contract event 0xa8ba28fa43d2ebdcd4f5c29ee4f5e5fb568e9986ae8be7c6ae54540176d6147f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseAddVotingPowerProvider(log types.Log) (*IValSetDriverAddVotingPowerProvider, error) ⋮---- // IValSetDriverInitEpochDurationIterator is returned from FilterInitEpochDuration and is used to iterate over the raw logs and unpacked data for InitEpochDuration events raised by the IValSetDriver contract. type IValSetDriverInitEpochDurationIterator struct { Event *IValSetDriverInitEpochDuration // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverInitEpochDuration // Event containing the contract specifics and raw log ⋮---- // IValSetDriverInitEpochDuration represents a InitEpochDuration event raised by the IValSetDriver contract. type IValSetDriverInitEpochDuration struct { EpochDuration *big.Int EpochDurationTimestamp *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterInitEpochDuration is a free log retrieval operation binding the contract event 0xf688b7b02a20c2dda7d7de03a41637b274af7706eb975ea4af45858648370f55. ⋮---- // Solidity: event InitEpochDuration(uint48 epochDuration, uint48 epochDurationTimestamp) func (_IValSetDriver *IValSetDriverFilterer) FilterInitEpochDuration(opts *bind.FilterOpts) (*IValSetDriverInitEpochDurationIterator, error) ⋮---- // WatchInitEpochDuration is a free log subscription operation binding the contract event 0xf688b7b02a20c2dda7d7de03a41637b274af7706eb975ea4af45858648370f55. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchInitEpochDuration(opts *bind.WatchOpts, sink chan<- *IValSetDriverInitEpochDuration) (event.Subscription, error) ⋮---- // ParseInitEpochDuration is a log parse operation binding the contract event 0xf688b7b02a20c2dda7d7de03a41637b274af7706eb975ea4af45858648370f55. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseInitEpochDuration(log types.Log) (*IValSetDriverInitEpochDuration, error) ⋮---- // IValSetDriverInitSubnetworkIterator is returned from FilterInitSubnetwork and is used to iterate over the raw logs and unpacked data for InitSubnetwork events raised by the IValSetDriver contract. type IValSetDriverInitSubnetworkIterator struct { Event *IValSetDriverInitSubnetwork // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverInitSubnetwork // Event containing the contract specifics and raw log ⋮---- // IValSetDriverInitSubnetwork represents a InitSubnetwork event raised by the IValSetDriver contract. type IValSetDriverInitSubnetwork struct { Network common.Address SubnetworkId *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterInitSubnetwork is a free log retrieval operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- // Solidity: event InitSubnetwork(address network, uint96 subnetworkId) func (_IValSetDriver *IValSetDriverFilterer) FilterInitSubnetwork(opts *bind.FilterOpts) (*IValSetDriverInitSubnetworkIterator, error) ⋮---- // WatchInitSubnetwork is a free log subscription operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchInitSubnetwork(opts *bind.WatchOpts, sink chan<- *IValSetDriverInitSubnetwork) (event.Subscription, error) ⋮---- // ParseInitSubnetwork is a log parse operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseInitSubnetwork(log types.Log) (*IValSetDriverInitSubnetwork, error) ⋮---- // IValSetDriverInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the IValSetDriver contract. type IValSetDriverInitializedIterator struct { Event *IValSetDriverInitialized // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverInitialized // Event containing the contract specifics and raw log ⋮---- // IValSetDriverInitialized represents a Initialized event raised by the IValSetDriver contract. type IValSetDriverInitialized struct { Version uint64 Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- // Solidity: event Initialized(uint64 version) func (_IValSetDriver *IValSetDriverFilterer) FilterInitialized(opts *bind.FilterOpts) (*IValSetDriverInitializedIterator, error) ⋮---- // WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *IValSetDriverInitialized) (event.Subscription, error) ⋮---- // ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseInitialized(log types.Log) (*IValSetDriverInitialized, error) ⋮---- // IValSetDriverRemoveQuorumThresholdIterator is returned from FilterRemoveQuorumThreshold and is used to iterate over the raw logs and unpacked data for RemoveQuorumThreshold events raised by the IValSetDriver contract. type IValSetDriverRemoveQuorumThresholdIterator struct { Event *IValSetDriverRemoveQuorumThreshold // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverRemoveQuorumThreshold // Event containing the contract specifics and raw log ⋮---- // IValSetDriverRemoveQuorumThreshold represents a RemoveQuorumThreshold event raised by the IValSetDriver contract. type IValSetDriverRemoveQuorumThreshold struct { QuorumThreshold IValSetDriverQuorumThreshold Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterRemoveQuorumThreshold is a free log retrieval operation binding the contract event 0xb321a5a0425badf1acf0a0b21b7984fa61e1e6405ae9011d4dcdb29b0e2f43ec. ⋮---- // Solidity: event RemoveQuorumThreshold((uint8,uint248) quorumThreshold) func (_IValSetDriver *IValSetDriverFilterer) FilterRemoveQuorumThreshold(opts *bind.FilterOpts) (*IValSetDriverRemoveQuorumThresholdIterator, error) ⋮---- // WatchRemoveQuorumThreshold is a free log subscription operation binding the contract event 0xb321a5a0425badf1acf0a0b21b7984fa61e1e6405ae9011d4dcdb29b0e2f43ec. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchRemoveQuorumThreshold(opts *bind.WatchOpts, sink chan<- *IValSetDriverRemoveQuorumThreshold) (event.Subscription, error) ⋮---- // ParseRemoveQuorumThreshold is a log parse operation binding the contract event 0xb321a5a0425badf1acf0a0b21b7984fa61e1e6405ae9011d4dcdb29b0e2f43ec. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseRemoveQuorumThreshold(log types.Log) (*IValSetDriverRemoveQuorumThreshold, error) ⋮---- // IValSetDriverRemoveSettlementIterator is returned from FilterRemoveSettlement and is used to iterate over the raw logs and unpacked data for RemoveSettlement events raised by the IValSetDriver contract. type IValSetDriverRemoveSettlementIterator struct { Event *IValSetDriverRemoveSettlement // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverRemoveSettlement // Event containing the contract specifics and raw log ⋮---- // IValSetDriverRemoveSettlement represents a RemoveSettlement event raised by the IValSetDriver contract. type IValSetDriverRemoveSettlement struct { Settlement IValSetDriverCrossChainAddress Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterRemoveSettlement is a free log retrieval operation binding the contract event 0x6307047e2a245d2a5867f7667a4a48687593b73e3b2f95d2204256cbff350cf3. ⋮---- // Solidity: event RemoveSettlement((uint64,address) settlement) func (_IValSetDriver *IValSetDriverFilterer) FilterRemoveSettlement(opts *bind.FilterOpts) (*IValSetDriverRemoveSettlementIterator, error) ⋮---- // WatchRemoveSettlement is a free log subscription operation binding the contract event 0x6307047e2a245d2a5867f7667a4a48687593b73e3b2f95d2204256cbff350cf3. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchRemoveSettlement(opts *bind.WatchOpts, sink chan<- *IValSetDriverRemoveSettlement) (event.Subscription, error) ⋮---- // ParseRemoveSettlement is a log parse operation binding the contract event 0x6307047e2a245d2a5867f7667a4a48687593b73e3b2f95d2204256cbff350cf3. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseRemoveSettlement(log types.Log) (*IValSetDriverRemoveSettlement, error) ⋮---- // IValSetDriverRemoveVotingPowerProviderIterator is returned from FilterRemoveVotingPowerProvider and is used to iterate over the raw logs and unpacked data for RemoveVotingPowerProvider events raised by the IValSetDriver contract. type IValSetDriverRemoveVotingPowerProviderIterator struct { Event *IValSetDriverRemoveVotingPowerProvider // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverRemoveVotingPowerProvider // Event containing the contract specifics and raw log ⋮---- // IValSetDriverRemoveVotingPowerProvider represents a RemoveVotingPowerProvider event raised by the IValSetDriver contract. type IValSetDriverRemoveVotingPowerProvider struct { VotingPowerProvider IValSetDriverCrossChainAddress Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterRemoveVotingPowerProvider is a free log retrieval operation binding the contract event 0x2a2103a52b9c3907936be3fea265a7bd34fdfc0c8c09cc3b8e3938b7deda761f. ⋮---- // Solidity: event RemoveVotingPowerProvider((uint64,address) votingPowerProvider) func (_IValSetDriver *IValSetDriverFilterer) FilterRemoveVotingPowerProvider(opts *bind.FilterOpts) (*IValSetDriverRemoveVotingPowerProviderIterator, error) ⋮---- // WatchRemoveVotingPowerProvider is a free log subscription operation binding the contract event 0x2a2103a52b9c3907936be3fea265a7bd34fdfc0c8c09cc3b8e3938b7deda761f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchRemoveVotingPowerProvider(opts *bind.WatchOpts, sink chan<- *IValSetDriverRemoveVotingPowerProvider) (event.Subscription, error) ⋮---- // ParseRemoveVotingPowerProvider is a log parse operation binding the contract event 0x2a2103a52b9c3907936be3fea265a7bd34fdfc0c8c09cc3b8e3938b7deda761f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseRemoveVotingPowerProvider(log types.Log) (*IValSetDriverRemoveVotingPowerProvider, error) ⋮---- // IValSetDriverSetEpochDurationIterator is returned from FilterSetEpochDuration and is used to iterate over the raw logs and unpacked data for SetEpochDuration events raised by the IValSetDriver contract. type IValSetDriverSetEpochDurationIterator struct { Event *IValSetDriverSetEpochDuration // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetEpochDuration // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetEpochDuration represents a SetEpochDuration event raised by the IValSetDriver contract. type IValSetDriverSetEpochDuration struct { EpochDuration *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetEpochDuration is a free log retrieval operation binding the contract event 0xc950f06b73b224f8b32d39245a5905020aebfc426a15833a70ac2e4e2ebe098c. ⋮---- // Solidity: event SetEpochDuration(uint48 epochDuration) func (_IValSetDriver *IValSetDriverFilterer) FilterSetEpochDuration(opts *bind.FilterOpts) (*IValSetDriverSetEpochDurationIterator, error) ⋮---- // WatchSetEpochDuration is a free log subscription operation binding the contract event 0xc950f06b73b224f8b32d39245a5905020aebfc426a15833a70ac2e4e2ebe098c. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetEpochDuration(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetEpochDuration) (event.Subscription, error) ⋮---- // ParseSetEpochDuration is a log parse operation binding the contract event 0xc950f06b73b224f8b32d39245a5905020aebfc426a15833a70ac2e4e2ebe098c. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetEpochDuration(log types.Log) (*IValSetDriverSetEpochDuration, error) ⋮---- // IValSetDriverSetKeysProviderIterator is returned from FilterSetKeysProvider and is used to iterate over the raw logs and unpacked data for SetKeysProvider events raised by the IValSetDriver contract. type IValSetDriverSetKeysProviderIterator struct { Event *IValSetDriverSetKeysProvider // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetKeysProvider // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetKeysProvider represents a SetKeysProvider event raised by the IValSetDriver contract. type IValSetDriverSetKeysProvider struct { KeysProvider IValSetDriverCrossChainAddress Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterSetKeysProvider is a free log retrieval operation binding the contract event 0x15ceb492f5dd0988720d5f2258f4de98a2ac5df85b25ed2f33eda91e90e07321. ⋮---- // Solidity: event SetKeysProvider((uint64,address) keysProvider) func (_IValSetDriver *IValSetDriverFilterer) FilterSetKeysProvider(opts *bind.FilterOpts) (*IValSetDriverSetKeysProviderIterator, error) ⋮---- // WatchSetKeysProvider is a free log subscription operation binding the contract event 0x15ceb492f5dd0988720d5f2258f4de98a2ac5df85b25ed2f33eda91e90e07321. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetKeysProvider(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetKeysProvider) (event.Subscription, error) ⋮---- // ParseSetKeysProvider is a log parse operation binding the contract event 0x15ceb492f5dd0988720d5f2258f4de98a2ac5df85b25ed2f33eda91e90e07321. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetKeysProvider(log types.Log) (*IValSetDriverSetKeysProvider, error) ⋮---- // IValSetDriverSetMaxValidatorsCountIterator is returned from FilterSetMaxValidatorsCount and is used to iterate over the raw logs and unpacked data for SetMaxValidatorsCount events raised by the IValSetDriver contract. type IValSetDriverSetMaxValidatorsCountIterator struct { Event *IValSetDriverSetMaxValidatorsCount // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetMaxValidatorsCount // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetMaxValidatorsCount represents a SetMaxValidatorsCount event raised by the IValSetDriver contract. type IValSetDriverSetMaxValidatorsCount struct { MaxValidatorsCount *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetMaxValidatorsCount is a free log retrieval operation binding the contract event 0x37ca3532b507cfa33b11765ae8b499cb6830421b982a7f8837ee71ca5a3119c8. ⋮---- // Solidity: event SetMaxValidatorsCount(uint208 maxValidatorsCount) func (_IValSetDriver *IValSetDriverFilterer) FilterSetMaxValidatorsCount(opts *bind.FilterOpts) (*IValSetDriverSetMaxValidatorsCountIterator, error) ⋮---- // WatchSetMaxValidatorsCount is a free log subscription operation binding the contract event 0x37ca3532b507cfa33b11765ae8b499cb6830421b982a7f8837ee71ca5a3119c8. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetMaxValidatorsCount(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetMaxValidatorsCount) (event.Subscription, error) ⋮---- // ParseSetMaxValidatorsCount is a log parse operation binding the contract event 0x37ca3532b507cfa33b11765ae8b499cb6830421b982a7f8837ee71ca5a3119c8. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetMaxValidatorsCount(log types.Log) (*IValSetDriverSetMaxValidatorsCount, error) ⋮---- // IValSetDriverSetMaxVotingPowerIterator is returned from FilterSetMaxVotingPower and is used to iterate over the raw logs and unpacked data for SetMaxVotingPower events raised by the IValSetDriver contract. type IValSetDriverSetMaxVotingPowerIterator struct { Event *IValSetDriverSetMaxVotingPower // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetMaxVotingPower // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetMaxVotingPower represents a SetMaxVotingPower event raised by the IValSetDriver contract. type IValSetDriverSetMaxVotingPower struct { MaxVotingPower *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetMaxVotingPower is a free log retrieval operation binding the contract event 0xe891886eac9e583940fb0844098689693a4d105206ec1f789d119b4314383b95. ⋮---- // Solidity: event SetMaxVotingPower(uint256 maxVotingPower) func (_IValSetDriver *IValSetDriverFilterer) FilterSetMaxVotingPower(opts *bind.FilterOpts) (*IValSetDriverSetMaxVotingPowerIterator, error) ⋮---- // WatchSetMaxVotingPower is a free log subscription operation binding the contract event 0xe891886eac9e583940fb0844098689693a4d105206ec1f789d119b4314383b95. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetMaxVotingPower(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetMaxVotingPower) (event.Subscription, error) ⋮---- // ParseSetMaxVotingPower is a log parse operation binding the contract event 0xe891886eac9e583940fb0844098689693a4d105206ec1f789d119b4314383b95. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetMaxVotingPower(log types.Log) (*IValSetDriverSetMaxVotingPower, error) ⋮---- // IValSetDriverSetMinInclusionVotingPowerIterator is returned from FilterSetMinInclusionVotingPower and is used to iterate over the raw logs and unpacked data for SetMinInclusionVotingPower events raised by the IValSetDriver contract. type IValSetDriverSetMinInclusionVotingPowerIterator struct { Event *IValSetDriverSetMinInclusionVotingPower // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetMinInclusionVotingPower // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetMinInclusionVotingPower represents a SetMinInclusionVotingPower event raised by the IValSetDriver contract. type IValSetDriverSetMinInclusionVotingPower struct { MinInclusionVotingPower *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetMinInclusionVotingPower is a free log retrieval operation binding the contract event 0x7ea1f11872caff0567f050bd06f29f128a1407e56e3272abbadef87f6cbb6188. ⋮---- // Solidity: event SetMinInclusionVotingPower(uint256 minInclusionVotingPower) func (_IValSetDriver *IValSetDriverFilterer) FilterSetMinInclusionVotingPower(opts *bind.FilterOpts) (*IValSetDriverSetMinInclusionVotingPowerIterator, error) ⋮---- // WatchSetMinInclusionVotingPower is a free log subscription operation binding the contract event 0x7ea1f11872caff0567f050bd06f29f128a1407e56e3272abbadef87f6cbb6188. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetMinInclusionVotingPower(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetMinInclusionVotingPower) (event.Subscription, error) ⋮---- // ParseSetMinInclusionVotingPower is a log parse operation binding the contract event 0x7ea1f11872caff0567f050bd06f29f128a1407e56e3272abbadef87f6cbb6188. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetMinInclusionVotingPower(log types.Log) (*IValSetDriverSetMinInclusionVotingPower, error) ⋮---- // IValSetDriverSetNumAggregatorsIterator is returned from FilterSetNumAggregators and is used to iterate over the raw logs and unpacked data for SetNumAggregators events raised by the IValSetDriver contract. type IValSetDriverSetNumAggregatorsIterator struct { Event *IValSetDriverSetNumAggregators // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetNumAggregators // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetNumAggregators represents a SetNumAggregators event raised by the IValSetDriver contract. type IValSetDriverSetNumAggregators struct { NumAggregators *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterSetNumAggregators is a free log retrieval operation binding the contract event 0xa47e6808a463c6134cf3bb23d54ee0ccb5c8056ab8c8b5fd5277fc83cc2f25f3. ⋮---- // Solidity: event SetNumAggregators(uint208 numAggregators) func (_IValSetDriver *IValSetDriverFilterer) FilterSetNumAggregators(opts *bind.FilterOpts) (*IValSetDriverSetNumAggregatorsIterator, error) ⋮---- // WatchSetNumAggregators is a free log subscription operation binding the contract event 0xa47e6808a463c6134cf3bb23d54ee0ccb5c8056ab8c8b5fd5277fc83cc2f25f3. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetNumAggregators(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetNumAggregators) (event.Subscription, error) ⋮---- // ParseSetNumAggregators is a log parse operation binding the contract event 0xa47e6808a463c6134cf3bb23d54ee0ccb5c8056ab8c8b5fd5277fc83cc2f25f3. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetNumAggregators(log types.Log) (*IValSetDriverSetNumAggregators, error) ⋮---- // IValSetDriverSetNumCommittersIterator is returned from FilterSetNumCommitters and is used to iterate over the raw logs and unpacked data for SetNumCommitters events raised by the IValSetDriver contract. type IValSetDriverSetNumCommittersIterator struct { Event *IValSetDriverSetNumCommitters // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetNumCommitters // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetNumCommitters represents a SetNumCommitters event raised by the IValSetDriver contract. type IValSetDriverSetNumCommitters struct { NumCommitters *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterSetNumCommitters is a free log retrieval operation binding the contract event 0x931a819f63102a134c17aeb8b67a254fc3e215c35487041ff43fd3225b272b5f. ⋮---- // Solidity: event SetNumCommitters(uint208 numCommitters) func (_IValSetDriver *IValSetDriverFilterer) FilterSetNumCommitters(opts *bind.FilterOpts) (*IValSetDriverSetNumCommittersIterator, error) ⋮---- // WatchSetNumCommitters is a free log subscription operation binding the contract event 0x931a819f63102a134c17aeb8b67a254fc3e215c35487041ff43fd3225b272b5f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetNumCommitters(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetNumCommitters) (event.Subscription, error) ⋮---- // ParseSetNumCommitters is a log parse operation binding the contract event 0x931a819f63102a134c17aeb8b67a254fc3e215c35487041ff43fd3225b272b5f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetNumCommitters(log types.Log) (*IValSetDriverSetNumCommitters, error) ⋮---- // IValSetDriverSetRequiredHeaderKeyTagIterator is returned from FilterSetRequiredHeaderKeyTag and is used to iterate over the raw logs and unpacked data for SetRequiredHeaderKeyTag events raised by the IValSetDriver contract. type IValSetDriverSetRequiredHeaderKeyTagIterator struct { Event *IValSetDriverSetRequiredHeaderKeyTag // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetRequiredHeaderKeyTag // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetRequiredHeaderKeyTag represents a SetRequiredHeaderKeyTag event raised by the IValSetDriver contract. type IValSetDriverSetRequiredHeaderKeyTag struct { RequiredHeaderKeyTag uint8 Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetRequiredHeaderKeyTag is a free log retrieval operation binding the contract event 0xba7887224500eabdaa5bddd0e0210aec811345379939ffbbc4bc87bdfb673b70. ⋮---- // Solidity: event SetRequiredHeaderKeyTag(uint8 requiredHeaderKeyTag) func (_IValSetDriver *IValSetDriverFilterer) FilterSetRequiredHeaderKeyTag(opts *bind.FilterOpts) (*IValSetDriverSetRequiredHeaderKeyTagIterator, error) ⋮---- // WatchSetRequiredHeaderKeyTag is a free log subscription operation binding the contract event 0xba7887224500eabdaa5bddd0e0210aec811345379939ffbbc4bc87bdfb673b70. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetRequiredHeaderKeyTag(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetRequiredHeaderKeyTag) (event.Subscription, error) ⋮---- // ParseSetRequiredHeaderKeyTag is a log parse operation binding the contract event 0xba7887224500eabdaa5bddd0e0210aec811345379939ffbbc4bc87bdfb673b70. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetRequiredHeaderKeyTag(log types.Log) (*IValSetDriverSetRequiredHeaderKeyTag, error) ⋮---- // IValSetDriverSetRequiredKeyTagsIterator is returned from FilterSetRequiredKeyTags and is used to iterate over the raw logs and unpacked data for SetRequiredKeyTags events raised by the IValSetDriver contract. type IValSetDriverSetRequiredKeyTagsIterator struct { Event *IValSetDriverSetRequiredKeyTags // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetRequiredKeyTags // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetRequiredKeyTags represents a SetRequiredKeyTags event raised by the IValSetDriver contract. type IValSetDriverSetRequiredKeyTags struct { RequiredKeyTags []uint8 Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterSetRequiredKeyTags is a free log retrieval operation binding the contract event 0x14f8998266f37e593027a05efebf63b8710681d1cdbd39e6d7a156ff7e1485cd. ⋮---- // Solidity: event SetRequiredKeyTags(uint8[] requiredKeyTags) func (_IValSetDriver *IValSetDriverFilterer) FilterSetRequiredKeyTags(opts *bind.FilterOpts) (*IValSetDriverSetRequiredKeyTagsIterator, error) ⋮---- // WatchSetRequiredKeyTags is a free log subscription operation binding the contract event 0x14f8998266f37e593027a05efebf63b8710681d1cdbd39e6d7a156ff7e1485cd. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetRequiredKeyTags(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetRequiredKeyTags) (event.Subscription, error) ⋮---- // ParseSetRequiredKeyTags is a log parse operation binding the contract event 0x14f8998266f37e593027a05efebf63b8710681d1cdbd39e6d7a156ff7e1485cd. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetRequiredKeyTags(log types.Log) (*IValSetDriverSetRequiredKeyTags, error) ⋮---- // IValSetDriverSetVerificationTypeIterator is returned from FilterSetVerificationType and is used to iterate over the raw logs and unpacked data for SetVerificationType events raised by the IValSetDriver contract. type IValSetDriverSetVerificationTypeIterator struct { Event *IValSetDriverSetVerificationType // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IValSetDriverSetVerificationType // Event containing the contract specifics and raw log ⋮---- // IValSetDriverSetVerificationType represents a SetVerificationType event raised by the IValSetDriver contract. type IValSetDriverSetVerificationType struct { VerificationType uint32 Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetVerificationType is a free log retrieval operation binding the contract event 0x2acc7be3ff5df4b911488f72502071dcf3f4a8f778a8abc351af3220bcd15b7f. ⋮---- // Solidity: event SetVerificationType(uint32 verificationType) func (_IValSetDriver *IValSetDriverFilterer) FilterSetVerificationType(opts *bind.FilterOpts) (*IValSetDriverSetVerificationTypeIterator, error) ⋮---- // WatchSetVerificationType is a free log subscription operation binding the contract event 0x2acc7be3ff5df4b911488f72502071dcf3f4a8f778a8abc351af3220bcd15b7f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) WatchSetVerificationType(opts *bind.WatchOpts, sink chan<- *IValSetDriverSetVerificationType) (event.Subscription, error) ⋮---- // ParseSetVerificationType is a log parse operation binding the contract event 0x2acc7be3ff5df4b911488f72502071dcf3f4a8f778a8abc351af3220bcd15b7f. ⋮---- func (_IValSetDriver *IValSetDriverFilterer) ParseSetVerificationType(log types.Log) (*IValSetDriverSetVerificationType, error) ```` ## File: symbiotic/client/evm/gen/votingPowerProvider.go ````go // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. ⋮---- package gen ⋮---- import ( "errors" "math/big" "strings" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ) ⋮---- "errors" "math/big" "strings" ⋮---- ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ⋮---- // Reference imports to suppress errors if they are not otherwise used. var ( _ = errors.New _ = big.NewInt _ = strings.NewReader _ = ethereum.NotFound _ = bind.Bind _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription _ = abi.ConvertType ) ⋮---- // IVotingPowerProviderOperatorVotingPower is an auto generated low-level Go binding around an user-defined struct. type IVotingPowerProviderOperatorVotingPower struct { Operator common.Address Vaults []IVotingPowerProviderVaultValue } ⋮---- // IVotingPowerProviderVaultValue is an auto generated low-level Go binding around an user-defined struct. type IVotingPowerProviderVaultValue struct { Vault common.Address Value *big.Int } ⋮---- // IVotingPowerProviderMetaData contains all meta data concerning the IVotingPowerProvider contract. var IVotingPowerProviderMetaData = &bind.MetaData{ ABI: "[{\"type\":\"function\",\"name\":\"NETWORK\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"OPERATOR_REGISTRY\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SUBNETWORK\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SUBNETWORK_IDENTIFIER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint96\",\"internalType\":\"uint96\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VAULT_FACTORY\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"eip712Domain\",\"inputs\":[],\"outputs\":[{\"name\":\"fields\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"},{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"salt\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"extensions\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperatorStakes\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.VaultValue[]\",\"components\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperatorStakesAt\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.VaultValue[]\",\"components\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperatorVaults\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperatorVaultsAt\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperatorVotingPowers\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.VaultValue[]\",\"components\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperatorVotingPowersAt\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.VaultValue[]\",\"components\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperators\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOperatorsAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSharedVaults\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSharedVaultsAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSlashingData\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSlashingDataAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"},{\"name\":\"hint\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokens\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokensAt\",\"inputs\":[{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVotingPowers\",\"inputs\":[{\"name\":\"extraData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.OperatorVotingPower[]\",\"components\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"vaults\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.VaultValue[]\",\"components\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVotingPowersAt\",\"inputs\":[{\"name\":\"extraData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.OperatorVotingPower[]\",\"components\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"vaults\",\"type\":\"tuple[]\",\"internalType\":\"structIVotingPowerProvider.VaultValue[]\",\"components\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hashTypedDataV4\",\"inputs\":[{\"name\":\"structHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hashTypedDataV4CrossChain\",\"inputs\":[{\"name\":\"structHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"invalidateOldSignatures\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isOperatorRegistered\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isOperatorRegisteredAt\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isOperatorVaultRegistered\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isOperatorVaultRegistered\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isOperatorVaultRegisteredAt\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isOperatorVaultRegisteredAt\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSharedVaultRegistered\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSharedVaultRegisteredAt\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isTokenRegistered\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isTokenRegisteredAt\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"multicall\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[{\"name\":\"results\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"nonces\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"registerOperator\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registerOperatorWithSignature\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"stakeToVotingPower\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"stake\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"power\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"stakeToVotingPowerAt\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"stake\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timestamp\",\"type\":\"uint48\",\"internalType\":\"uint48\"}],\"outputs\":[{\"name\":\"power\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"staticDelegateCall\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unregisterOperator\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unregisterOperatorWithSignature\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"EIP712DomainChanged\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitEIP712\",\"inputs\":[{\"name\":\"name\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitSubnetwork\",\"inputs\":[{\"name\":\"network\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"subnetworkId\",\"type\":\"uint96\",\"indexed\":false,\"internalType\":\"uint96\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RegisterOperator\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RegisterOperatorVault\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"vault\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RegisterSharedVault\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RegisterToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SetSlashingData\",\"inputs\":[{\"name\":\"requireSlasher\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"},{\"name\":\"minVaultEpochDuration\",\"type\":\"uint48\",\"indexed\":false,\"internalType\":\"uint48\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UnregisterOperator\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UnregisterOperatorVault\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"vault\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UnregisterSharedVault\",\"inputs\":[{\"name\":\"vault\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UnregisterToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidAccountNonce\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"currentNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NetworkManager_InvalidNetwork\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_InvalidOperator\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_InvalidOperatorVault\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_InvalidSharedVault\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_InvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_InvalidToken\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_InvalidVault\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_OperatorAlreadyRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_OperatorNotRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_OperatorVaultAlreadyIsRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_OperatorVaultNotRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_SharedVaultAlreadyIsRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_SharedVaultNotRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_TokenAlreadyIsRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VotingPowerProvider_TokenNotRegistered\",\"inputs\":[]}]", } ⋮---- // IVotingPowerProviderABI is the input ABI used to generate the binding from. // Deprecated: Use IVotingPowerProviderMetaData.ABI instead. var IVotingPowerProviderABI = IVotingPowerProviderMetaData.ABI ⋮---- // IVotingPowerProvider is an auto generated Go binding around an Ethereum contract. type IVotingPowerProvider struct { IVotingPowerProviderCaller // Read-only binding to the contract IVotingPowerProviderTransactor // Write-only binding to the contract IVotingPowerProviderFilterer // Log filterer for contract events } ⋮---- IVotingPowerProviderCaller // Read-only binding to the contract IVotingPowerProviderTransactor // Write-only binding to the contract IVotingPowerProviderFilterer // Log filterer for contract events ⋮---- // IVotingPowerProviderCaller is an auto generated read-only Go binding around an Ethereum contract. type IVotingPowerProviderCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- contract *bind.BoundContract // Generic contract wrapper for the low level calls ⋮---- // IVotingPowerProviderTransactor is an auto generated write-only Go binding around an Ethereum contract. type IVotingPowerProviderTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // IVotingPowerProviderFilterer is an auto generated log filtering Go binding around an Ethereum contract events. type IVotingPowerProviderFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } ⋮---- // IVotingPowerProviderSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. type IVotingPowerProviderSession struct { Contract *IVotingPowerProvider // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *IVotingPowerProvider // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // IVotingPowerProviderCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. type IVotingPowerProviderCallerSession struct { Contract *IVotingPowerProviderCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } ⋮---- Contract *IVotingPowerProviderCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session ⋮---- // IVotingPowerProviderTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. type IVotingPowerProviderTransactorSession struct { Contract *IVotingPowerProviderTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } ⋮---- Contract *IVotingPowerProviderTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ⋮---- // IVotingPowerProviderRaw is an auto generated low-level Go binding around an Ethereum contract. type IVotingPowerProviderRaw struct { Contract *IVotingPowerProvider // Generic contract binding to access the raw methods on } ⋮---- Contract *IVotingPowerProvider // Generic contract binding to access the raw methods on ⋮---- // IVotingPowerProviderCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. type IVotingPowerProviderCallerRaw struct { Contract *IVotingPowerProviderCaller // Generic read-only contract binding to access the raw methods on } ⋮---- Contract *IVotingPowerProviderCaller // Generic read-only contract binding to access the raw methods on ⋮---- // IVotingPowerProviderTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. type IVotingPowerProviderTransactorRaw struct { Contract *IVotingPowerProviderTransactor // Generic write-only contract binding to access the raw methods on } ⋮---- Contract *IVotingPowerProviderTransactor // Generic write-only contract binding to access the raw methods on ⋮---- // NewIVotingPowerProvider creates a new instance of IVotingPowerProvider, bound to a specific deployed contract. func NewIVotingPowerProvider(address common.Address, backend bind.ContractBackend) (*IVotingPowerProvider, error) ⋮---- // NewIVotingPowerProviderCaller creates a new read-only instance of IVotingPowerProvider, bound to a specific deployed contract. func NewIVotingPowerProviderCaller(address common.Address, caller bind.ContractCaller) (*IVotingPowerProviderCaller, error) ⋮---- // NewIVotingPowerProviderTransactor creates a new write-only instance of IVotingPowerProvider, bound to a specific deployed contract. func NewIVotingPowerProviderTransactor(address common.Address, transactor bind.ContractTransactor) (*IVotingPowerProviderTransactor, error) ⋮---- // NewIVotingPowerProviderFilterer creates a new log filterer instance of IVotingPowerProvider, bound to a specific deployed contract. func NewIVotingPowerProviderFilterer(address common.Address, filterer bind.ContractFilterer) (*IVotingPowerProviderFilterer, error) ⋮---- // bindIVotingPowerProvider binds a generic wrapper to an already deployed contract. func bindIVotingPowerProvider(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) ⋮---- // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. func (_IVotingPowerProvider *IVotingPowerProviderRaw) Call(opts *bind.CallOpts, result *[]interface ⋮---- // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. func (_IVotingPowerProvider *IVotingPowerProviderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // Transact invokes the (paid) contract method with params as input values. func (_IVotingPowerProvider *IVotingPowerProviderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface ⋮---- // NETWORK is a free data retrieval call binding the contract method 0x8759e6d1. // // Solidity: function NETWORK() view returns(address) func (_IVotingPowerProvider *IVotingPowerProviderCaller) NETWORK(opts *bind.CallOpts) (common.Address, error) ⋮---- var out []interface{} ⋮---- // OPERATORREGISTRY is a free data retrieval call binding the contract method 0x83ce0322. ⋮---- // Solidity: function OPERATOR_REGISTRY() view returns(address) func (_IVotingPowerProvider *IVotingPowerProviderCaller) OPERATORREGISTRY(opts *bind.CallOpts) (common.Address, error) ⋮---- // SUBNETWORK is a free data retrieval call binding the contract method 0x773e6b54. ⋮---- // Solidity: function SUBNETWORK() view returns(bytes32) func (_IVotingPowerProvider *IVotingPowerProviderCaller) SUBNETWORK(opts *bind.CallOpts) ([32]byte, error) ⋮---- // SUBNETWORKIDENTIFIER is a free data retrieval call binding the contract method 0xabacb807. ⋮---- // Solidity: function SUBNETWORK_IDENTIFIER() view returns(uint96) func (_IVotingPowerProvider *IVotingPowerProviderCaller) SUBNETWORKIDENTIFIER(opts *bind.CallOpts) (*big.Int, error) ⋮---- // VAULTFACTORY is a free data retrieval call binding the contract method 0x103f2907. ⋮---- // Solidity: function VAULT_FACTORY() view returns(address) func (_IVotingPowerProvider *IVotingPowerProviderCaller) VAULTFACTORY(opts *bind.CallOpts) (common.Address, error) ⋮---- // Eip712Domain is a free data retrieval call binding the contract method 0x84b0196e. ⋮---- // Solidity: function eip712Domain() view returns(bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions) func (_IVotingPowerProvider *IVotingPowerProviderCaller) Eip712Domain(opts *bind.CallOpts) (struct ⋮---- // GetOperatorStakes is a free data retrieval call binding the contract method 0x93816a13. ⋮---- // Solidity: function getOperatorStakes(address operator) view returns((address,uint256)[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperatorStakes(opts *bind.CallOpts, operator common.Address) ([]IVotingPowerProviderVaultValue, error) ⋮---- // GetOperatorStakesAt is a free data retrieval call binding the contract method 0xa54e116e. ⋮---- // Solidity: function getOperatorStakesAt(address operator, uint48 timestamp) view returns((address,uint256)[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperatorStakesAt(opts *bind.CallOpts, operator common.Address, timestamp *big.Int) ([]IVotingPowerProviderVaultValue, error) ⋮---- // GetOperatorVaults is a free data retrieval call binding the contract method 0x14d7e25b. ⋮---- // Solidity: function getOperatorVaults(address operator) view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperatorVaults(opts *bind.CallOpts, operator common.Address) ([]common.Address, error) ⋮---- // GetOperatorVaultsAt is a free data retrieval call binding the contract method 0x49f993ec. ⋮---- // Solidity: function getOperatorVaultsAt(address operator, uint48 timestamp) view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperatorVaultsAt(opts *bind.CallOpts, operator common.Address, timestamp *big.Int) ([]common.Address, error) ⋮---- // GetOperatorVotingPowers is a free data retrieval call binding the contract method 0x63ff1140. ⋮---- // Solidity: function getOperatorVotingPowers(address operator, bytes extraData) view returns((address,uint256)[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperatorVotingPowers(opts *bind.CallOpts, operator common.Address, extraData []byte) ([]IVotingPowerProviderVaultValue, error) ⋮---- // GetOperatorVotingPowersAt is a free data retrieval call binding the contract method 0x380f9945. ⋮---- // Solidity: function getOperatorVotingPowersAt(address operator, bytes extraData, uint48 timestamp) view returns((address,uint256)[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperatorVotingPowersAt(opts *bind.CallOpts, operator common.Address, extraData []byte, timestamp *big.Int) ([]IVotingPowerProviderVaultValue, error) ⋮---- // GetOperators is a free data retrieval call binding the contract method 0x27a099d8. ⋮---- // Solidity: function getOperators() view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperators(opts *bind.CallOpts) ([]common.Address, error) ⋮---- // GetOperatorsAt is a free data retrieval call binding the contract method 0xa2e33009. ⋮---- // Solidity: function getOperatorsAt(uint48 timestamp) view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetOperatorsAt(opts *bind.CallOpts, timestamp *big.Int) ([]common.Address, error) ⋮---- // GetSharedVaults is a free data retrieval call binding the contract method 0xc28474cd. ⋮---- // Solidity: function getSharedVaults() view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetSharedVaults(opts *bind.CallOpts) ([]common.Address, error) ⋮---- // GetSharedVaultsAt is a free data retrieval call binding the contract method 0x4a0c7c17. ⋮---- // Solidity: function getSharedVaultsAt(uint48 timestamp) view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetSharedVaultsAt(opts *bind.CallOpts, timestamp *big.Int) ([]common.Address, error) ⋮---- // GetSlashingData is a free data retrieval call binding the contract method 0xf7dfb974. ⋮---- // Solidity: function getSlashingData() view returns(bool, uint48) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetSlashingData(opts *bind.CallOpts) (bool, *big.Int, error) ⋮---- // GetSlashingDataAt is a free data retrieval call binding the contract method 0x7a74c7fd. ⋮---- // Solidity: function getSlashingDataAt(uint48 timestamp, bytes hint) view returns(bool, uint48) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetSlashingDataAt(opts *bind.CallOpts, timestamp *big.Int, hint []byte) (bool, *big.Int, error) ⋮---- // GetTokens is a free data retrieval call binding the contract method 0xaa6ca808. ⋮---- // Solidity: function getTokens() view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetTokens(opts *bind.CallOpts) ([]common.Address, error) ⋮---- // GetTokensAt is a free data retrieval call binding the contract method 0x1796df1b. ⋮---- // Solidity: function getTokensAt(uint48 timestamp) view returns(address[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetTokensAt(opts *bind.CallOpts, timestamp *big.Int) ([]common.Address, error) ⋮---- // GetVotingPowers is a free data retrieval call binding the contract method 0xff7cd71c. ⋮---- // Solidity: function getVotingPowers(bytes[] extraData) view returns((address,(address,uint256)[])[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetVotingPowers(opts *bind.CallOpts, extraData [][]byte) ([]IVotingPowerProviderOperatorVotingPower, error) ⋮---- // GetVotingPowersAt is a free data retrieval call binding the contract method 0x77adea5f. ⋮---- // Solidity: function getVotingPowersAt(bytes[] extraData, uint48 timestamp) view returns((address,(address,uint256)[])[]) func (_IVotingPowerProvider *IVotingPowerProviderCaller) GetVotingPowersAt(opts *bind.CallOpts, extraData [][]byte, timestamp *big.Int) ([]IVotingPowerProviderOperatorVotingPower, error) ⋮---- // HashTypedDataV4 is a free data retrieval call binding the contract method 0x4980f288. ⋮---- // Solidity: function hashTypedDataV4(bytes32 structHash) view returns(bytes32) func (_IVotingPowerProvider *IVotingPowerProviderCaller) HashTypedDataV4(opts *bind.CallOpts, structHash [32]byte) ([32]byte, error) ⋮---- // HashTypedDataV4CrossChain is a free data retrieval call binding the contract method 0x518dcf3b. ⋮---- // Solidity: function hashTypedDataV4CrossChain(bytes32 structHash) view returns(bytes32) func (_IVotingPowerProvider *IVotingPowerProviderCaller) HashTypedDataV4CrossChain(opts *bind.CallOpts, structHash [32]byte) ([32]byte, error) ⋮---- // IsOperatorRegistered is a free data retrieval call binding the contract method 0x6b1906f8. ⋮---- // Solidity: function isOperatorRegistered(address operator) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsOperatorRegistered(opts *bind.CallOpts, operator common.Address) (bool, error) ⋮---- // IsOperatorRegisteredAt is a free data retrieval call binding the contract method 0x8a5aef51. ⋮---- // Solidity: function isOperatorRegisteredAt(address operator, uint48 timestamp) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsOperatorRegisteredAt(opts *bind.CallOpts, operator common.Address, timestamp *big.Int) (bool, error) ⋮---- // IsOperatorVaultRegistered is a free data retrieval call binding the contract method 0x0f6e0743. ⋮---- // Solidity: function isOperatorVaultRegistered(address vault) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsOperatorVaultRegistered(opts *bind.CallOpts, vault common.Address) (bool, error) ⋮---- // IsOperatorVaultRegistered0 is a free data retrieval call binding the contract method 0x669fa8c7. ⋮---- // Solidity: function isOperatorVaultRegistered(address operator, address vault) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsOperatorVaultRegistered0(opts *bind.CallOpts, operator common.Address, vault common.Address) (bool, error) ⋮---- // IsOperatorVaultRegisteredAt is a free data retrieval call binding the contract method 0xdae8f803. ⋮---- // Solidity: function isOperatorVaultRegisteredAt(address operator, address vault, uint48 timestamp) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsOperatorVaultRegisteredAt(opts *bind.CallOpts, operator common.Address, vault common.Address, timestamp *big.Int) (bool, error) ⋮---- // IsOperatorVaultRegisteredAt0 is a free data retrieval call binding the contract method 0xf6c011de. ⋮---- // Solidity: function isOperatorVaultRegisteredAt(address vault, uint48 timestamp) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsOperatorVaultRegisteredAt0(opts *bind.CallOpts, vault common.Address, timestamp *big.Int) (bool, error) ⋮---- // IsSharedVaultRegistered is a free data retrieval call binding the contract method 0x9a1ebee9. ⋮---- // Solidity: function isSharedVaultRegistered(address vault) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsSharedVaultRegistered(opts *bind.CallOpts, vault common.Address) (bool, error) ⋮---- // IsSharedVaultRegisteredAt is a free data retrieval call binding the contract method 0xe66e1ed2. ⋮---- // Solidity: function isSharedVaultRegisteredAt(address vault, uint48 timestamp) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsSharedVaultRegisteredAt(opts *bind.CallOpts, vault common.Address, timestamp *big.Int) (bool, error) ⋮---- // IsTokenRegistered is a free data retrieval call binding the contract method 0x26aa101f. ⋮---- // Solidity: function isTokenRegistered(address token) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsTokenRegistered(opts *bind.CallOpts, token common.Address) (bool, error) ⋮---- // IsTokenRegisteredAt is a free data retrieval call binding the contract method 0x6a496108. ⋮---- // Solidity: function isTokenRegisteredAt(address token, uint48 timestamp) view returns(bool) func (_IVotingPowerProvider *IVotingPowerProviderCaller) IsTokenRegisteredAt(opts *bind.CallOpts, token common.Address, timestamp *big.Int) (bool, error) ⋮---- // Nonces is a free data retrieval call binding the contract method 0x7ecebe00. ⋮---- // Solidity: function nonces(address owner) view returns(uint256) func (_IVotingPowerProvider *IVotingPowerProviderCaller) Nonces(opts *bind.CallOpts, owner common.Address) (*big.Int, error) ⋮---- // StakeToVotingPower is a free data retrieval call binding the contract method 0x039b8dd0. ⋮---- // Solidity: function stakeToVotingPower(address vault, uint256 stake, bytes extraData) view returns(uint256 power) func (_IVotingPowerProvider *IVotingPowerProviderCaller) StakeToVotingPower(opts *bind.CallOpts, vault common.Address, stake *big.Int, extraData []byte) (*big.Int, error) ⋮---- // StakeToVotingPowerAt is a free data retrieval call binding the contract method 0x52936362. ⋮---- // Solidity: function stakeToVotingPowerAt(address vault, uint256 stake, bytes extraData, uint48 timestamp) view returns(uint256 power) func (_IVotingPowerProvider *IVotingPowerProviderCaller) StakeToVotingPowerAt(opts *bind.CallOpts, vault common.Address, stake *big.Int, extraData []byte, timestamp *big.Int) (*big.Int, error) ⋮---- // InvalidateOldSignatures is a paid mutator transaction binding the contract method 0x622e4dba. ⋮---- // Solidity: function invalidateOldSignatures() returns() func (_IVotingPowerProvider *IVotingPowerProviderTransactor) InvalidateOldSignatures(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // Multicall is a paid mutator transaction binding the contract method 0xac9650d8. ⋮---- // Solidity: function multicall(bytes[] data) returns(bytes[] results) func (_IVotingPowerProvider *IVotingPowerProviderTransactor) Multicall(opts *bind.TransactOpts, data [][]byte) (*types.Transaction, error) ⋮---- // RegisterOperator is a paid mutator transaction binding the contract method 0x2acde098. ⋮---- // Solidity: function registerOperator() returns() func (_IVotingPowerProvider *IVotingPowerProviderTransactor) RegisterOperator(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // RegisterOperatorWithSignature is a paid mutator transaction binding the contract method 0xeb5e940d. ⋮---- // Solidity: function registerOperatorWithSignature(address operator, bytes signature) returns() func (_IVotingPowerProvider *IVotingPowerProviderTransactor) RegisterOperatorWithSignature(opts *bind.TransactOpts, operator common.Address, signature []byte) (*types.Transaction, error) ⋮---- // StaticDelegateCall is a paid mutator transaction binding the contract method 0x9f86fd85. ⋮---- // Solidity: function staticDelegateCall(address target, bytes data) returns() func (_IVotingPowerProvider *IVotingPowerProviderTransactor) StaticDelegateCall(opts *bind.TransactOpts, target common.Address, data []byte) (*types.Transaction, error) ⋮---- // UnregisterOperator is a paid mutator transaction binding the contract method 0xa876b89a. ⋮---- // Solidity: function unregisterOperator() returns() func (_IVotingPowerProvider *IVotingPowerProviderTransactor) UnregisterOperator(opts *bind.TransactOpts) (*types.Transaction, error) ⋮---- // UnregisterOperatorWithSignature is a paid mutator transaction binding the contract method 0xf96d1946. ⋮---- // Solidity: function unregisterOperatorWithSignature(address operator, bytes signature) returns() func (_IVotingPowerProvider *IVotingPowerProviderTransactor) UnregisterOperatorWithSignature(opts *bind.TransactOpts, operator common.Address, signature []byte) (*types.Transaction, error) ⋮---- // IVotingPowerProviderEIP712DomainChangedIterator is returned from FilterEIP712DomainChanged and is used to iterate over the raw logs and unpacked data for EIP712DomainChanged events raised by the IVotingPowerProvider contract. type IVotingPowerProviderEIP712DomainChangedIterator struct { Event *IVotingPowerProviderEIP712DomainChanged // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderEIP712DomainChanged // Event containing the contract specifics and raw log ⋮---- contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data ⋮---- logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration ⋮---- // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. func (it *IVotingPowerProviderEIP712DomainChangedIterator) Next() bool ⋮---- // If the iterator failed, stop iterating ⋮---- // If the iterator completed, deliver directly whatever's available ⋮---- // Iterator still in progress, wait for either a data or an error event ⋮---- // Error returns any retrieval or parsing error occurred during filtering. func (it *IVotingPowerProviderEIP712DomainChangedIterator) Error() error ⋮---- // Close terminates the iteration process, releasing any pending underlying // resources. func (it *IVotingPowerProviderEIP712DomainChangedIterator) Close() error ⋮---- // IVotingPowerProviderEIP712DomainChanged represents a EIP712DomainChanged event raised by the IVotingPowerProvider contract. type IVotingPowerProviderEIP712DomainChanged struct { Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterEIP712DomainChanged is a free log retrieval operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. ⋮---- // Solidity: event EIP712DomainChanged() func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterEIP712DomainChanged(opts *bind.FilterOpts) (*IVotingPowerProviderEIP712DomainChangedIterator, error) ⋮---- // WatchEIP712DomainChanged is a free log subscription operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchEIP712DomainChanged(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderEIP712DomainChanged) (event.Subscription, error) ⋮---- // New log arrived, parse the event and forward to the user ⋮---- // ParseEIP712DomainChanged is a log parse operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseEIP712DomainChanged(log types.Log) (*IVotingPowerProviderEIP712DomainChanged, error) ⋮---- // IVotingPowerProviderInitEIP712Iterator is returned from FilterInitEIP712 and is used to iterate over the raw logs and unpacked data for InitEIP712 events raised by the IVotingPowerProvider contract. type IVotingPowerProviderInitEIP712Iterator struct { Event *IVotingPowerProviderInitEIP712 // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderInitEIP712 // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderInitEIP712 represents a InitEIP712 event raised by the IVotingPowerProvider contract. type IVotingPowerProviderInitEIP712 struct { Name string Version string Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterInitEIP712 is a free log retrieval operation binding the contract event 0x98790bb3996c909e6f4279ffabdfe70fa6c0d49b8fa04656d6161decfc442e0a. ⋮---- // Solidity: event InitEIP712(string name, string version) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterInitEIP712(opts *bind.FilterOpts) (*IVotingPowerProviderInitEIP712Iterator, error) ⋮---- // WatchInitEIP712 is a free log subscription operation binding the contract event 0x98790bb3996c909e6f4279ffabdfe70fa6c0d49b8fa04656d6161decfc442e0a. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchInitEIP712(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderInitEIP712) (event.Subscription, error) ⋮---- // ParseInitEIP712 is a log parse operation binding the contract event 0x98790bb3996c909e6f4279ffabdfe70fa6c0d49b8fa04656d6161decfc442e0a. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseInitEIP712(log types.Log) (*IVotingPowerProviderInitEIP712, error) ⋮---- // IVotingPowerProviderInitSubnetworkIterator is returned from FilterInitSubnetwork and is used to iterate over the raw logs and unpacked data for InitSubnetwork events raised by the IVotingPowerProvider contract. type IVotingPowerProviderInitSubnetworkIterator struct { Event *IVotingPowerProviderInitSubnetwork // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderInitSubnetwork // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderInitSubnetwork represents a InitSubnetwork event raised by the IVotingPowerProvider contract. type IVotingPowerProviderInitSubnetwork struct { Network common.Address SubnetworkId *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterInitSubnetwork is a free log retrieval operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- // Solidity: event InitSubnetwork(address network, uint96 subnetworkId) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterInitSubnetwork(opts *bind.FilterOpts) (*IVotingPowerProviderInitSubnetworkIterator, error) ⋮---- // WatchInitSubnetwork is a free log subscription operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchInitSubnetwork(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderInitSubnetwork) (event.Subscription, error) ⋮---- // ParseInitSubnetwork is a log parse operation binding the contract event 0x469c2e982e7d76d34cf5d1e72abee29749bb9971942c180e9023cea09f5f8e83. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseInitSubnetwork(log types.Log) (*IVotingPowerProviderInitSubnetwork, error) ⋮---- // IVotingPowerProviderInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the IVotingPowerProvider contract. type IVotingPowerProviderInitializedIterator struct { Event *IVotingPowerProviderInitialized // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderInitialized // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderInitialized represents a Initialized event raised by the IVotingPowerProvider contract. type IVotingPowerProviderInitialized struct { Version uint64 Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- // Solidity: event Initialized(uint64 version) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterInitialized(opts *bind.FilterOpts) (*IVotingPowerProviderInitializedIterator, error) ⋮---- // WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderInitialized) (event.Subscription, error) ⋮---- // ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseInitialized(log types.Log) (*IVotingPowerProviderInitialized, error) ⋮---- // IVotingPowerProviderRegisterOperatorIterator is returned from FilterRegisterOperator and is used to iterate over the raw logs and unpacked data for RegisterOperator events raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterOperatorIterator struct { Event *IVotingPowerProviderRegisterOperator // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderRegisterOperator // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderRegisterOperator represents a RegisterOperator event raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterOperator struct { Operator common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterRegisterOperator is a free log retrieval operation binding the contract event 0xdfd9e0392912bee97777ec588d2ff7ae010ea24202d153a0bff1b30aed643daa. ⋮---- // Solidity: event RegisterOperator(address indexed operator) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterRegisterOperator(opts *bind.FilterOpts, operator []common.Address) (*IVotingPowerProviderRegisterOperatorIterator, error) ⋮---- var operatorRule []interface{} ⋮---- // WatchRegisterOperator is a free log subscription operation binding the contract event 0xdfd9e0392912bee97777ec588d2ff7ae010ea24202d153a0bff1b30aed643daa. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchRegisterOperator(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderRegisterOperator, operator []common.Address) (event.Subscription, error) ⋮---- // ParseRegisterOperator is a log parse operation binding the contract event 0xdfd9e0392912bee97777ec588d2ff7ae010ea24202d153a0bff1b30aed643daa. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseRegisterOperator(log types.Log) (*IVotingPowerProviderRegisterOperator, error) ⋮---- // IVotingPowerProviderRegisterOperatorVaultIterator is returned from FilterRegisterOperatorVault and is used to iterate over the raw logs and unpacked data for RegisterOperatorVault events raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterOperatorVaultIterator struct { Event *IVotingPowerProviderRegisterOperatorVault // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderRegisterOperatorVault // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderRegisterOperatorVault represents a RegisterOperatorVault event raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterOperatorVault struct { Operator common.Address Vault common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterRegisterOperatorVault is a free log retrieval operation binding the contract event 0x6db8d1ad7903329250db9b7a653d3aa009807c85daa2281a75e063808bceefdc. ⋮---- // Solidity: event RegisterOperatorVault(address indexed operator, address indexed vault) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterRegisterOperatorVault(opts *bind.FilterOpts, operator []common.Address, vault []common.Address) (*IVotingPowerProviderRegisterOperatorVaultIterator, error) ⋮---- var vaultRule []interface{} ⋮---- // WatchRegisterOperatorVault is a free log subscription operation binding the contract event 0x6db8d1ad7903329250db9b7a653d3aa009807c85daa2281a75e063808bceefdc. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchRegisterOperatorVault(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderRegisterOperatorVault, operator []common.Address, vault []common.Address) (event.Subscription, error) ⋮---- // ParseRegisterOperatorVault is a log parse operation binding the contract event 0x6db8d1ad7903329250db9b7a653d3aa009807c85daa2281a75e063808bceefdc. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseRegisterOperatorVault(log types.Log) (*IVotingPowerProviderRegisterOperatorVault, error) ⋮---- // IVotingPowerProviderRegisterSharedVaultIterator is returned from FilterRegisterSharedVault and is used to iterate over the raw logs and unpacked data for RegisterSharedVault events raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterSharedVaultIterator struct { Event *IVotingPowerProviderRegisterSharedVault // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderRegisterSharedVault // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderRegisterSharedVault represents a RegisterSharedVault event raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterSharedVault struct { Vault common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterRegisterSharedVault is a free log retrieval operation binding the contract event 0x99528065e654d6d4b95447d6787148a84b7e98a95e752784e99da056b403b25c. ⋮---- // Solidity: event RegisterSharedVault(address indexed vault) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterRegisterSharedVault(opts *bind.FilterOpts, vault []common.Address) (*IVotingPowerProviderRegisterSharedVaultIterator, error) ⋮---- // WatchRegisterSharedVault is a free log subscription operation binding the contract event 0x99528065e654d6d4b95447d6787148a84b7e98a95e752784e99da056b403b25c. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchRegisterSharedVault(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderRegisterSharedVault, vault []common.Address) (event.Subscription, error) ⋮---- // ParseRegisterSharedVault is a log parse operation binding the contract event 0x99528065e654d6d4b95447d6787148a84b7e98a95e752784e99da056b403b25c. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseRegisterSharedVault(log types.Log) (*IVotingPowerProviderRegisterSharedVault, error) ⋮---- // IVotingPowerProviderRegisterTokenIterator is returned from FilterRegisterToken and is used to iterate over the raw logs and unpacked data for RegisterToken events raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterTokenIterator struct { Event *IVotingPowerProviderRegisterToken // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderRegisterToken // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderRegisterToken represents a RegisterToken event raised by the IVotingPowerProvider contract. type IVotingPowerProviderRegisterToken struct { Token common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterRegisterToken is a free log retrieval operation binding the contract event 0xf7fe8023cb2e36bde1d59a88ac5763a8c11be6d25e6819f71bb7e23e5bf0dc16. ⋮---- // Solidity: event RegisterToken(address indexed token) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterRegisterToken(opts *bind.FilterOpts, token []common.Address) (*IVotingPowerProviderRegisterTokenIterator, error) ⋮---- var tokenRule []interface{} ⋮---- // WatchRegisterToken is a free log subscription operation binding the contract event 0xf7fe8023cb2e36bde1d59a88ac5763a8c11be6d25e6819f71bb7e23e5bf0dc16. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchRegisterToken(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderRegisterToken, token []common.Address) (event.Subscription, error) ⋮---- // ParseRegisterToken is a log parse operation binding the contract event 0xf7fe8023cb2e36bde1d59a88ac5763a8c11be6d25e6819f71bb7e23e5bf0dc16. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseRegisterToken(log types.Log) (*IVotingPowerProviderRegisterToken, error) ⋮---- // IVotingPowerProviderSetSlashingDataIterator is returned from FilterSetSlashingData and is used to iterate over the raw logs and unpacked data for SetSlashingData events raised by the IVotingPowerProvider contract. type IVotingPowerProviderSetSlashingDataIterator struct { Event *IVotingPowerProviderSetSlashingData // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderSetSlashingData // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderSetSlashingData represents a SetSlashingData event raised by the IVotingPowerProvider contract. type IVotingPowerProviderSetSlashingData struct { RequireSlasher bool MinVaultEpochDuration *big.Int Raw types.Log // Blockchain specific contextual infos } ⋮---- Raw types.Log // Blockchain specific contextual infos ⋮---- // FilterSetSlashingData is a free log retrieval operation binding the contract event 0xfa31c1b97ed96532301949e5fd34d2e059500b0de599195245ddf8fbfbb36db0. ⋮---- // Solidity: event SetSlashingData(bool requireSlasher, uint48 minVaultEpochDuration) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterSetSlashingData(opts *bind.FilterOpts) (*IVotingPowerProviderSetSlashingDataIterator, error) ⋮---- // WatchSetSlashingData is a free log subscription operation binding the contract event 0xfa31c1b97ed96532301949e5fd34d2e059500b0de599195245ddf8fbfbb36db0. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchSetSlashingData(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderSetSlashingData) (event.Subscription, error) ⋮---- // ParseSetSlashingData is a log parse operation binding the contract event 0xfa31c1b97ed96532301949e5fd34d2e059500b0de599195245ddf8fbfbb36db0. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseSetSlashingData(log types.Log) (*IVotingPowerProviderSetSlashingData, error) ⋮---- // IVotingPowerProviderUnregisterOperatorIterator is returned from FilterUnregisterOperator and is used to iterate over the raw logs and unpacked data for UnregisterOperator events raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterOperatorIterator struct { Event *IVotingPowerProviderUnregisterOperator // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderUnregisterOperator // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderUnregisterOperator represents a UnregisterOperator event raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterOperator struct { Operator common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterUnregisterOperator is a free log retrieval operation binding the contract event 0xd1b48d1e49885298af5dc8adc7777836ef804b38af88eabf4e079c04ee1538a7. ⋮---- // Solidity: event UnregisterOperator(address indexed operator) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterUnregisterOperator(opts *bind.FilterOpts, operator []common.Address) (*IVotingPowerProviderUnregisterOperatorIterator, error) ⋮---- // WatchUnregisterOperator is a free log subscription operation binding the contract event 0xd1b48d1e49885298af5dc8adc7777836ef804b38af88eabf4e079c04ee1538a7. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchUnregisterOperator(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderUnregisterOperator, operator []common.Address) (event.Subscription, error) ⋮---- // ParseUnregisterOperator is a log parse operation binding the contract event 0xd1b48d1e49885298af5dc8adc7777836ef804b38af88eabf4e079c04ee1538a7. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseUnregisterOperator(log types.Log) (*IVotingPowerProviderUnregisterOperator, error) ⋮---- // IVotingPowerProviderUnregisterOperatorVaultIterator is returned from FilterUnregisterOperatorVault and is used to iterate over the raw logs and unpacked data for UnregisterOperatorVault events raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterOperatorVaultIterator struct { Event *IVotingPowerProviderUnregisterOperatorVault // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderUnregisterOperatorVault // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderUnregisterOperatorVault represents a UnregisterOperatorVault event raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterOperatorVault struct { Operator common.Address Vault common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterUnregisterOperatorVault is a free log retrieval operation binding the contract event 0x3455b6128675eff843703027879cc9b52d6ce684ddc6077cbe0d191ad98b255e. ⋮---- // Solidity: event UnregisterOperatorVault(address indexed operator, address indexed vault) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterUnregisterOperatorVault(opts *bind.FilterOpts, operator []common.Address, vault []common.Address) (*IVotingPowerProviderUnregisterOperatorVaultIterator, error) ⋮---- // WatchUnregisterOperatorVault is a free log subscription operation binding the contract event 0x3455b6128675eff843703027879cc9b52d6ce684ddc6077cbe0d191ad98b255e. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchUnregisterOperatorVault(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderUnregisterOperatorVault, operator []common.Address, vault []common.Address) (event.Subscription, error) ⋮---- // ParseUnregisterOperatorVault is a log parse operation binding the contract event 0x3455b6128675eff843703027879cc9b52d6ce684ddc6077cbe0d191ad98b255e. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseUnregisterOperatorVault(log types.Log) (*IVotingPowerProviderUnregisterOperatorVault, error) ⋮---- // IVotingPowerProviderUnregisterSharedVaultIterator is returned from FilterUnregisterSharedVault and is used to iterate over the raw logs and unpacked data for UnregisterSharedVault events raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterSharedVaultIterator struct { Event *IVotingPowerProviderUnregisterSharedVault // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderUnregisterSharedVault // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderUnregisterSharedVault represents a UnregisterSharedVault event raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterSharedVault struct { Vault common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterUnregisterSharedVault is a free log retrieval operation binding the contract event 0xead83f8482d0fa5de2b5c28fb39ee288392076d150db7020e10a92954aea82ee. ⋮---- // Solidity: event UnregisterSharedVault(address indexed vault) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterUnregisterSharedVault(opts *bind.FilterOpts, vault []common.Address) (*IVotingPowerProviderUnregisterSharedVaultIterator, error) ⋮---- // WatchUnregisterSharedVault is a free log subscription operation binding the contract event 0xead83f8482d0fa5de2b5c28fb39ee288392076d150db7020e10a92954aea82ee. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchUnregisterSharedVault(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderUnregisterSharedVault, vault []common.Address) (event.Subscription, error) ⋮---- // ParseUnregisterSharedVault is a log parse operation binding the contract event 0xead83f8482d0fa5de2b5c28fb39ee288392076d150db7020e10a92954aea82ee. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseUnregisterSharedVault(log types.Log) (*IVotingPowerProviderUnregisterSharedVault, error) ⋮---- // IVotingPowerProviderUnregisterTokenIterator is returned from FilterUnregisterToken and is used to iterate over the raw logs and unpacked data for UnregisterToken events raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterTokenIterator struct { Event *IVotingPowerProviderUnregisterToken // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } ⋮---- Event *IVotingPowerProviderUnregisterToken // Event containing the contract specifics and raw log ⋮---- // IVotingPowerProviderUnregisterToken represents a UnregisterToken event raised by the IVotingPowerProvider contract. type IVotingPowerProviderUnregisterToken struct { Token common.Address Raw types.Log // Blockchain specific contextual infos } ⋮---- // FilterUnregisterToken is a free log retrieval operation binding the contract event 0xca2a890939276223a9122217752c67608466faee388aff53f077d00a186a389b. ⋮---- // Solidity: event UnregisterToken(address indexed token) func (_IVotingPowerProvider *IVotingPowerProviderFilterer) FilterUnregisterToken(opts *bind.FilterOpts, token []common.Address) (*IVotingPowerProviderUnregisterTokenIterator, error) ⋮---- // WatchUnregisterToken is a free log subscription operation binding the contract event 0xca2a890939276223a9122217752c67608466faee388aff53f077d00a186a389b. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) WatchUnregisterToken(opts *bind.WatchOpts, sink chan<- *IVotingPowerProviderUnregisterToken, token []common.Address) (event.Subscription, error) ⋮---- // ParseUnregisterToken is a log parse operation binding the contract event 0xca2a890939276223a9122217752c67608466faee388aff53f077d00a186a389b. ⋮---- func (_IVotingPowerProvider *IVotingPowerProviderFilterer) ParseUnregisterToken(log types.Log) (*IVotingPowerProviderUnregisterToken, error) ```` ## File: symbiotic/client/evm/mocks/eth.go ````go // Code generated by MockGen. DO NOT EDIT. // Source: github.com/symbioticfi/relay/symbiotic/client/evm (interfaces: IEvmClient,conn,metrics,keyProvider,driverContract) // // Generated by this command: ⋮---- // mockgen -destination=mocks/eth.go -package=mocks github.com/symbioticfi/relay/symbiotic/client/evm IEvmClient,conn,metrics,keyProvider,driverContract ⋮---- // Package mocks is a generated GoMock package. package mocks ⋮---- import ( context "context" big "math/big" reflect "reflect" time "time" ethereum "github.com/ethereum/go-ethereum" bind "github.com/ethereum/go-ethereum/accounts/abi/bind" common "github.com/ethereum/go-ethereum/common" types "github.com/ethereum/go-ethereum/core/types" gen "github.com/symbioticfi/relay/symbiotic/client/evm/gen" entity "github.com/symbioticfi/relay/symbiotic/entity" crypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" gomock "go.uber.org/mock/gomock" ) ⋮---- context "context" big "math/big" reflect "reflect" time "time" ⋮---- ethereum "github.com/ethereum/go-ethereum" bind "github.com/ethereum/go-ethereum/accounts/abi/bind" common "github.com/ethereum/go-ethereum/common" types "github.com/ethereum/go-ethereum/core/types" gen "github.com/symbioticfi/relay/symbiotic/client/evm/gen" entity "github.com/symbioticfi/relay/symbiotic/entity" crypto "github.com/symbioticfi/relay/symbiotic/usecase/crypto" gomock "go.uber.org/mock/gomock" ⋮---- // MockIEvmClient is a mock of IEvmClient interface. type MockIEvmClient struct { ctrl *gomock.Controller recorder *MockIEvmClientMockRecorder isgomock struct{} ⋮---- // MockIEvmClientMockRecorder is the mock recorder for MockIEvmClient. type MockIEvmClientMockRecorder struct { mock *MockIEvmClient } ⋮---- // NewMockIEvmClient creates a new mock instance. func NewMockIEvmClient(ctrl *gomock.Controller) *MockIEvmClient ⋮---- // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockIEvmClient) EXPECT() *MockIEvmClientMockRecorder ⋮---- // CommitValsetHeader mocks base method. func (m *MockIEvmClient) CommitValsetHeader(ctx context.Context, addr entity.CrossChainAddress, header entity.ValidatorSetHeader, extraData []entity.ExtraData, proof []byte) (entity.TxResult, error) ⋮---- // CommitValsetHeader indicates an expected call of CommitValsetHeader. ⋮---- // GetCaptureTimestampFromValsetHeaderAt mocks base method. func (m *MockIEvmClient) GetCaptureTimestampFromValsetHeaderAt(ctx context.Context, addr entity.CrossChainAddress, epoch entity.Epoch) (uint64, error) ⋮---- // GetCaptureTimestampFromValsetHeaderAt indicates an expected call of GetCaptureTimestampFromValsetHeaderAt. ⋮---- // GetChains mocks base method. func (m *MockIEvmClient) GetChains() []uint64 ⋮---- // GetChains indicates an expected call of GetChains. ⋮---- // GetConfig mocks base method. func (m *MockIEvmClient) GetConfig(ctx context.Context, timestamp entity.Timestamp, epoch entity.Epoch) (entity.NetworkConfig, error) ⋮---- // GetConfig indicates an expected call of GetConfig. ⋮---- // GetCurrentEpoch mocks base method. func (m *MockIEvmClient) GetCurrentEpoch(ctx context.Context) (entity.Epoch, error) ⋮---- // GetCurrentEpoch indicates an expected call of GetCurrentEpoch. ⋮---- // GetCurrentEpochDuration mocks base method. func (m *MockIEvmClient) GetCurrentEpochDuration(ctx context.Context) (uint64, error) ⋮---- // GetCurrentEpochDuration indicates an expected call of GetCurrentEpochDuration. ⋮---- // GetEip712Domain mocks base method. func (m *MockIEvmClient) GetEip712Domain(ctx context.Context, addr entity.CrossChainAddress) (entity.Eip712Domain, error) ⋮---- // GetEip712Domain indicates an expected call of GetEip712Domain. ⋮---- // GetEpochDuration mocks base method. func (m *MockIEvmClient) GetEpochDuration(ctx context.Context, epoch entity.Epoch) (uint64, error) ⋮---- // GetEpochDuration indicates an expected call of GetEpochDuration. ⋮---- // GetEpochStart mocks base method. func (m *MockIEvmClient) GetEpochStart(ctx context.Context, epoch entity.Epoch) (entity.Timestamp, error) ⋮---- // GetEpochStart indicates an expected call of GetEpochStart. ⋮---- // GetHeaderHash mocks base method. func (m *MockIEvmClient) GetHeaderHash(ctx context.Context, addr entity.CrossChainAddress) (common.Hash, error) ⋮---- // GetHeaderHash indicates an expected call of GetHeaderHash. ⋮---- // GetHeaderHashAt mocks base method. func (m *MockIEvmClient) GetHeaderHashAt(ctx context.Context, addr entity.CrossChainAddress, epoch entity.Epoch) (common.Hash, error) ⋮---- // GetHeaderHashAt indicates an expected call of GetHeaderHashAt. ⋮---- // GetKeys mocks base method. func (m *MockIEvmClient) GetKeys(ctx context.Context, address entity.CrossChainAddress, timestamp entity.Timestamp) ([]entity.OperatorWithKeys, error) ⋮---- // GetKeys indicates an expected call of GetKeys. ⋮---- // GetLastCommittedHeaderEpoch mocks base method. func (m *MockIEvmClient) GetLastCommittedHeaderEpoch(ctx context.Context, addr entity.CrossChainAddress, evmOptions ...entity.EVMOption) (entity.Epoch, error) ⋮---- // GetLastCommittedHeaderEpoch indicates an expected call of GetLastCommittedHeaderEpoch. ⋮---- // GetNetworkAddress mocks base method. func (m *MockIEvmClient) GetNetworkAddress(ctx context.Context) (common.Address, error) ⋮---- // GetNetworkAddress indicates an expected call of GetNetworkAddress. ⋮---- // GetOperatorNonce mocks base method. func (m *MockIEvmClient) GetOperatorNonce(ctx context.Context, votingPowerProvider entity.CrossChainAddress, operator common.Address) (*big.Int, error) ⋮---- // GetOperatorNonce indicates an expected call of GetOperatorNonce. ⋮---- // GetSubnetwork mocks base method. func (m *MockIEvmClient) GetSubnetwork(ctx context.Context) (common.Hash, error) ⋮---- // GetSubnetwork indicates an expected call of GetSubnetwork. ⋮---- // GetValSetHeader mocks base method. func (m *MockIEvmClient) GetValSetHeader(ctx context.Context, addr entity.CrossChainAddress) (entity.ValidatorSetHeader, error) ⋮---- // GetValSetHeader indicates an expected call of GetValSetHeader. ⋮---- // GetValSetHeaderAt mocks base method. func (m *MockIEvmClient) GetValSetHeaderAt(ctx context.Context, addr entity.CrossChainAddress, epoch entity.Epoch) (entity.ValidatorSetHeader, error) ⋮---- // GetValSetHeaderAt indicates an expected call of GetValSetHeaderAt. ⋮---- // GetVotingPowerProviderEip712Domain mocks base method. func (m *MockIEvmClient) GetVotingPowerProviderEip712Domain(ctx context.Context, addr entity.CrossChainAddress) (entity.Eip712Domain, error) ⋮---- // GetVotingPowerProviderEip712Domain indicates an expected call of GetVotingPowerProviderEip712Domain. ⋮---- // GetVotingPowers mocks base method. func (m *MockIEvmClient) GetVotingPowers(ctx context.Context, address entity.CrossChainAddress, timestamp entity.Timestamp) ([]entity.OperatorVotingPower, error) ⋮---- // GetVotingPowers indicates an expected call of GetVotingPowers. ⋮---- // InvalidateOldSignatures mocks base method. func (m *MockIEvmClient) InvalidateOldSignatures(ctx context.Context, addr entity.CrossChainAddress) (entity.TxResult, error) ⋮---- // InvalidateOldSignatures indicates an expected call of InvalidateOldSignatures. ⋮---- // IsValsetHeaderCommittedAt mocks base method. func (m *MockIEvmClient) IsValsetHeaderCommittedAt(ctx context.Context, addr entity.CrossChainAddress, epoch entity.Epoch, opts ...entity.EVMOption) (bool, error) ⋮---- // IsValsetHeaderCommittedAt indicates an expected call of IsValsetHeaderCommittedAt. ⋮---- // IsValsetHeaderCommittedAtEpochs mocks base method. func (m *MockIEvmClient) IsValsetHeaderCommittedAtEpochs(ctx context.Context, addr entity.CrossChainAddress, epochs []entity.Epoch) ([]bool, error) ⋮---- // IsValsetHeaderCommittedAtEpochs indicates an expected call of IsValsetHeaderCommittedAtEpochs. ⋮---- // RegisterKey mocks base method. func (m *MockIEvmClient) RegisterKey(ctx context.Context, addr entity.CrossChainAddress, keyTag entity.KeyTag, key entity.CompactPublicKey, signature entity.RawSignature, extraData []byte) (entity.TxResult, error) ⋮---- // RegisterKey indicates an expected call of RegisterKey. ⋮---- // RegisterOperator mocks base method. func (m *MockIEvmClient) RegisterOperator(ctx context.Context, addr entity.CrossChainAddress) (entity.TxResult, error) ⋮---- // RegisterOperator indicates an expected call of RegisterOperator. ⋮---- // RegisterOperatorVotingPowerProvider mocks base method. func (m *MockIEvmClient) RegisterOperatorVotingPowerProvider(ctx context.Context, addr entity.CrossChainAddress) (entity.TxResult, error) ⋮---- // RegisterOperatorVotingPowerProvider indicates an expected call of RegisterOperatorVotingPowerProvider. ⋮---- // SetGenesis mocks base method. func (m *MockIEvmClient) SetGenesis(ctx context.Context, addr entity.CrossChainAddress, header entity.ValidatorSetHeader, extraData []entity.ExtraData) (entity.TxResult, error) ⋮---- // SetGenesis indicates an expected call of SetGenesis. ⋮---- // UnregisterOperatorVotingPowerProvider mocks base method. func (m *MockIEvmClient) UnregisterOperatorVotingPowerProvider(ctx context.Context, addr entity.CrossChainAddress) (entity.TxResult, error) ⋮---- // UnregisterOperatorVotingPowerProvider indicates an expected call of UnregisterOperatorVotingPowerProvider. ⋮---- // VerifyQuorumSig mocks base method. func (m *MockIEvmClient) VerifyQuorumSig(ctx context.Context, addr entity.CrossChainAddress, epoch entity.Epoch, message []byte, keyTag entity.KeyTag, threshold *big.Int, proof []byte) (bool, error) ⋮---- // VerifyQuorumSig indicates an expected call of VerifyQuorumSig. ⋮---- // Mockconn is a mock of conn interface. type Mockconn struct { ctrl *gomock.Controller recorder *MockconnMockRecorder isgomock struct{} ⋮---- // MockconnMockRecorder is the mock recorder for Mockconn. type MockconnMockRecorder struct { mock *Mockconn } ⋮---- // NewMockconn creates a new mock instance. func NewMockconn(ctrl *gomock.Controller) *Mockconn ⋮---- // CallContract mocks base method. func (m *Mockconn) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) ⋮---- // CallContract indicates an expected call of CallContract. ⋮---- // CodeAt mocks base method. func (m *Mockconn) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) ⋮---- // CodeAt indicates an expected call of CodeAt. ⋮---- // EstimateGas mocks base method. func (m *Mockconn) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) ⋮---- // EstimateGas indicates an expected call of EstimateGas. ⋮---- // FilterLogs mocks base method. func (m *Mockconn) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) ⋮---- // FilterLogs indicates an expected call of FilterLogs. ⋮---- // HeaderByNumber mocks base method. func (m *Mockconn) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) ⋮---- // HeaderByNumber indicates an expected call of HeaderByNumber. ⋮---- // PendingCodeAt mocks base method. func (m *Mockconn) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) ⋮---- // PendingCodeAt indicates an expected call of PendingCodeAt. ⋮---- // PendingNonceAt mocks base method. func (m *Mockconn) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) ⋮---- // PendingNonceAt indicates an expected call of PendingNonceAt. ⋮---- // SendTransaction mocks base method. func (m *Mockconn) SendTransaction(ctx context.Context, tx *types.Transaction) error ⋮---- // SendTransaction indicates an expected call of SendTransaction. ⋮---- // SubscribeFilterLogs mocks base method. func (m *Mockconn) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) ⋮---- // SubscribeFilterLogs indicates an expected call of SubscribeFilterLogs. ⋮---- // SuggestGasPrice mocks base method. func (m *Mockconn) SuggestGasPrice(ctx context.Context) (*big.Int, error) ⋮---- // SuggestGasPrice indicates an expected call of SuggestGasPrice. ⋮---- // SuggestGasTipCap mocks base method. func (m *Mockconn) SuggestGasTipCap(ctx context.Context) (*big.Int, error) ⋮---- // SuggestGasTipCap indicates an expected call of SuggestGasTipCap. ⋮---- // TransactionReceipt mocks base method. func (m *Mockconn) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) ⋮---- // TransactionReceipt indicates an expected call of TransactionReceipt. ⋮---- // Mockmetrics is a mock of metrics interface. type Mockmetrics struct { ctrl *gomock.Controller recorder *MockmetricsMockRecorder isgomock struct{} ⋮---- // MockmetricsMockRecorder is the mock recorder for Mockmetrics. type MockmetricsMockRecorder struct { mock *Mockmetrics } ⋮---- // NewMockmetrics creates a new mock instance. func NewMockmetrics(ctrl *gomock.Controller) *Mockmetrics ⋮---- // ObserveCommitValsetHeaderParams mocks base method. func (m *Mockmetrics) ObserveCommitValsetHeaderParams(chainID, gasUsed uint64, effectiveGasPrice *big.Int) ⋮---- // ObserveCommitValsetHeaderParams indicates an expected call of ObserveCommitValsetHeaderParams. ⋮---- // ObserveEVMMethodCall mocks base method. func (m *Mockmetrics) ObserveEVMMethodCall(method string, chainID uint64, status string, d time.Duration) ⋮---- // ObserveEVMMethodCall indicates an expected call of ObserveEVMMethodCall. ⋮---- // MockkeyProvider is a mock of keyProvider interface. type MockkeyProvider struct { ctrl *gomock.Controller recorder *MockkeyProviderMockRecorder isgomock struct{} ⋮---- // MockkeyProviderMockRecorder is the mock recorder for MockkeyProvider. type MockkeyProviderMockRecorder struct { mock *MockkeyProvider } ⋮---- // NewMockkeyProvider creates a new mock instance. func NewMockkeyProvider(ctrl *gomock.Controller) *MockkeyProvider ⋮---- // GetPrivateKeyByNamespaceTypeId mocks base method. func (m *MockkeyProvider) GetPrivateKeyByNamespaceTypeId(namespace string, keyType entity.KeyType, id int) (crypto.PrivateKey, error) ⋮---- // GetPrivateKeyByNamespaceTypeId indicates an expected call of GetPrivateKeyByNamespaceTypeId. ⋮---- // MockdriverContract is a mock of driverContract interface. type MockdriverContract struct { ctrl *gomock.Controller recorder *MockdriverContractMockRecorder isgomock struct{} ⋮---- // MockdriverContractMockRecorder is the mock recorder for MockdriverContract. type MockdriverContractMockRecorder struct { mock *MockdriverContract } ⋮---- // NewMockdriverContract creates a new mock instance. func NewMockdriverContract(ctrl *gomock.Controller) *MockdriverContract ⋮---- // GetConfigAt mocks base method. func (m *MockdriverContract) GetConfigAt(opts *bind.CallOpts, timestamp *big.Int) (gen.IValSetDriverConfig, error) ⋮---- // GetConfigAt indicates an expected call of GetConfigAt. ⋮---- // NETWORK mocks base method. func (m *MockdriverContract) NETWORK(opts *bind.CallOpts) (common.Address, error) ⋮---- // NETWORK indicates an expected call of NETWORK. ⋮---- // SUBNETWORK mocks base method. func (m *MockdriverContract) SUBNETWORK(opts *bind.CallOpts) ([32]byte, error) ⋮---- // SUBNETWORK indicates an expected call of SUBNETWORK. ```` ## File: symbiotic/client/evm/eth_commit_valset_test.go ````go package evm ⋮---- import ( "context" "crypto/ecdsa" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "crypto/ecdsa" "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type mockPrivateKey struct { key *ecdsa.PrivateKey } ⋮---- func (m *mockPrivateKey) Bytes() []byte ⋮---- func (m *mockPrivateKey) Sign(msg []byte) (symbiotic.RawSignature, symbiotic.MessageHash, error) ⋮---- func (m *mockPrivateKey) PublicKey() symbiotic.PublicKey ⋮---- func TestCommitValsetHeader_NoSettlementContract_ReturnsError(t *testing.T) ⋮---- func TestCommitValsetHeader_KeyProviderFails_ReturnsError(t *testing.T) ⋮---- func TestCommitValsetHeader_InvalidECDSAKey_ReturnsError(t *testing.T) ⋮---- func TestCommitValsetHeader_ContextTimeout_ReturnsError(t *testing.T) ⋮---- func TestCommitValsetHeader_InvalidChainID_ReturnsError(t *testing.T) ⋮---- func TestCommitValsetHeader_EmptyProof_HandlesCorrectly(t *testing.T) ⋮---- func TestCommitValsetHeader_EmptyExtraData_HandlesCorrectly(t *testing.T) ⋮---- func TestCommitValsetHeader_PartialHappyPath_ValidatesDataPreparation(t *testing.T) ```` ## File: symbiotic/client/evm/eth_commit_valset.go ````go package evm ⋮---- import ( "context" "log/slog" "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "log/slog" "math/big" "time" ⋮---- "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (e *Client) CommitValsetHeader( ctx context.Context, addr symbiotic.CrossChainAddress, header symbiotic.ValidatorSetHeader, extraData []symbiotic.ExtraData, proof []byte, ) (_ symbiotic.TxResult, err error) ```` ## File: symbiotic/client/evm/eth_operator_test.go ````go package evm ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestRegisterOperator_KeyProviderFails_ReturnsError(t *testing.T) ⋮---- func TestRegisterOperator_InvalidECDSAKey_ReturnsError(t *testing.T) ⋮---- func TestRegisterOperator_ContextTimeout_ReturnsError(t *testing.T) ⋮---- func TestRegisterOperator_NoOperatorRegistry_ReturnsError(t *testing.T) ⋮---- func TestRegisterKey_KeyProviderFails_ReturnsError(t *testing.T) ⋮---- func TestRegisterKey_InvalidECDSAKey_ReturnsError(t *testing.T) ⋮---- func TestRegisterKey_NoKeyRegistry_ReturnsError(t *testing.T) ⋮---- func TestRegisterKey_EmptyExtraData_HandlesCorrectly(t *testing.T) ⋮---- func TestRegisterOperatorVotingPowerProvider_KeyProviderFails_ReturnsError(t *testing.T) ⋮---- func TestRegisterOperatorVotingPowerProvider_InvalidECDSAKey_ReturnsError(t *testing.T) ⋮---- func TestRegisterOperatorVotingPowerProvider_NoVotingPowerProvider_ReturnsError(t *testing.T) ⋮---- func TestUnregisterOperatorVotingPowerProvider_KeyProviderFails_ReturnsError(t *testing.T) ⋮---- func TestUnregisterOperatorVotingPowerProvider_InvalidECDSAKey_ReturnsError(t *testing.T) ⋮---- func TestUnregisterOperatorVotingPowerProvider_NoVotingPowerProvider_ReturnsError(t *testing.T) ⋮---- func TestRegisterOperator_PartialHappyPath_ValidatesDataPreparation(t *testing.T) ⋮---- func TestInvalidateOldSignatures_KeyProviderFails_ReturnsError(t *testing.T) ⋮---- func TestInvalidateOldSignatures_InvalidECDSAKey_ReturnsError(t *testing.T) ⋮---- func TestInvalidateOldSignatures_NoVotingPowerProvider_ReturnsError(t *testing.T) ```` ## File: symbiotic/client/evm/eth_operator.go ````go package evm ⋮---- import ( "context" "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" "time" ⋮---- "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (e *Client) RegisterOperator( ctx context.Context, addr symbiotic.CrossChainAddress, ) (_ symbiotic.TxResult, err error) ⋮---- func (e *Client) RegisterKey( ctx context.Context, addr symbiotic.CrossChainAddress, keyTag symbiotic.KeyTag, key symbiotic.CompactPublicKey, signature symbiotic.RawSignature, extraData []byte, ) (_ symbiotic.TxResult, err error) ⋮---- func (e *Client) InvalidateOldSignatures( ctx context.Context, addr symbiotic.CrossChainAddress, ) (_ symbiotic.TxResult, err error) ⋮---- func (e *Client) RegisterOperatorVotingPowerProvider( ctx context.Context, addr symbiotic.CrossChainAddress, ) (_ symbiotic.TxResult, err error) ⋮---- func (e *Client) UnregisterOperatorVotingPowerProvider( ctx context.Context, addr symbiotic.CrossChainAddress, ) (_ symbiotic.TxResult, err error) ```` ## File: symbiotic/client/evm/eth_set_genesis_test.go ````go package evm ⋮---- import ( "context" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestSetGenesis_NoSettlementContract_ReturnsError(t *testing.T) ⋮---- func TestSetGenesis_KeyProviderFails_ReturnsError(t *testing.T) ⋮---- func TestSetGenesis_InvalidECDSAKey_ReturnsError(t *testing.T) ⋮---- func TestSetGenesis_ContextTimeout_ReturnsError(t *testing.T) ⋮---- func TestSetGenesis_InvalidChainID_ReturnsError(t *testing.T) ⋮---- func TestSetGenesis_EmptyExtraData_HandlesCorrectly(t *testing.T) ⋮---- func TestSetGenesis_NilExtraData_HandlesCorrectly(t *testing.T) ⋮---- func TestSetGenesis_PartialHappyPath_ValidatesDataPreparation(t *testing.T) ```` ## File: symbiotic/client/evm/eth_set_genesis.go ````go package evm ⋮---- import ( "context" "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" "time" ⋮---- "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ⋮---- keyprovider "github.com/symbioticfi/relay/internal/usecase/key-provider" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (e *Client) SetGenesis( ctx context.Context, addr symbiotic.CrossChainAddress, header symbiotic.ValidatorSetHeader, extraData []symbiotic.ExtraData, ) (_ symbiotic.TxResult, err error) ```` ## File: symbiotic/client/evm/eth_test.go ````go package evm ⋮---- import ( "context" "errors" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "errors" "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm/gen" "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestGetChains_WithMultipleChains_ReturnsAllChainIDs(t *testing.T) ⋮---- func TestGetChains_WithNoChains_ReturnsEmptySlice(t *testing.T) ⋮---- func TestGetChains_WithSingleChain_ReturnsSingleChainID(t *testing.T) ⋮---- func TestObserveMetrics_WithMetricsEnabled_CallsObserveEVMMethodCall(t *testing.T) ⋮---- func TestObserveMetrics_WithError_CallsWithErrorStatus(t *testing.T) ⋮---- func TestObserveMetrics_WithNilMetrics_DoesNotPanic(t *testing.T) ⋮---- func TestIsValsetHeaderCommittedAt_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetHeaderHash_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetHeaderHashAt_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetLastCommittedHeaderEpoch_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetCaptureTimestampFromValsetHeaderAt_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetValSetHeaderAt_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetValSetHeader_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetEip712Domain_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetVotingPowerProviderEip712Domain_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetOperatorNonce_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetVotingPowers_MulticallCheckFails_ReturnsError(t *testing.T) ⋮---- func TestGetOperators_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetKeysOperators_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetKeys_MulticallCheckFails_ReturnsError(t *testing.T) ⋮---- func TestIsValsetHeaderCommittedAtEpochs_MulticallCheckFails_ReturnsError(t *testing.T) ⋮---- func TestGetSubnetwork_Success_ReturnsSubnetworkHash(t *testing.T) ⋮---- func TestGetSubnetwork_DriverError_ReturnsError(t *testing.T) ⋮---- func TestGetNetworkAddress_Success_ReturnsNetworkAddress(t *testing.T) ⋮---- func TestGetNetworkAddress_DriverError_ReturnsError(t *testing.T) ⋮---- func TestFormatEVMContractError_WithNonJSONError_ReturnsOriginalError(t *testing.T) ⋮---- func TestGetVotingPowers_WithNoMulticall_ReturnsError(t *testing.T) ⋮---- func TestGetKeys_WithNoMulticall_ReturnsError(t *testing.T) ⋮---- func TestGetSettlementContract_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetSettlementContract_WithConnection_ReturnsContract(t *testing.T) ⋮---- func TestGetVotingPowerProviderContract_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetVotingPowerProviderContract_WithConnection_ReturnsContract(t *testing.T) ⋮---- func TestGetVotingPowerProviderContractTransactor_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetVotingPowerProviderContractTransactor_WithConnection_ReturnsContract(t *testing.T) ⋮---- func TestGetKeyRegistryContract_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetKeyRegistryContract_WithConnection_ReturnsContract(t *testing.T) ⋮---- func TestGetOperatorRegistryContract_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestGetOperatorRegistryContract_WithConnection_ReturnsContract(t *testing.T) ⋮---- func TestGetCurrentEpoch_Success_ReturnsEpoch(t *testing.T) ⋮---- func TestGetCurrentEpoch_DriverError_ReturnsError(t *testing.T) ⋮---- func TestGetCurrentEpochDuration_Success_ReturnsDuration(t *testing.T) ⋮---- func TestGetCurrentEpochDuration_DriverError_ReturnsError(t *testing.T) ⋮---- func TestGetEpochDuration_Success_ReturnsDuration(t *testing.T) ⋮---- func TestGetEpochDuration_DriverError_ReturnsError(t *testing.T) ⋮---- func TestGetEpochStart_Success_ReturnsTimestamp(t *testing.T) ⋮---- func TestGetEpochStart_DriverError_ReturnsError(t *testing.T) ⋮---- func TestGetConfig_Success_ReturnsConfig(t *testing.T) ⋮---- func TestGetConfig_GetConfigAtError_ReturnsError(t *testing.T) ⋮---- func TestGetConfig_GetEpochDurationError_ReturnsError(t *testing.T) ```` ## File: symbiotic/client/evm/eth_verify_quorum_sig_test.go ````go package evm ⋮---- import ( "context" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestVerifyQuorumSig_NoSettlementContract_ReturnsError(t *testing.T) ⋮---- func TestVerifyQuorumSig_ContextTimeout_ReturnsError(t *testing.T) ⋮---- func TestVerifyQuorumSig_InvalidChainID_ReturnsError(t *testing.T) ⋮---- func TestVerifyQuorumSig_EmptyProof_HandlesCorrectly(t *testing.T) ⋮---- func TestVerifyQuorumSig_EmptyMessage_HandlesCorrectly(t *testing.T) ⋮---- func TestVerifyQuorumSig_NilThreshold_HandlesCorrectly(t *testing.T) ⋮---- func TestVerifyQuorumSig_ZeroEpoch_HandlesCorrectly(t *testing.T) ```` ## File: symbiotic/client/evm/eth_verify_quorum_sig.go ````go package evm ⋮---- import ( "context" "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/rpc" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" "time" ⋮---- "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/rpc" "github.com/go-errors/errors" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func (e *Client) VerifyQuorumSig(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch, message []byte, keyTag symbiotic.KeyTag, threshold *big.Int, proof []byte) (_ bool, err error) ```` ## File: symbiotic/client/evm/eth.go ````go package evm ⋮---- import ( "context" _ "embed" "encoding/hex" "log/slog" "math/big" "regexp" "time" "github.com/ethereum/go-ethereum/rpc" "github.com/samber/lo" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" cryptoSym "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ) ⋮---- "context" _ "embed" "encoding/hex" "log/slog" "math/big" "regexp" "time" ⋮---- "github.com/ethereum/go-ethereum/rpc" "github.com/samber/lo" ⋮---- "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/go-errors/errors" "github.com/go-playground/validator/v10" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" cryptoSym "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- //go:generate mockgen -destination=mocks/eth.go -package=mocks github.com/symbioticfi/relay/symbiotic/client/evm IEvmClient,conn,metrics,keyProvider,driverContract ⋮---- type metrics interface { ObserveEVMMethodCall(method string, chainID uint64, status string, d time.Duration) ObserveCommitValsetHeaderParams(chainID uint64, gasUsed uint64, effectiveGasPrice *big.Int) } ⋮---- // IEvmClient defines the interface for EVM client operations type IEvmClient interface { GetChains() []uint64 GetSubnetwork(ctx context.Context) (common.Hash, error) GetNetworkAddress(ctx context.Context) (common.Address, error) GetConfig(ctx context.Context, timestamp symbiotic.Timestamp, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) GetEip712Domain(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.Eip712Domain, error) GetVotingPowerProviderEip712Domain(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.Eip712Domain, error) GetOperatorNonce(ctx context.Context, votingPowerProvider symbiotic.CrossChainAddress, operator common.Address) (*big.Int, error) GetCurrentEpoch(ctx context.Context) (symbiotic.Epoch, error) GetCurrentEpochDuration(ctx context.Context) (uint64, error) GetEpochDuration(ctx context.Context, epoch symbiotic.Epoch) (uint64, error) GetEpochStart(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.Timestamp, error) IsValsetHeaderCommittedAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch, opts ...symbiotic.EVMOption) (bool, error) GetHeaderHash(ctx context.Context, addr symbiotic.CrossChainAddress) (common.Hash, error) GetHeaderHashAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch) (common.Hash, error) GetLastCommittedHeaderEpoch(ctx context.Context, addr symbiotic.CrossChainAddress, evmOptions ...symbiotic.EVMOption) (symbiotic.Epoch, error) GetCaptureTimestampFromValsetHeaderAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch) (uint64, error) GetValSetHeaderAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch) (symbiotic.ValidatorSetHeader, error) GetValSetHeader(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.ValidatorSetHeader, error) GetVotingPowers(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) ([]symbiotic.OperatorVotingPower, error) GetKeys(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) ([]symbiotic.OperatorWithKeys, error) CommitValsetHeader(ctx context.Context, addr symbiotic.CrossChainAddress, header symbiotic.ValidatorSetHeader, extraData []symbiotic.ExtraData, proof []byte) (symbiotic.TxResult, error) RegisterOperator(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.TxResult, error) RegisterKey(ctx context.Context, addr symbiotic.CrossChainAddress, keyTag symbiotic.KeyTag, key symbiotic.CompactPublicKey, signature symbiotic.RawSignature, extraData []byte) (symbiotic.TxResult, error) InvalidateOldSignatures(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.TxResult, error) RegisterOperatorVotingPowerProvider(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.TxResult, error) UnregisterOperatorVotingPowerProvider(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.TxResult, error) SetGenesis(ctx context.Context, addr symbiotic.CrossChainAddress, header symbiotic.ValidatorSetHeader, extraData []symbiotic.ExtraData) (symbiotic.TxResult, error) VerifyQuorumSig(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch, message []byte, keyTag symbiotic.KeyTag, threshold *big.Int, proof []byte) (bool, error) IsValsetHeaderCommittedAtEpochs(ctx context.Context, addr symbiotic.CrossChainAddress, epochs []symbiotic.Epoch) ([]bool, error) } ⋮---- type keyProvider interface { GetPrivateKeyByNamespaceTypeId(namespace string, keyType symbiotic.KeyType, id int) (cryptoSym.PrivateKey, error) } ⋮---- // conn defines the interface for Ethereum client operations // ethclient.Client implements this interface type conn interface { bind.ContractBackend bind.DeployBackend } ⋮---- var _ driverContract = (*gen.IValSetDriverCaller)(nil) ⋮---- // driverContract defines the interface for driver contract operations // gen.IValSetDriverCaller implements this interface type driverContract interface { GetConfigAt(opts *bind.CallOpts, timestamp *big.Int) (gen.IValSetDriverConfig, error) GetCurrentEpoch(opts *bind.CallOpts) (*big.Int, error) GetCurrentEpochDuration(opts *bind.CallOpts) (*big.Int, error) GetEpochDuration(opts *bind.CallOpts, epoch *big.Int) (*big.Int, error) GetEpochStart(opts *bind.CallOpts, epoch *big.Int) (*big.Int, error) SUBNETWORK(opts *bind.CallOpts) ([32]byte, error) NETWORK(opts *bind.CallOpts) (common.Address, error) } ⋮---- type Config struct { ChainURLs []string `validate:"required"` DriverAddress symbiotic.CrossChainAddress `validate:"required"` RequestTimeout time.Duration `validate:"required,gt=0"` KeyProvider keyProvider Metrics metrics MaxCalls int } ⋮---- func (c Config) Validate() error ⋮---- type Client struct { cfg Config conns map[uint64]conn driver driverContract driverChainID uint64 metrics metrics } ⋮---- func NewEvmClient(ctx context.Context, cfg Config) (*Client, error) ⋮---- func (e *Client) GetChains() []uint64 ⋮---- func (e *Client) GetConfig(ctx context.Context, timestamp symbiotic.Timestamp, epoch symbiotic.Epoch) (_ symbiotic.NetworkConfig, err error) ⋮---- // TODO: get from contract ⋮---- func (e *Client) GetCurrentEpoch(ctx context.Context) (_ symbiotic.Epoch, err error) ⋮---- func (e *Client) GetCurrentEpochDuration(ctx context.Context) (_ uint64, err error) ⋮---- func (e *Client) GetEpochDuration(ctx context.Context, epoch symbiotic.Epoch) (_ uint64, err error) ⋮---- func (e *Client) GetEpochStart(ctx context.Context, epoch symbiotic.Epoch) (_ symbiotic.Timestamp, err error) ⋮---- func (e *Client) GetSubnetwork(ctx context.Context) (_ common.Hash, err error) ⋮---- func (e *Client) GetNetworkAddress(ctx context.Context) (_ common.Address, err error) ⋮---- func (e *Client) IsValsetHeaderCommittedAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch, opts ...symbiotic.EVMOption) (_ bool, err error) ⋮---- func (e *Client) GetHeaderHash(ctx context.Context, addr symbiotic.CrossChainAddress) (_ common.Hash, err error) ⋮---- func (e *Client) GetHeaderHashAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch) (_ common.Hash, err error) ⋮---- func (e *Client) GetLastCommittedHeaderEpoch(ctx context.Context, addr symbiotic.CrossChainAddress, opts ...symbiotic.EVMOption) (_ symbiotic.Epoch, err error) ⋮---- // todo if zero epoch need to check if it's committed or not ⋮---- func getRPCBlockNumber(number symbiotic.BlockNumber) *big.Int ⋮---- func (e *Client) GetCaptureTimestampFromValsetHeaderAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch) (_ uint64, err error) ⋮---- func (e *Client) GetValSetHeaderAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch) (_ symbiotic.ValidatorSetHeader, err error) ⋮---- func (e *Client) GetValSetHeader(ctx context.Context, addr symbiotic.CrossChainAddress) (_ symbiotic.ValidatorSetHeader, err error) ⋮---- func (e *Client) GetEip712Domain(ctx context.Context, addr symbiotic.CrossChainAddress) (_ symbiotic.Eip712Domain, err error) ⋮---- func (e *Client) GetVotingPowerProviderEip712Domain(ctx context.Context, addr symbiotic.CrossChainAddress) (_ symbiotic.Eip712Domain, err error) ⋮---- func (e *Client) GetOperatorNonce(ctx context.Context, votingPowerProvider symbiotic.CrossChainAddress, operator common.Address) (_ *big.Int, err error) ⋮---- func (e *Client) GetVotingPowers(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) (_ []symbiotic.OperatorVotingPower, err error) ⋮---- func (e *Client) GetOperators(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) (_ []common.Address, err error) ⋮---- func (e *Client) GetKeysOperators(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) (_ []common.Address, err error) ⋮---- func (e *Client) GetKeys(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) (_ []symbiotic.OperatorWithKeys, err error) ⋮---- func (e *Client) IsValsetHeaderCommittedAtEpochs(ctx context.Context, addr symbiotic.CrossChainAddress, epochs []symbiotic.Epoch) (_ []bool, err error) ⋮---- var res bool ⋮---- var customErrRegExp = regexp.MustCompile(`0x[0-9a-fA-F]{8}`) ⋮---- type metadata interface { GetAbi() (*abi.ABI, error) } ⋮---- func (e *Client) formatEVMContractError(meta metadata, originalErr error) error ⋮---- type jsonError interface { Error() string ErrorData() interface{} var errData jsonError ⋮---- func (e *Client) formatEVMError(err error) error ⋮---- func (e *Client) getSettlementContract(addr symbiotic.CrossChainAddress) (*gen.ISettlement, error) ⋮---- func (e *Client) getVotingPowerProviderContract(addr symbiotic.CrossChainAddress) (*gen.IVotingPowerProviderCaller, error) ⋮---- func (e *Client) getVotingPowerProviderContractTransactor(addr symbiotic.CrossChainAddress) (*gen.IVotingPowerProvider, error) ⋮---- func (e *Client) getKeyRegistryContract(addr symbiotic.CrossChainAddress) (*gen.IKeyRegistry, error) ⋮---- func (e *Client) getOperatorRegistryContract(addr symbiotic.CrossChainAddress) (*gen.OperatorRegistry, error) ⋮---- func findErrorBySelector(errSelector string) (abi.Error, bool) ⋮---- func (e *Client) observeMetrics(method string, chainID uint64, err error, start time.Time) ```` ## File: symbiotic/client/evm/multicall_test.go ````go package evm ⋮---- import ( "context" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" ) ⋮---- "context" "testing" "time" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm/mocks" ⋮---- func TestMulticallExists_NoConnection_ReturnsError(t *testing.T) ⋮---- func TestMulticallExists_CodeAtFails_ReturnsError(t *testing.T) ⋮---- func TestMulticallExists_CodeExists_ReturnsTrue(t *testing.T) ⋮---- func TestMulticallExists_NoCode_ReturnsFalse(t *testing.T) ⋮---- func TestMulticall_NoConnection_ReturnsError(t *testing.T) ```` ## File: symbiotic/client/evm/multicall.go ````go package evm ⋮---- import ( "context" "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" "github.com/go-errors/errors" "github.com/samber/lo" "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "context" "math/big" "time" ⋮---- "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" "github.com/go-errors/errors" "github.com/samber/lo" ⋮---- "github.com/symbioticfi/relay/internal/entity" "github.com/symbioticfi/relay/symbiotic/client/evm/gen" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const Multicall3 = "0xcA11bde05977b3631167028862bE2a173976CA11" ⋮---- func (e *Client) multicallExists(ctx context.Context, chainId uint64) (bool, error) ⋮---- func (e *Client) multicall(ctx context.Context, chainId uint64, calls []Call) (_ []Result, err error) ⋮---- func (e *Client) getVotingPowersMulticall(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) ([]symbiotic.OperatorVotingPower, error) ⋮---- var res []gen.IVotingPowerProviderVaultValue ⋮---- func (e *Client) getKeysMulticall(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) (_ []symbiotic.OperatorWithKeys, err error) ⋮---- var res []gen.IKeyRegistryKey ```` ## File: symbiotic/entity/entity_test.go ````go package entity ⋮---- import ( "context" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) ⋮---- "context" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ⋮---- func TestValidatorSet_FindValidatorsBySignatures(t *testing.T) ⋮---- // Test data setup ⋮---- // Create validators ⋮---- {Tag: KeyTag(2), Payload: publicKey3}, // Different key tag ⋮---- // Check that we found the right validators ⋮---- // Validator3 has publicKey3 but for different tag ⋮---- func TestValidatorSet_IsActiveCommitter(t *testing.T) ⋮---- // Create test validators with keys ⋮---- { // Index 0 - committer ⋮---- { // Index 1 - committer ⋮---- { // Index 2 - committer ⋮---- { // Index 3 - not a committer ⋮---- CommitterIndices: []uint32{0, 1, 2}, // Only first three are committers ⋮---- // Test with non-committer key ⋮---- // Test with unknown key ⋮---- // When duration is 0, any committer should always be active ⋮---- CommitterIndices: []uint32{1}, // Only one committer ⋮---- // Single committer should always be active after capture time (no time slot rotation needed) ⋮---- // but capture time is in the future, so before that it should be false ⋮---- // But non-committer key should still return false ⋮---- // No committer should be active before capture timestamp ⋮---- CommitterIndices: []uint32{0, 1, 2}, // Three committers ⋮---- // Test first slot (1000-1099): committer 0 should be active ⋮---- // Test second slot (1100-1199): committer 1 should be active ⋮---- // Test third slot (1200-1299): committer 2 should be active ⋮---- // Test fourth slot (1300-1399): wraps back to committer 0 ⋮---- // Test fifth slot (1400-1499): committer 1 again ⋮---- // Test sixth slot (1500-1599): committer 2 again ⋮---- // Test grace period at end of slot 0 (time 1095, grace brings us to 1105 which is slot 1) ⋮---- // Test grace period at end of slot 1 (time 1195, grace brings us to 1205 which is slot 2) ⋮---- // Test grace period at end of slot 2 (time 1295, grace brings us to 1305 which is slot 3, wraps to committer 0) ⋮---- // Test grace period that doesn't cross slot boundary ⋮---- CommitterIndices: []uint32{2, 0, 1}, // Different order to test proper indexing ⋮---- // First slot should go to validator at index 2 (first in CommitterIndices) ⋮---- // Second slot should go to validator at index 0 (second in CommitterIndices) ⋮---- // Third slot should go to validator at index 1 (third in CommitterIndices) ⋮---- // Fourth slot wraps back to validator at index 2 ⋮---- CaptureTimestamp: 1000000000, // 1 billion ⋮---- slotDuration := uint64(1000000) // 1 million seconds per slot ⋮---- // Test first slot ⋮---- // Test second slot ⋮---- // Test wrap-around with large values ⋮---- // Test exact boundary between slot 0 and slot 1 ⋮---- // Test exact boundary between slot 1 and slot 2 ⋮---- CommitterIndices: []uint32{}, // No committers ⋮---- // No one should be active if there are no committers ⋮---- func TestPaddedUint64(t *testing.T) ⋮---- input: 65535, // 0xFFFF ⋮---- input: 4294967295, // 0xFFFFFFFF ⋮---- input: 18446744073709551615, // 0xFFFFFFFFFFFFFFFF ⋮---- input: 1640995200, // Typical epoch timestamp ```` ## File: symbiotic/entity/entity.go ````go package entity ⋮---- import ( "bytes" "context" "encoding/binary" "fmt" "log/slog" "math/big" "slices" "github.com/symbioticfi/relay/symbiotic/usecase/ssz" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/samber/lo" ) ⋮---- "bytes" "context" "encoding/binary" "fmt" "log/slog" "math/big" "slices" ⋮---- "github.com/symbioticfi/relay/symbiotic/usecase/ssz" ⋮---- "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/samber/lo" ⋮---- type VerificationType uint32 type AggregationPolicyType uint32 ⋮---- const ( VerificationTypeBlsBn254ZK VerificationType = 0 VerificationTypeBlsBn254Simple VerificationType = 1 AggregationPolicyLowLatency AggregationPolicyType = 0 AggregationPolicyLowCost AggregationPolicyType = 1 ) ⋮---- var ( ExtraDataKeyTagPrefixHash = crypto.Keccak256Hash([]byte("keyTag.")) ⋮---- var ( ZkVerificationTotalActiveValidatorsHash = crypto.Keccak256Hash([]byte("totalActiveValidators")) ⋮---- var ( SimpleVerificationValidatorSetHashKeccak256Hash = crypto.Keccak256Hash([]byte("validatorSetHashKeccak256")) ⋮---- type ValidatorSetStatus uint8 ⋮---- const ( HeaderDerived ValidatorSetStatus = iota HeaderAggregated HeaderCommitted HeaderMissed ) ⋮---- const ValsetHeaderKeyTag = KeyTag(15) ⋮---- type RawSignature []byte type RawMessageHash []byte type RawPublicKey []byte type CompactPublicKey []byte type RawMessage []byte type RawProof []byte type VotingPower struct { *big.Int } type QuorumThresholdPct struct { *big.Int } ⋮---- func ToVotingPower(val *big.Int) VotingPower ⋮---- func ToQuorumThresholdPct(val *big.Int) QuorumThresholdPct ⋮---- type Epoch uint64 type Timestamp uint64 ⋮---- // Bytes returns the epoch as a BigEndian encoded byte slice for use in database keys. // BigEndian encoding ensures that lexicographic byte ordering matches numeric ordering, // which is crucial for proper sorting in key-value stores like Badger. // Example: Epoch(51).Bytes() < Epoch(501).Bytes() when comparing bytes lexicographically. func (e Epoch) Bytes() []byte ⋮---- func (raw RawSignature) MarshalText() ([]byte, error) ⋮---- func (vp VotingPower) MarshalJSON() ([]byte, error) ⋮---- // dirty hack to force using string instead of float in json ⋮---- // SignatureRequest signature request message type SignatureRequest struct { KeyTag KeyTag RequiredEpoch Epoch Message RawMessage } ⋮---- type SignatureRequestWithID struct { SignatureRequest RequestID common.Hash } ⋮---- // Signature signer.sign() -> Signature type Signature struct { MessageHash RawMessageHash // scheme depends on KeyTag KeyTag KeyTag // Key tag for validation Epoch Epoch // Epoch for validation PublicKey PublicKey // parse based on KeyTag (for bls will contain g1+g2) Signature RawSignature // parse based on KeyTag } ⋮---- MessageHash RawMessageHash // scheme depends on KeyTag KeyTag KeyTag // Key tag for validation Epoch Epoch // Epoch for validation PublicKey PublicKey // parse based on KeyTag (for bls will contain g1+g2) Signature RawSignature // parse based on KeyTag ⋮---- // RequestID calculates the request id based on Hash(MessageHash, KeyTag, Epoch) func (s Signature) RequestID() common.Hash ⋮---- func requestID(keyTag KeyTag, epoch Epoch, messageHash RawMessageHash) common.Hash ⋮---- func paddedUint64(value uint64) []byte ⋮---- // AggregationProof aggregator.proof(signatures []Signature) -> AggregationProof type AggregationProof struct { MessageHash RawMessageHash // scheme depends on KeyTag KeyTag KeyTag // Key tag for validation Epoch Epoch // Epoch for validation Proof RawProof // parse based on KeyTag } ⋮---- Proof RawProof // parse based on KeyTag ⋮---- // ProofCommitKey represents a proof commit key with its parsed epoch and hash for sorting type ProofCommitKey struct { Epoch Epoch RequestID common.Hash } ⋮---- func (vt VerificationType) String() string ⋮---- type CrossChainAddress struct { ChainId uint64 Address common.Address } ⋮---- type QuorumThreshold struct { KeyTag KeyTag QuorumThreshold QuorumThresholdPct } ⋮---- type NetworkConfig struct { VotingPowerProviders []CrossChainAddress KeysProvider CrossChainAddress Settlements []CrossChainAddress VerificationType VerificationType MaxVotingPower VotingPower MinInclusionVotingPower VotingPower MaxValidatorsCount VotingPower RequiredKeyTags []KeyTag RequiredHeaderKeyTag KeyTag QuorumThresholds []QuorumThreshold EpochDuration uint64 // in seconds // scheduler config NumAggregators uint64 NumCommitters uint64 CommitterSlotDuration uint64 // in seconds } ⋮---- EpochDuration uint64 // in seconds // scheduler config ⋮---- CommitterSlotDuration uint64 // in seconds ⋮---- func maxThreshold() *big.Int ⋮---- // 10^18 is the maximum threshold value ⋮---- func (nc NetworkConfig) CalcQuorumThreshold(totalVP VotingPower) (VotingPower, error) ⋮---- // add 1 to apply up rounding ⋮---- type NetworkData struct { Address common.Address Subnetwork common.Hash Eip712Data Eip712Domain } ⋮---- type VaultVotingPower struct { Vault common.Address VotingPower VotingPower } ⋮---- type OperatorVotingPower struct { Operator common.Address Vaults []VaultVotingPower } ⋮---- type OperatorWithKeys struct { Operator common.Address Keys []ValidatorKey } ⋮---- type Eip712Domain struct { Fields [1]byte Name string Version string ChainId *big.Int VerifyingContract common.Address Salt *big.Int Extensions []*big.Int } ⋮---- type ValidatorKey struct { Tag KeyTag Payload CompactPublicKey } ⋮---- type ValidatorVault struct { ChainID uint64 `json:"chainId"` Vault common.Address `json:"vault"` VotingPower VotingPower `json:"votingPower"` } ⋮---- type Validators []Validator ⋮---- func (va Validators) SortByVotingPowerDescAndOperatorAddressAsc() ⋮---- func (va Validators) SortByOperatorAddressAsc() ⋮---- func (va Validators) CheckIsSortedByOperatorAddressAsc() error ⋮---- type Vaults []ValidatorVault ⋮---- func (v Vaults) SortByAddressAsc() ⋮---- func (v Vaults) SortVaultsByVotingPowerDescAndAddressAsc() ⋮---- func (va Validators) GetTotalActiveVotingPower() VotingPower ⋮---- func (va Validators) GetActiveValidators() Validators ⋮---- var activeValidators Validators ⋮---- type Validator struct { Operator common.Address `json:"operator"` VotingPower VotingPower `json:"votingPower"` IsActive bool `json:"isActive"` Keys []ValidatorKey `json:"keys"` Vaults Vaults `json:"vaults"` } ⋮---- func (v Validator) FindKeyByKeyTag(keyTag KeyTag) ([]byte, bool) ⋮---- type ValidatorSet struct { Version uint8 RequiredKeyTag KeyTag // key tag required to commit next valset Epoch Epoch // valset epoch CaptureTimestamp Timestamp // epoch capture timestamp QuorumThreshold VotingPower // absolute number now, not a percent Validators Validators Status ValidatorSetStatus // Scheduler info for current validator set, completely offchain not included in header AggregatorIndices []uint32 CommitterIndices []uint32 } ⋮---- RequiredKeyTag KeyTag // key tag required to commit next valset Epoch Epoch // valset epoch CaptureTimestamp Timestamp // epoch capture timestamp QuorumThreshold VotingPower // absolute number now, not a percent ⋮---- // Scheduler info for current validator set, completely offchain not included in header ⋮---- func (v ValidatorSet) IsAggregator(requiredKey []byte) bool ⋮---- func (v ValidatorSet) IsCommitter(requiredKey []byte) bool ⋮---- func (v ValidatorSet) IsSigner(requiredKey CompactPublicKey) bool ⋮---- func (v ValidatorSet) findMembership(indexArray []uint32, requiredKey []byte) (uint32, bool) ⋮---- // IsActiveCommitter determines if the current time falls within the time slot // of the current node based on the network configuration and validator set. // Each committer has a dedicated time slot of CommitterSlotDuration seconds, // starting from the CaptureTimestamp. If the node's slot is about to start // i.e. if currentTime + graceSeconds moves us to the next slot, it will also return true. func (v ValidatorSet) IsActiveCommitter( ctx context.Context, committerSlotDuration uint64, currentTime Timestamp, graceSeconds uint64, requiredKey []byte, ) bool ⋮---- // If current time is before capture timestamp, we're not in any slot yet ⋮---- // single committer no need to check time slots ⋮---- // Calculate elapsed time since capture ⋮---- // Calculate which slot we're currently in ⋮---- // Calculate which committer should be active for current slot (round-robin) ⋮---- // Check if the required key matches the current slot's committer ⋮---- // Check if adding grace period moves us to the next slot ⋮---- // If grace period moves us to a different slot, check that slot's committer too ⋮---- func (v ValidatorSet) FindValidatorByKey(keyTag KeyTag, publicKey []byte) (Validator, bool) { // DON'T USE INSIDE LOOPS ⋮---- type ValidatorSetHash struct { KeyTag KeyTag Hash common.Hash } ⋮---- // ValidatorSetHeader represents the input for validator set header type ValidatorSetHeader struct { Version uint8 RequiredKeyTag KeyTag Epoch Epoch CaptureTimestamp Timestamp QuorumThreshold VotingPower TotalVotingPower VotingPower ValidatorsSszMRoot common.Hash } ⋮---- type ValidatorSetMetadata struct { RequestID common.Hash ExtraData []ExtraData Epoch Epoch CommitmentData []byte } ⋮---- type ExtraData struct { Key common.Hash Value common.Hash } ⋮---- type ExtraDataList []ExtraData ⋮---- func (e ExtraDataList) Hash() ([]byte, error) ⋮---- func (e ExtraDataList) AbiEncode() ([]byte, error) ⋮---- func (v ValidatorSet) GetTotalActiveValidators() int64 ⋮---- func (v ValidatorSet) GetHeader() (ValidatorSetHeader, error) ⋮---- func (v ValidatorSet) FindValidatorsByKeys(keyTag KeyTag, publicKeys []CompactPublicKey) (Validators, error) ⋮---- // Build lookup map: publicKey -> validator ⋮---- // Find validators for each public key ⋮---- func sszTreeRoot(v *ValidatorSet) (common.Hash, error) ⋮---- func keyPayloadHash(k ValidatorKey) common.Hash ⋮---- func validatorSetToSszValidators(v *ValidatorSet) ssz.SszValidatorSet ⋮---- type TxResult struct { TxHash common.Hash } ⋮---- type ChainURL struct { ChainID uint64 RPCURL string } ⋮---- type AggregationStatus struct { VotingPower VotingPower Validators []Validator } ```` ## File: symbiotic/entity/evm_entity.go ````go package entity ⋮---- type BlockNumber string ⋮---- const ( BlockNumberFinalized BlockNumber = "finalized" BlockNumberLatest BlockNumber = "latest" ) ⋮---- type EVMOptions struct { BlockNumber BlockNumber } ⋮---- func AppliedEVMOptions(opts ...EVMOption) *EVMOptions ⋮---- type EVMOption func(options *EVMOptions) ⋮---- func WithEVMBlockNumber(blockNumber BlockNumber) EVMOption ```` ## File: symbiotic/entity/key_tag_entity_test.go ````go package entity ⋮---- import ( "strings" "testing" ) ⋮---- "strings" "testing" ⋮---- func TestKeyTag_Type(t *testing.T) ⋮---- func TestKeyTag_MarshalText(t *testing.T) ⋮---- func TestKeyTag_String(t *testing.T) ⋮---- func TestKeyType_String(t *testing.T) ⋮---- func TestKeyTypeFromString(t *testing.T) ```` ## File: symbiotic/entity/key_tag_entity.go ````go package entity ⋮---- import ( "fmt" "github.com/go-errors/errors" ) ⋮---- "fmt" ⋮---- "github.com/go-errors/errors" ⋮---- type KeyType uint8 ⋮---- const ( KeyTypeBlsBn254 KeyType = 0 KeyTypeEcdsaSecp256k1 KeyType = 1 KeyTypeBls12381Bn254 KeyType = 2 KeyTypeInvalid KeyType = 255 BLS_BN254_TYPE = "bls_bn254" ECDSA_SECP256K1_TYPE = "ecdsa_secp256k1" BLS_12381_BN254_TYPE = "bls12381_bn254" INVALID_TYPE = "invalid" ) ⋮---- type KeyTag uint8 ⋮---- func (kt KeyTag) Type() KeyType ⋮---- return KeyTypeInvalid // Invalid key type ⋮---- func (kt KeyTag) MarshalText() (text []byte, err error) ⋮---- func (kt KeyTag) String() string ⋮---- // SignerKey returns true if the key type can be used for signing func (kt KeyType) SignerKey() bool ⋮---- // AggregationKey returns true if the key type can be used for aggregation func (kt KeyType) AggregationKey() bool ⋮---- func KeyTypeFromString(typeStr string) (KeyType, error) ⋮---- func KeyTagFromTypeAndId(keyType KeyType, keyId uint8) (KeyTag, error) ```` ## File: symbiotic/entity/key.go ````go package entity ⋮---- type PublicKey interface { Verify(msg Message, sig RawSignature) error VerifyWithHash(msgHash MessageHash, sig RawSignature) error OnChain() CompactPublicKey Raw() RawPublicKey MarshalText() (text []byte, err error) } ⋮---- type PrivateKey interface { Bytes() []byte Sign(msg []byte) (RawSignature, MessageHash, error) PublicKey() PublicKey } ```` ## File: symbiotic/usecase/aggregator/aggregator-types/aggregator.go ````go package aggregator_types ⋮---- import ( "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/ethereum/go-ethereum/common" ) ⋮---- "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- "github.com/ethereum/go-ethereum/common" ⋮---- type Aggregator interface { Aggregate(valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, messageHash []byte, signatures []symbiotic.Signature) (symbiotic.AggregationProof, error) Verify(valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, aggregationProof symbiotic.AggregationProof) (bool, error) GenerateExtraData(valset symbiotic.ValidatorSet, keyTags []symbiotic.KeyTag) ([]symbiotic.ExtraData, error) } ⋮---- type Prover interface { Prove(proveInput proof.ProveInput) (proof.ProofData, error) Verify(valsetLen int, publicInputHash common.Hash, proofBytes []byte) (bool, error) } ```` ## File: symbiotic/usecase/aggregator/blsBn254Simple/aggregator_test.go ````go package blsBn254Simple ⋮---- import ( "math/big" "testing" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" "testing" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestNewAggregator_Success(t *testing.T) ⋮---- func TestCompress_WithValidG1Point_ReturnsCompressedHash(t *testing.T) ⋮---- func TestCompress_WithZeroPoint_ReturnsHash(t *testing.T) ⋮---- func TestCompress_WithDifferentPoints_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestDecompress_WithValidCompressedPoint_ReturnsG1Point(t *testing.T) ⋮---- func TestCompress_Decompress_RoundTrip_PreservesPoint(t *testing.T) ⋮---- func TestFindYFromX_WithValidX_ReturnsY(t *testing.T) ⋮---- assert.Greater(t, y.Cmp(big.NewInt(0)), 0) //nolint:testifylint // assert.Positive doesn't work with *big.Int ⋮---- func TestFindYFromX_WithZeroX_ReturnsY(t *testing.T) ⋮---- func TestFindYFromX_WithLargeX_ReturnsY(t *testing.T) ⋮---- func TestProcessValidators_WithNoValidators_ReturnsEmpty(t *testing.T) ⋮---- func TestProcessValidators_WithInactiveValidators_ReturnsEmpty(t *testing.T) ⋮---- func TestProcessValidators_WithActiveValidators_ReturnsValidatorData(t *testing.T) ⋮---- func TestProcessValidators_WithMultipleValidators_ReturnsSortedData(t *testing.T) ⋮---- func TestProcessValidators_WithMissingKeyTag_ReturnsError(t *testing.T) ⋮---- func TestCalcAlpha_WithValidInputs_ReturnsAlpha(t *testing.T) ⋮---- assert.Greater(t, alpha.Cmp(big.NewInt(0)), 0) //nolint:testifylint // assert.Positive doesn't work with *big.Int ⋮---- func TestCalcAlpha_WithDifferentInputs_ReturnsDifferentAlphas(t *testing.T) ⋮---- func TestCalcAlpha_WithSameInputs_ReturnsSameAlpha(t *testing.T) ⋮---- func TestAggregator_Aggregate_WithEmptySignatures_Succeeds(t *testing.T) ⋮---- func TestAggregator_Aggregate_WithMismatchedMessageHashes_ReturnsError(t *testing.T) ⋮---- func TestAggregator_Verify_WithInvalidMessageHashLength_ReturnsError(t *testing.T) ⋮---- func TestAggregator_Verify_WithShortProof_ReturnsError(t *testing.T) ⋮---- func TestAggregator_PackValidatorsData_WithValidData_ReturnsBytes(t *testing.T) ⋮---- func TestAggregator_PackValidatorsData_WithEmptyData_ReturnsBytes(t *testing.T) ⋮---- func TestAggregator_CalculateValidatorsKeccak_WithValidData_ReturnsHash(t *testing.T) ⋮---- func TestAggregator_CalculateValidatorsKeccak_WithSameData_ReturnsSameHash(t *testing.T) ⋮---- func TestAggregator_CalculateValidatorsKeccak_WithDifferentData_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestAggregator_GenerateExtraData_WithValidValidatorSet_ReturnsExtraData(t *testing.T) ⋮---- func TestAggregator_GenerateExtraData_WithMultipleKeyTags_ReturnsMultipleExtraData(t *testing.T) ⋮---- func TestAggregator_GenerateExtraData_ReturnsSortedData(t *testing.T) ```` ## File: symbiotic/usecase/aggregator/blsBn254Simple/aggregator.go ````go package blsBn254Simple ⋮---- import ( "bytes" "encoding/binary" "math/big" "sort" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/helpers" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" ) ⋮---- "bytes" "encoding/binary" "math/big" "sort" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/helpers" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" ⋮---- const maxValidators = 65_536 ⋮---- type abiTypes struct { g1Type abi.Type g2Type abi.Type validatorsDataType abi.Type g1Args abi.Arguments g2Args abi.Arguments validatorsArgs abi.Arguments } ⋮---- type Aggregator struct { abiTypes abiTypes } ⋮---- type ValidatorData struct { KeySerialized common.Hash VotingPower *big.Int } ⋮---- func NewAggregator() (*Aggregator, error) ⋮---- // createABITypes creates and returns all ABI types func createABITypes() (abiTypes, error) ⋮---- func (a Aggregator) Aggregate( valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, messageHash []byte, signatures []symbiotic.Signature, ) (symbiotic.AggregationProof, error) ⋮---- aggG2Key.X.A1.BigInt(new(big.Int)), // index 0 aggG2Key.X.A0.BigInt(new(big.Int)), // index 1 ⋮---- aggG2Key.Y.A1.BigInt(new(big.Int)), // index 0 aggG2Key.Y.A0.BigInt(new(big.Int)), // index 1 ⋮---- // Pack validators data with anonymous structs ⋮---- // Encode non-signers indices ⋮---- // Assemble proof ⋮---- func (a Aggregator) Verify( valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, aggregationProof symbiotic.AggregationProof, ) (bool, error) ⋮---- // Check key tag type ⋮---- // Parse proof components ⋮---- // Parse validators data length ⋮---- // Calculate non-signers offset ⋮---- // Verify validators data hash matches ⋮---- // Parse non-signers with proper validation ⋮---- // Validate proof length matches expected non-signers data ⋮---- // Parse and validate non-signers with ordering check ⋮---- var nonSignersVotingPower big.Int var nonSignersPublicKeyG1 *bn254.G1Affine nonSignersPublicKeyG1 = new(bn254.G1Affine) // Initialize to zero point ⋮---- var prevNonSignerIndex uint16 ⋮---- // Validate non-signer index ⋮---- // Check ordering (must be ascending) ⋮---- // Add non-signer's voting power ⋮---- // Add non-signer's public key ⋮---- // Verify validators match expected ⋮---- // Verify validator data matches ⋮---- // Check quorum using the same logic as Solidity ⋮---- // Get aggregated public key from valset (equivalent to extra data in Solidity) ⋮---- // Calculate effective public key: aggPubKeyG1 - nonSignersPublicKeyG1 // This matches the Solidity logic: aggPubKeyG1.plus(nonSignersPublicKeyG1.negate()) ⋮---- // Verify signature using BLS verification ⋮---- // Prepare bytes for alpha calculation ⋮---- func calcAlpha(aggPubKeyG1 *bn254.G1Affine, aggPubKeyG2 *bn254.G2Affine, aggSig *bn254.G1Affine, messageHash []byte) *big.Int ⋮---- // G1 public key bytes ⋮---- // G2 public key bytes ⋮---- // Signature bytes ⋮---- func (a Aggregator) GenerateExtraData(valset symbiotic.ValidatorSet, keyTags []symbiotic.KeyTag) ([]symbiotic.ExtraData, error) ⋮---- // Pack aggregated keys ⋮---- // sort extra data by key to ensure deterministic order ⋮---- func (a Aggregator) packValidatorsData(validatorsData []ValidatorData) ([]byte, error) ⋮---- func processValidators(validators []symbiotic.Validator, keyTag symbiotic.KeyTag) ([]ValidatorData, error) ⋮---- func (a Aggregator) calculateValidatorsKeccak(validatorsData []ValidatorData) (common.Hash, error) ⋮---- func compress(g1 *bn254.G1Affine) (common.Hash, error) ⋮---- func decompress(compressed [32]byte) (*bn254.G1Affine, error) ⋮---- func findYFromX(x *big.Int) (y *big.Int, err error) ⋮---- // Calculate beta = x^3 + 3 mod p beta := new(big.Int).Exp(x, big.NewInt(3), fpModulus) // x^3 beta.Add(beta, big.NewInt(3)) // x^3 + 3 beta.Mod(beta, fpModulus) // (x^3 + 3) mod p ⋮---- // Calculate y = beta^((p+1)/4) mod p ```` ## File: symbiotic/usecase/aggregator/blsBn254ZK/aggregator_test.go ````go package blsBn254ZK ⋮---- import ( "math/big" "testing" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" "testing" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- type mockProver struct{} ⋮---- func (m *mockProver) Prove(proveInput proof.ProveInput) (proof.ProofData, error) ⋮---- func (m *mockProver) Verify(valsetLen int, publicInputHash common.Hash, proofBytes []byte) (bool, error) ⋮---- func TestNewAggregator_WithProver_Success(t *testing.T) ⋮---- func TestNewAggregator_WithNilProver_Success(t *testing.T) ⋮---- func TestAggregator_Aggregate_WithMismatchedMessageHashes_ReturnsError(t *testing.T) ⋮---- func TestValidatorSetMimcAccumulator_WithNoValidators_ReturnsZeroHash(t *testing.T) ⋮---- func TestValidatorSetMimcAccumulator_WithActiveValidators_ReturnsHash(t *testing.T) ⋮---- func TestValidatorSetMimcAccumulator_WithSameValidators_ReturnsSameHash(t *testing.T) ⋮---- func TestValidatorSetMimcAccumulator_WithDifferentValidators_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestToValidatorsData_WithNoValidators_ReturnsNormalizedData(t *testing.T) ⋮---- func TestToValidatorsData_WithInactiveValidators_ReturnsNormalizedData(t *testing.T) ⋮---- func TestToValidatorsData_WithActiveValidators_ReturnsData(t *testing.T) ⋮---- func TestToValidatorsData_WithSigners_MarksSignersCorrectly(t *testing.T) ⋮---- func TestToValidatorsData_WithMixedSignersAndNonSigners_MarksCorrectly(t *testing.T) ⋮---- func TestAggregator_GenerateExtraData_WithValidValidators_ReturnsExtraData(t *testing.T) ⋮---- func TestAggregator_GenerateExtraData_WithMultipleKeyTags_ReturnsMultipleExtraData(t *testing.T) ⋮---- func TestAggregator_GenerateExtraData_ReturnsSortedData(t *testing.T) ⋮---- func TestAggregator_Verify_WithInvalidMessageHash_ReturnsError(t *testing.T) ⋮---- func TestAggregator_Verify_WithInsufficientVotingPower_ReturnsError(t *testing.T) ```` ## File: symbiotic/usecase/aggregator/blsBn254ZK/aggregator.go ````go package blsBn254ZK ⋮---- import ( "bytes" "math/big" "sort" "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" types "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/aggregator-types" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/helpers" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ) ⋮---- "bytes" "math/big" "sort" ⋮---- "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" types "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/aggregator-types" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/helpers" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ⋮---- type Aggregator struct { prover types.Prover } ⋮---- func NewAggregator(prover types.Prover) (*Aggregator, error) ⋮---- func (a Aggregator) Aggregate( valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, messageHash []byte, signatures []symbiotic.Signature, ) (symbiotic.AggregationProof, error) ⋮---- var validatorsData []proof.ValidatorData ⋮---- func (a Aggregator) Verify( valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag, aggregationProof symbiotic.AggregationProof, ) (bool, error) ⋮---- // last 32 bytes is aggVotingPowerBytes ⋮---- messageG1Bytes := messageG1.RawBytes() // non compressed ⋮---- func (a Aggregator) GenerateExtraData(valset symbiotic.ValidatorSet, keyTags []symbiotic.KeyTag) ([]symbiotic.ExtraData, error) ⋮---- // sort extra data by key to ensure deterministic order ⋮---- func validatorSetMimcAccumulator(valset []symbiotic.Validator, requiredKeyTag symbiotic.KeyTag) (common.Hash, error) ⋮---- func toValidatorsData(signerValidators []symbiotic.Validator, allValidators symbiotic.Validators, requiredKeyTag symbiotic.KeyTag) ([]proof.ValidatorData, error) ```` ## File: symbiotic/usecase/aggregator/helpers/helpers_test.go ````go package helpers ⋮---- import ( "math/big" "testing" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "math/big" "testing" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func TestCompareMessageHasher_WithMatchingHashes_ReturnsTrue(t *testing.T) ⋮---- func TestCompareMessageHasher_WithDifferentHash_ReturnsFalse(t *testing.T) ⋮---- func TestCompareMessageHasher_WithEmptySignatures_ReturnsTrue(t *testing.T) ⋮---- func TestCompareMessageHasher_WithSingleSignature_ReturnsCorrectResult(t *testing.T) ⋮---- func TestGetExtraDataKey_WithValidInputs_ReturnsHash(t *testing.T) ⋮---- func TestGetExtraDataKey_WithDifferentVerificationTypes_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestGetExtraDataKey_WithDifferentNameHashes_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestGetExtraDataKey_WithSameInputs_ReturnsSameHash(t *testing.T) ⋮---- func TestGetExtraDataKeyTagged_WithValidInputs_ReturnsHash(t *testing.T) ⋮---- func TestGetExtraDataKeyTagged_WithDifferentKeyTags_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestGetExtraDataKeyTagged_WithDifferentVerificationTypes_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestGetExtraDataKeyTagged_WithSameInputs_ReturnsSameHash(t *testing.T) ⋮---- func TestGetAggregatedPubKeys_WithNoValidators_ReturnsZeroPoint(t *testing.T) ⋮---- func TestGetAggregatedPubKeys_WithInactiveValidators_ReturnsZeroPoint(t *testing.T) ⋮---- func TestGetAggregatedPubKeys_WithSingleActiveValidator_ReturnsAggregatedKey(t *testing.T) ⋮---- func TestGetAggregatedPubKeys_WithMultipleActiveValidators_ReturnsAggregatedKey(t *testing.T) ⋮---- func TestGetAggregatedPubKeys_WithMixedActiveInactive_ReturnsOnlyActiveAggregation(t *testing.T) ⋮---- func TestGetAggregatedPubKeys_WithMultipleKeyTags_ReturnsMultipleAggregations(t *testing.T) ⋮---- func TestGetExtraDataKeyIndexed_WithValidInputs_ReturnsHash(t *testing.T) ⋮---- func TestGetExtraDataKeyIndexed_WithZeroIndex_EqualsBaseHash(t *testing.T) ⋮---- func TestGetExtraDataKeyIndexed_WithDifferentIndexes_ReturnsDifferentHashes(t *testing.T) ⋮---- func TestGetExtraDataKeyIndexed_WithLargeIndex_ReturnsHash(t *testing.T) ⋮---- func TestGetValidatorsIndexesMapByKey_WithNoValidators_ReturnsEmptyMap(t *testing.T) ⋮---- func TestGetValidatorsIndexesMapByKey_WithInactiveValidators_ReturnsEmptyMap(t *testing.T) ⋮---- func TestGetValidatorsIndexesMapByKey_WithSingleActiveValidator_ReturnsMapWithOneEntry(t *testing.T) ⋮---- func TestGetValidatorsIndexesMapByKey_WithMultipleActiveValidators_ReturnsMapWithAllEntries(t *testing.T) ⋮---- func TestGetValidatorsIndexesMapByKey_WithMixedActiveInactive_ReturnsOnlyActiveValidators(t *testing.T) ⋮---- func TestGetValidatorsIndexesMapByKey_WithNonMatchingKeyTag_ReturnsEmptyMap(t *testing.T) ⋮---- func TestGetValidatorsIndexesMapByKey_WithValidatorHavingMultipleKeys_OnlyMapsMatchingKeyTag(t *testing.T) ```` ## File: symbiotic/usecase/aggregator/helpers/helpers.go ````go package helpers ⋮---- import ( "bytes" "math/big" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "bytes" "math/big" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- func CompareMessageHasher(signatures []symbiotic.Signature, msgHash []byte) bool ⋮---- func GetExtraDataKey(verificationType symbiotic.VerificationType, nameHash common.Hash) (common.Hash, error) ⋮---- func GetExtraDataKeyTagged(verificationType symbiotic.VerificationType, keyTag symbiotic.KeyTag, nameHash common.Hash) (common.Hash, error) ⋮---- func GetAggregatedPubKeys( valset symbiotic.ValidatorSet, keyTags []symbiotic.KeyTag, ) []symbiotic.ValidatorKey ⋮---- // only bn254 bls for now ⋮---- // aggregate and save in map ⋮---- var aggregatedPubKeys []symbiotic.ValidatorKey ⋮---- // pack g1 point to bytes and add to list ⋮---- // will be used later func GetExtraDataKeyIndexed( verificationType symbiotic.VerificationType, keyTag symbiotic.KeyTag, nameHash common.Hash, index *big.Int, ) (common.Hash, error) ⋮---- var out common.Hash ⋮---- func GetValidatorsIndexesMapByKey(valset symbiotic.ValidatorSet, keyTag symbiotic.KeyTag) map[string]int ```` ## File: symbiotic/usecase/aggregator/aggregators_test.go ````go package aggregator ⋮---- import ( "encoding/hex" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254Simple" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254ZK" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" crypto2 "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ) ⋮---- "encoding/hex" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ⋮---- "github.com/symbioticfi/relay/pkg/proof" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254Simple" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254ZK" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" ⋮---- crypto2 "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ⋮---- type mockProver struct{} ⋮---- func (m *mockProver) Prove(proveInput proof.ProveInput) (proof.ProofData, error) ⋮---- func (m *mockProver) Verify(valsetLen int, publicInputHash common.Hash, proofBytes []byte) (bool, error) ⋮---- func TestSimpleAggregator(t *testing.T) ⋮---- func TestInvalidSimpleAggregator(t *testing.T) ⋮---- func TestSimpleAggregatorExtraData(t *testing.T) ⋮---- func TestAggregatorZKExtraData(t *testing.T) ⋮---- func TestZkAggregator(t *testing.T) ⋮---- func genExtraDataTest(t *testing.T) (symbiotic.ValidatorSet, symbiotic.KeyTag) ⋮---- var err error ⋮---- func genCorrectTest(numValidators int, nonSigners []int) (symbiotic.ValidatorSet, []symbiotic.Signature, symbiotic.KeyTag) ⋮---- func TestNewAggregator_WithBlsBn254Simple_ReturnsAggregator(t *testing.T) ⋮---- func TestNewAggregator_WithBlsBn254ZK_ReturnsAggregator(t *testing.T) ⋮---- func TestNewAggregator_WithUnsupportedType_ReturnsError(t *testing.T) ⋮---- func TestNewAggregator_WithDifferentTypes_ReturnsDifferentImplementations(t *testing.T) ```` ## File: symbiotic/usecase/aggregator/aggregators.go ````go package aggregator ⋮---- import ( symbiotic "github.com/symbioticfi/relay/symbiotic/entity" types "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/aggregator-types" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254Simple" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254ZK" "github.com/go-errors/errors" ) ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" types "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/aggregator-types" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254Simple" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator/blsBn254ZK" ⋮---- "github.com/go-errors/errors" ⋮---- func NewAggregator(verificationType symbiotic.VerificationType, prover Prover) (Aggregator, error) ```` ## File: symbiotic/usecase/crypto/bls12381Bn254/key_test.go ````go package bls12381Bn254 ⋮---- import ( "crypto/rand" "math/big" "testing" "github.com/stretchr/testify/require" ) ⋮---- "crypto/rand" "math/big" "testing" ⋮---- "github.com/stretchr/testify/require" ⋮---- func TestBLS12381Keys(t *testing.T) ⋮---- func TestCheckPrivateKeyBytes(t *testing.T) ⋮---- func TestMarshalText(t *testing.T) ⋮---- func TestInvalidVerification(t *testing.T) ⋮---- func TestFromRaw(t *testing.T) ⋮---- func randData(t *testing.T) []byte ```` ## File: symbiotic/usecase/crypto/bls12381Bn254/key.go ````go package bls12381Bn254 ⋮---- import ( "fmt" "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "fmt" "math/big" ⋮---- bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( RawKeyLength int = bls12381.SizeOfG1AffineCompressed + bls12381.SizeOfG2AffineCompressed MessageHashLength int = 32 hashToG1Domain = "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" ) ⋮---- type PublicKey struct { g1PubKey bls12381.G1Affine g2PubKey bls12381.G2Affine } ⋮---- type PrivateKey struct { privateKey *big.Int } ⋮---- func NewPrivateKey(b []byte) (*PrivateKey, error) ⋮---- func HashMessage(msg []byte) MessageHash ⋮---- func GenerateKey() (*PrivateKey, error) ⋮---- var err error ⋮---- func (k *PrivateKey) Bytes() []byte ⋮---- func (k *PrivateKey) Sign(msg []byte) (Signature, MessageHash, error) ⋮---- // symbiotic using keccak256 for hashing in bls12381-bn254 ⋮---- var g1Sig bls12381.G1Affine ⋮---- func HashToG1(data []byte) (*bls12381.G1Affine, error) ⋮---- func (k *PrivateKey) PublicKey() symbiotic.PublicKey ⋮---- func NewPublicKey(g1PubKey bls12381.G1Affine, g2PubKey bls12381.G2Affine) *PublicKey ⋮---- func (k *PublicKey) Verify(msg Message, sig Signature) error ⋮---- func (k *PublicKey) VerifyWithHash(msgHash MessageHash, sig Signature) error ⋮---- var negSig bls12381.G1Affine ⋮---- // OnChain might be one way operation, meaning that it's impossible to reconstruct PublicKey from compact func (k *PublicKey) OnChain() CompactPublicKey ⋮---- func (k *PublicKey) Raw() RawPublicKey ⋮---- // combined g1 and g2 [compressed] ⋮---- func (k *PublicKey) G2() *bls12381.G2Affine ⋮---- func (k *PublicKey) MarshalText() ([]byte, error) ⋮---- func FromRaw(rawKey RawPublicKey) (*PublicKey, error) ⋮---- var g1 bls12381.G1Affine var g2 bls12381.G2Affine ⋮---- func FromPrivateKey(privateKey *PrivateKey) symbiotic.PublicKey ```` ## File: symbiotic/usecase/crypto/blsBn254/key_test.go ````go package blsBn254 ⋮---- import ( "crypto/rand" "math/big" "testing" "github.com/stretchr/testify/require" ) ⋮---- "crypto/rand" "math/big" "testing" ⋮---- "github.com/stretchr/testify/require" ⋮---- func TestBLSKeys(t *testing.T) ⋮---- func TestCheckPrivateKeyBytes(t *testing.T) ⋮---- func TestMarshallText(t *testing.T) ⋮---- func TestInvalidVerification(t *testing.T) ⋮---- func TestFromRaw(t *testing.T) ⋮---- func randData(t *testing.T) []byte ```` ## File: symbiotic/usecase/crypto/blsBn254/key.go ````go package blsBn254 ⋮---- import ( "fmt" "math/big" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "fmt" "math/big" ⋮---- "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( RawKeyLength int = 96 MessageHashLength int = 32 ) ⋮---- type PublicKey struct { g1PubKey bn254.G1Affine g2PubKey bn254.G2Affine } ⋮---- type PrivateKey struct { privateKey *big.Int } ⋮---- func NewPrivateKey(b []byte) (*PrivateKey, error) ⋮---- func HashMessage(msg []byte) MessageHash ⋮---- func GenerateKey() (*PrivateKey, error) ⋮---- var err error ⋮---- func (k *PrivateKey) Bytes() []byte ⋮---- func (k *PrivateKey) Sign(msg []byte) (Signature, MessageHash, error) ⋮---- // symbiotic using keccak256 for hashing in bls-bn254 ⋮---- // returns non compressed G1 point ⋮---- func HashToG1(data []byte) (*bn254.G1Affine, error) ⋮---- // Convert data to a big integer ⋮---- // Ensure x is within the field ⋮---- // Find y coordinate for the current x ⋮---- // Check if y^2 == beta ⋮---- // Create a G1 point with the found coordinates var point bn254.G1Affine ⋮---- // Increment x and try again ⋮---- // FindYFromX calculates the y coordinate for a given x on the BN254 curve // Returns (beta, y) where beta = x^3 + 3 (mod p) and y = sqrt(beta) if it exists func findYFromX(x *big.Int) (beta *big.Int, y *big.Int, err error) ⋮---- // Calculate beta = x^3 + 3 mod p beta = new(big.Int).Exp(x, big.NewInt(3), fpModulus) // x^3 beta.Add(beta, big.NewInt(3)) // x^3 + 3 beta.Mod(beta, fpModulus) // (x^3 + 3) mod p ⋮---- // Calculate y = beta^((p+1)/4) mod p // The exponent (p+1)/4 for BN254 is 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52 ⋮---- func (k *PrivateKey) PublicKey() symbiotic.PublicKey ⋮---- // Get the generators for G1 and G2 ⋮---- // Compute public keys by scalar multiplication with generators ⋮---- func NewPublicKey(g1PubKey bn254.G1Affine, g2PubKey bn254.G2Affine) *PublicKey ⋮---- func (k *PublicKey) Verify(msg Message, sig Signature) error ⋮---- // Hash the message to a point on G1 ⋮---- // Get the G2 generator ⋮---- var negSig bn254.G1Affine ⋮---- func (k *PublicKey) VerifyWithHash(msgHash MessageHash, sig Signature) error ⋮---- // OnChain might be one way operation, meaning that it's impossible to reconstruct PublicKey from compact func (k *PublicKey) OnChain() CompactPublicKey ⋮---- func (k *PublicKey) Raw() RawPublicKey ⋮---- // combined g1 and g2 [compressed] ⋮---- func (k *PublicKey) G2() *bn254.G2Affine ⋮---- func (k *PublicKey) MarshalText() (text []byte, err error) ⋮---- func FromRaw(rawKey RawPublicKey) (*PublicKey, error) ⋮---- func FromPrivateKey(privateKey *PrivateKey) symbiotic.PublicKey ```` ## File: symbiotic/usecase/crypto/ecdsaSecp256k1/key_test.go ````go package ecdsaSecp256k1 ⋮---- import ( "crypto/rand" "math/big" "testing" "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" ) ⋮---- "crypto/rand" "math/big" "testing" ⋮---- "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" ⋮---- func TestECDSAKeys(t *testing.T) ⋮---- func TestCheckPrivateKeyBytes(t *testing.T) ⋮---- func TestMakePrivateFromNumber(t *testing.T) ⋮---- func TestMarshallText(t *testing.T) ⋮---- func TestInvalidVerification(t *testing.T) ⋮---- func TestFromRaw(t *testing.T) ⋮---- func randData(t *testing.T) []byte ```` ## File: symbiotic/usecase/crypto/ecdsaSecp256k1/key.go ````go package ecdsaSecp256k1 ⋮---- import ( "crypto/ecdsa" "math/big" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ) ⋮---- "crypto/ecdsa" "math/big" ⋮---- "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" ⋮---- const ( RawKeyLength int = 33 MessageHashLength int = 32 ) ⋮---- type PublicKey struct { pubKey ecdsa.PublicKey } ⋮---- type PrivateKey struct { privateKey ecdsa.PrivateKey } ⋮---- func NewPrivateKey(b []byte) (*PrivateKey, error) ⋮---- if kInt.BitLen() > 32*8 { // 32 bytes = 256 bits ⋮---- func HashMessage(msg []byte) MessageHash ⋮---- func GenerateKey() (*PrivateKey, error) ⋮---- func (k *PrivateKey) Bytes() []byte ⋮---- func (k *PrivateKey) Sign(msg []byte) (Signature, MessageHash, error) ⋮---- // symbiotic using keccak256 for hashing in ecdsaSecp256k1 ⋮---- func (k *PrivateKey) PublicKey() symbiotic.PublicKey ⋮---- func NewPublicKey(x *big.Int, y *big.Int) *PublicKey ⋮---- func (k *PublicKey) Verify(msg Message, sig Signature) error ⋮---- func (k *PublicKey) VerifyWithHash(msgHash MessageHash, sig Signature) error ⋮---- // Remove recovery ID from signature for verification ⋮---- // OnChain might be one way operation, meaning that it's impossible to reconstruct PublicKey from compact func (k *PublicKey) OnChain() CompactPublicKey ⋮---- // returns eth address in this case, left-padded to 32 bytes to match logic in contracts // see https://github.com/symbioticfi/relay-contracts/blob/abcf4d7bb151780094d3a67cce7431300ecd5e31/src/contracts/libraries/keys/KeyEcdsaSecp256k1.sol#L41 ⋮---- func (k *PublicKey) Raw() RawPublicKey ⋮---- // returns 33 bytes compressed pubKey ⋮---- func (k *PublicKey) MarshalText() (text []byte, err error) ⋮---- func FromRaw(rawKey RawPublicKey) (*PublicKey, error) ⋮---- func FromPrivateKey(privateKey *PrivateKey) symbiotic.PublicKey ```` ## File: symbiotic/usecase/crypto/keys.go ````go package crypto ⋮---- import ( "sync" "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/client/repository/cache" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/bls12381Bn254" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/ecdsaSecp256k1" ) ⋮---- "sync" ⋮---- "github.com/go-errors/errors" "github.com/symbioticfi/relay/internal/client/repository/cache" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/bls12381Bn254" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/blsBn254" "github.com/symbioticfi/relay/symbiotic/usecase/crypto/ecdsaSecp256k1" ⋮---- var ( pubKeyCache cache.Cache[pubKeyCacheKey, symbiotic.PublicKey] initCacheOnce sync.Once ) ⋮---- // InitializePubkeyCache initializes the public key cache with the given size. // Dev: Should be called only once during application startup. func InitializePubkeyCache(cacheSize int) (err error) ⋮---- // FNV-1a 32-bit hash const ( offset32 = uint32(2166136261) ⋮---- // Process each byte of the key string ⋮---- type pubKeyCacheKey struct { keyTag symbiotic.KeyType key string } ⋮---- func NewPublicKey(keyType symbiotic.KeyType, keyBytes symbiotic.RawPublicKey) (PublicKey, error) ⋮---- // Try cache first ⋮---- var ( pubkey PublicKey err error ) ⋮---- func NewPrivateKey(keyType symbiotic.KeyType, keyBytes []byte) (PrivateKey, error) ⋮---- func HashMessage(keyType symbiotic.KeyType, msg []byte) (symbiotic.RawMessageHash, error) ⋮---- func GeneratePrivateKey(keyType symbiotic.KeyType) (PrivateKey, error) ```` ## File: symbiotic/usecase/ssz/ssz.go ````go // Hash: 8c67e0de1079a95336f540c6c73e42f4633fd2cb9841d83ab84b052439e4f3c7 // Version: 0.1.3 package ssz ⋮---- import ( "sort" ssz "github.com/ferranbt/fastssz" "github.com/go-errors/errors" "github.com/ethereum/go-ethereum/common" ) ⋮---- "sort" ⋮---- ssz "github.com/ferranbt/fastssz" "github.com/go-errors/errors" ⋮---- "github.com/ethereum/go-ethereum/common" ⋮---- const ( ValidatorsListLocalPosition = 0 OperatorLocalPosition = 0 ValidatorVotingPowerLocalPosition = 1 IsActiveLocalPosition = 2 KeysListLocalPosition = 3 VaultsListLocalPosition = 4 TagLocalPosition = 0 PayloadHashLocalPosition = 1 ChainIdLocalPosition = 0 VaultLocalPosition = 1 VaultVotingPowerLocalPosition = 2 ) ⋮---- const ( ValidatorSetElements = 1 ValidatorSetTreeHeight = 0 // ceil(log2(ValidatorSetElements)) ⋮---- ValidatorSetTreeHeight = 0 // ceil(log2(ValidatorSetElements)) ⋮---- ValidatorTreeHeight = 3 // ceil(log2(ValidatorElements)) ⋮---- VaultTreeHeight = 2 // ceil(log2(VaultElements)) ⋮---- KeyTreeHeight = 1 // ceil(log2(KeyElements)) ⋮---- ValidatorsListTreeHeight = 20 // ceil(log2(ValidatorsListMaxElements)) ⋮---- KeysListTreeHeight = 7 // ceil(log2(KeysListMaxElements)) ⋮---- VaultsListTreeHeight = 10 // ceil(log2(VaultsListMaxElements)) ⋮---- // MarshalSSZ ssz marshals the Key object func (k *SszKey) MarshalSSZ() ([]byte, error) ⋮---- // MarshalSSZTo ssz marshals the Key object to a target array func (k *SszKey) MarshalSSZTo(buf []byte) ([]byte, error) ⋮---- // Field (0) 'Tag' ⋮---- // Field (1) 'PayloadHash' ⋮---- // UnmarshalSSZ ssz unmarshals the Key object func (k *SszKey) UnmarshalSSZ(buf []byte) error ⋮---- var err error ⋮---- // SizeSSZ returns the ssz encoded size in bytes for the Key object func (k *SszKey) SizeSSZ() int ⋮---- // HashTreeRoot ssz hashes the Key object func (k *SszKey) HashTreeRoot() ([32]byte, error) ⋮---- // HashTreeRootWith ssz hashes the Key object with a hasher func (k *SszKey) HashTreeRootWith(hh ssz.HashWalker) error ⋮---- // GetTree ssz hashes the Key object func (k *SszKey) GetTree() (*ssz.Node, error) ⋮---- // MarshalSSZ ssz marshals the Vault object ⋮---- // MarshalSSZTo ssz marshals the Vault object to a target array ⋮---- // Field (0) 'ChainId' ⋮---- // Field (1) 'OperatorVault' ⋮---- // Field (2) 'VotingPower' ⋮---- // UnmarshalSSZ ssz unmarshals the Vault object ⋮---- // SizeSSZ returns the ssz encoded size in bytes for the Vault object ⋮---- // HashTreeRoot ssz hashes the Vault object ⋮---- // HashTreeRootWith ssz hashes the Vault object with a hasher ⋮---- // GetTree ssz hashes the Vault object ⋮---- // MarshalSSZ ssz marshals the Validator object ⋮---- // MarshalSSZTo ssz marshals the Validator object to a target array ⋮---- // Field (0) 'Operator' ⋮---- // Field (1) 'VotingPower' ⋮---- // Field (2) 'IsActive' ⋮---- // Offset (3) 'Keys' ⋮---- // Offset (4) 'Vaults' ⋮---- // Field (3) 'Keys' ⋮---- var err error ⋮---- // Field (4) 'Vaults' ⋮---- // UnmarshalSSZ ssz unmarshals the Validator object ⋮---- var o3, o4 uint64 ⋮---- // SizeSSZ returns the ssz encoded size in bytes for the Validator object ⋮---- // HashTreeRoot ssz hashes the Validator object ⋮---- // HashTreeRootWith ssz hashes the Validator object with a hasher ⋮---- // GetTree ssz hashes the Validator object ⋮---- // MarshalSSZ ssz marshals the SszValidatorSet object ⋮---- // MarshalSSZTo ssz marshals the SszValidatorSet object to a target array ⋮---- // Offset (0) 'Validators' ⋮---- // Field (0) 'Validators' ⋮---- // UnmarshalSSZ ssz unmarshalls the SszValidatorSet object ⋮---- var o0 uint64 ⋮---- // SizeSSZ returns the ssz encoded size in bytes for the SszValidatorSet object ⋮---- // HashTreeRoot ssz hashes the SszValidatorSet object ⋮---- // HashTreeRootWith ssz hashes the SszValidatorSet object with a hasher ⋮---- // GetTree ssz hashes the SszValidatorSet object ⋮---- //nolint:revive // function-result-limit: This function needs to return multiple complex types for cryptographic operations func (v *SszValidatorSet) ProveValidatorRoot(operator common.Address) (*SszValidator, int, *ssz.Proof, error) ⋮---- // go to SszValidatorSet.Validators ⋮---- // consider List's length mix-in ⋮---- // go to SszValidatorSet.Validators[validatorIndex] ⋮---- func (v *SszValidator) ProveValidatorOperator() (*ssz.Proof, error) ⋮---- // go to Validator.Operator ⋮---- func (v *SszValidator) ProveValidatorVotingPower() (*ssz.Proof, error) ⋮---- // go to Validator.VotingPower ⋮---- func (v *SszValidator) ProveValidatorIsActive() (*ssz.Proof, error) ⋮---- // go to Validator.IsActive ⋮---- func (v *SszValidator) ProveKeyRoot(keyTag uint8) (*SszKey, int, *ssz.Proof, error) ⋮---- // go to Validator.Keys ⋮---- // go to Validator.Keys[keyIndex] ⋮---- func (k *SszKey) ProveKeyTag() (*ssz.Proof, error) ⋮---- // go to Key.Tag ⋮---- func (k *SszKey) ProveKeyPayloadHash() (*ssz.Proof, error) ⋮---- // go to Key.PayloadHash ⋮---- func (v *SszValidator) ProveVaultRoot(vault common.Address) (*SszVault, int, *ssz.Proof, error) ⋮---- // go to Validator.Vaults ⋮---- // go to Validator.Vaults[vaultIndex] ⋮---- func (v *SszVault) ProveVaultChainId() (*ssz.Proof, error) ⋮---- // go to Vault.ChainId ⋮---- func (v *SszVault) ProveVaultVault() (*ssz.Proof, error) ⋮---- // go to Vault.Vault ⋮---- func (v *SszVault) ProveVaultVotingPower() (*ssz.Proof, error) ⋮---- // go to Vault.VotingPower ```` ## File: symbiotic/usecase/ssz/types.go ````go package ssz ⋮---- import ( "math/big" "github.com/ethereum/go-ethereum/common" ) ⋮---- "math/big" ⋮---- "github.com/ethereum/go-ethereum/common" ⋮---- type SszKey struct { Tag uint8 `ssz-size:"1"` Payload []byte PayloadHash [32]byte `ssz-size:"32"` } ⋮---- type SszVault struct { ChainId uint64 `ssz-size:"8"` Vault common.Address `ssz-size:"20"` VotingPower *big.Int `ssz-size:"32"` } ⋮---- type SszValidator struct { Operator common.Address `ssz-size:"20"` VotingPower *big.Int `ssz-size:"32"` IsActive bool `ssz-size:"1"` Keys []*SszKey `ssz-max:"128"` Vaults []*SszVault `ssz-max:"1024"` } ⋮---- type SszValidatorSet struct { Version uint8 Validators []*SszValidator `ssz-max:"1048576"` } ```` ## File: symbiotic/usecase/valset-deriver/mocks/deriver.go ````go // Code generated by MockGen. DO NOT EDIT. // Source: valset_deriver.go // // Generated by this command: ⋮---- // mockgen -source=valset_deriver.go -destination=mocks/deriver.go -package=mocks -mock_names=evmClient=MockEvmClient ⋮---- // Package mocks is a generated GoMock package. package mocks ⋮---- import ( context "context" reflect "reflect" common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ) ⋮---- context "context" reflect "reflect" ⋮---- common "github.com/ethereum/go-ethereum/common" entity "github.com/symbioticfi/relay/symbiotic/entity" gomock "go.uber.org/mock/gomock" ⋮---- // MockEvmClient is a mock of evmClient interface. type MockEvmClient struct { ctrl *gomock.Controller recorder *MockEvmClientMockRecorder isgomock struct{} ⋮---- // MockEvmClientMockRecorder is the mock recorder for MockEvmClient. type MockEvmClientMockRecorder struct { mock *MockEvmClient } ⋮---- // NewMockEvmClient creates a new mock instance. func NewMockEvmClient(ctrl *gomock.Controller) *MockEvmClient ⋮---- // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockEvmClient) EXPECT() *MockEvmClientMockRecorder ⋮---- // GetConfig mocks base method. func (m *MockEvmClient) GetConfig(ctx context.Context, timestamp entity.Timestamp, epoch entity.Epoch) (entity.NetworkConfig, error) ⋮---- // GetConfig indicates an expected call of GetConfig. ⋮---- // GetCurrentEpoch mocks base method. func (m *MockEvmClient) GetCurrentEpoch(ctx context.Context) (entity.Epoch, error) ⋮---- // GetCurrentEpoch indicates an expected call of GetCurrentEpoch. ⋮---- // GetEip712Domain mocks base method. func (m *MockEvmClient) GetEip712Domain(ctx context.Context, addr entity.CrossChainAddress) (entity.Eip712Domain, error) ⋮---- // GetEip712Domain indicates an expected call of GetEip712Domain. ⋮---- // GetEpochStart mocks base method. func (m *MockEvmClient) GetEpochStart(ctx context.Context, epoch entity.Epoch) (entity.Timestamp, error) ⋮---- // GetEpochStart indicates an expected call of GetEpochStart. ⋮---- // GetHeaderHash mocks base method. func (m *MockEvmClient) GetHeaderHash(ctx context.Context, addr entity.CrossChainAddress) (common.Hash, error) ⋮---- // GetHeaderHash indicates an expected call of GetHeaderHash. ⋮---- // GetHeaderHashAt mocks base method. func (m *MockEvmClient) GetHeaderHashAt(ctx context.Context, addr entity.CrossChainAddress, epoch entity.Epoch) (common.Hash, error) ⋮---- // GetHeaderHashAt indicates an expected call of GetHeaderHashAt. ⋮---- // GetKeys mocks base method. func (m *MockEvmClient) GetKeys(ctx context.Context, address entity.CrossChainAddress, timestamp entity.Timestamp) ([]entity.OperatorWithKeys, error) ⋮---- // GetKeys indicates an expected call of GetKeys. ⋮---- // GetLastCommittedHeaderEpoch mocks base method. func (m *MockEvmClient) GetLastCommittedHeaderEpoch(ctx context.Context, addr entity.CrossChainAddress, opts ...entity.EVMOption) (entity.Epoch, error) ⋮---- // GetLastCommittedHeaderEpoch indicates an expected call of GetLastCommittedHeaderEpoch. ⋮---- // GetNetworkAddress mocks base method. func (m *MockEvmClient) GetNetworkAddress(ctx context.Context) (common.Address, error) ⋮---- // GetNetworkAddress indicates an expected call of GetNetworkAddress. ⋮---- // GetOperators mocks base method. func (m *MockEvmClient) GetOperators(ctx context.Context, address entity.CrossChainAddress, timestamp entity.Timestamp) ([]common.Address, error) ⋮---- // GetOperators indicates an expected call of GetOperators. ⋮---- // GetSubnetwork mocks base method. func (m *MockEvmClient) GetSubnetwork(ctx context.Context) (common.Hash, error) ⋮---- // GetSubnetwork indicates an expected call of GetSubnetwork. ⋮---- // GetVotingPowers mocks base method. func (m *MockEvmClient) GetVotingPowers(ctx context.Context, address entity.CrossChainAddress, timestamp entity.Timestamp) ([]entity.OperatorVotingPower, error) ⋮---- // GetVotingPowers indicates an expected call of GetVotingPowers. ⋮---- // IsValsetHeaderCommittedAt mocks base method. func (m *MockEvmClient) IsValsetHeaderCommittedAt(ctx context.Context, addr entity.CrossChainAddress, epoch entity.Epoch, opts ...entity.EVMOption) (bool, error) ⋮---- // IsValsetHeaderCommittedAt indicates an expected call of IsValsetHeaderCommittedAt. ```` ## File: symbiotic/usecase/valset-deriver/valset_deriver_test.go ````go package valsetDeriver ⋮---- import ( "context" "fmt" "math/big" "slices" "testing" "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/ssz" "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ) ⋮---- "context" "fmt" "math/big" "slices" "testing" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/go-errors/errors" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/ssz" "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver/mocks" ⋮---- func TestDeriver_calcQuorumThreshold(t *testing.T) ⋮---- QuorumThreshold: symbiotic.ToQuorumThresholdPct(big.NewInt(670000000000000000)), // 67% ⋮---- expectedQuorum: big.NewInt(1000*.67 + 1), // (1000 * 67% + 1) ⋮---- QuorumThreshold: symbiotic.ToQuorumThresholdPct(big.NewInt(750000000000000000)), // 75% ⋮---- expectedQuorum: big.NewInt(2000*.75 + 1), // (2000 * 75% + 1) ⋮---- func TestDeriver_fillValidators(t *testing.T) ⋮---- func TestDeriver_fillValidatorsActive(t *testing.T) ⋮---- expectedActiveValidators []common.Address // operator addresses that should be active expectedInactiveValidators []common.Address // operator addresses that should be inactive expectedVotingPowers map[string]*big.Int // operator -> expected voting power after capping ⋮---- MaxVotingPower: symbiotic.ToVotingPower(big.NewInt(0)), // no max limit MaxValidatorsCount: symbiotic.ToVotingPower(big.NewInt(0)), // no max count ⋮---- expectedTotalVotingPower: big.NewInt(700), // 500 + 200 ⋮---- expectedInactiveValidators: []common.Address{common.HexToAddress("0x789")}, // below minimum ⋮---- "0x789": big.NewInt(50), // unchanged but inactive ⋮---- Keys: []symbiotic.ValidatorKey{}, // no keys ⋮---- expectedInactiveValidators: []common.Address{common.HexToAddress("0x456")}, // no keys ⋮---- expectedTotalVotingPower: big.NewInt(600), // 400 (capped) + 200 ⋮---- "0x123": big.NewInt(400), // capped from 600 ⋮---- expectedTotalVotingPower: big.NewInt(900), // 500 + 400 (only first 2 validators) ⋮---- expectedInactiveValidators: []common.Address{common.HexToAddress("0x789")}, // exceeds max count ⋮---- expectedTotalVotingPower: big.NewInt(550), // 350 (capped from 500) + 200 ⋮---- expectedInactiveValidators: []common.Address{common.HexToAddress("0x789"), common.HexToAddress("0xabc")}, // 0x789 exceeds max count, 0xabc below min power ⋮---- "0x123": big.NewInt(350), // capped from 500 ⋮---- // Make a copy of validators to avoid modifying the test data ⋮---- // Check total voting power ⋮---- // Check active validators var activeValidators []common.Address var inactiveValidators []common.Address ⋮---- // Check voting power (capping) ⋮---- func TestDeriver_GetNetworkData(t *testing.T) ⋮---- func TestDeriver_fillValidators_VaultLimitExceeded(t *testing.T) ⋮---- // This test verifies vault truncation when exceeding ssz.VaultsListMaxElements (1024) // Expected behavior: // 1. Sort vaults by voting power DESC, then vault address ASC // 2. Truncate to keep only top 1024 vaults // 3. Re-sort remaining vaults by vault address ASC only ⋮---- const ( highPowerVaults = 5 mediumPowerVaults = 5 extraVaults = 10 // Create more than the 1024 limit highPower = 2000 mediumPower = 1500 lowPower = 1000 ) ⋮---- extraVaults = 10 // Create more than the 1024 limit ⋮---- // Create test vaults with different voting powers ⋮---- var power int64 ⋮---- // Setup test data ⋮---- // Execute ⋮---- // Verify results ⋮---- // All high and medium power vaults should be kept ⋮---- // Remaining slots filled with low power vaults ⋮---- func TestDeriver_GetSchedulerInfo(t *testing.T) ⋮---- // These expected values are deterministic based on the hash calculation expectedAggIndices: []uint32{2, 0}, // Calculated deterministically from hash expectedCommIndices: []uint32{1}, // Calculated deterministically from hash ⋮---- func TestDeriver_GetSchedulerInfo_Deterministic(t *testing.T) ⋮---- // Test that GetSchedulerInfo returns consistent results for the same inputs ⋮---- // Run the same calculation multiple times const iterations = 10 var firstAggIndices, firstCommIndices []uint32 ⋮---- func TestDeriver_GetSchedulerInfo_VerifyRandomness(t *testing.T) ⋮---- // Test that different inputs produce different results ⋮---- // Get results for original valset ⋮---- // Test with different epoch ⋮---- // Note: Different epochs might produce the same results due to hash collisions, // but we can verify they run without error ⋮---- // Test with different timestamp ⋮---- // Results should be different for different timestamps (high probability) ⋮---- func TestDeriver_findNextAvailableIndex(t *testing.T) ⋮---- // Verify the result is not in usedIndices ⋮---- // Verify the result is within bounds ⋮---- func TestDeriver_findNextAvailableIndex_Panic(t *testing.T) ⋮---- // Test that the function panics when no indices are available ⋮---- // Create a scenario where all indices are taken ```` ## File: symbiotic/usecase/valset-deriver/valset_deriver.go ````go package valsetDeriver ⋮---- import ( "context" "log/slog" "maps" "math/big" "slices" "strconv" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/samber/lo" symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/ssz" ) ⋮---- "context" "log/slog" "maps" "math/big" "slices" "strconv" ⋮---- "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/go-errors/errors" "github.com/samber/lo" ⋮---- symbiotic "github.com/symbioticfi/relay/symbiotic/entity" "github.com/symbioticfi/relay/symbiotic/usecase/ssz" ⋮---- const ( valsetVersion = 1 aggregatorRoleType = "AGGREGATOR" committerRoleType = "COMMITTER" ) ⋮---- //go:generate mockgen -source=valset_deriver.go -destination=mocks/deriver.go -package=mocks -mock_names=evmClient=MockEvmClient type evmClient interface { GetConfig(ctx context.Context, timestamp symbiotic.Timestamp, epoch symbiotic.Epoch) (symbiotic.NetworkConfig, error) GetEpochStart(ctx context.Context, epoch symbiotic.Epoch) (symbiotic.Timestamp, error) GetVotingPowers(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) ([]symbiotic.OperatorVotingPower, error) GetKeys(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) ([]symbiotic.OperatorWithKeys, error) GetEip712Domain(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.Eip712Domain, error) GetCurrentEpoch(ctx context.Context) (symbiotic.Epoch, error) GetSubnetwork(ctx context.Context) (common.Hash, error) GetNetworkAddress(ctx context.Context) (common.Address, error) GetHeaderHash(ctx context.Context, addr symbiotic.CrossChainAddress) (common.Hash, error) IsValsetHeaderCommittedAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch, opts ...symbiotic.EVMOption) (bool, error) GetHeaderHashAt(ctx context.Context, addr symbiotic.CrossChainAddress, epoch symbiotic.Epoch) (common.Hash, error) GetLastCommittedHeaderEpoch(ctx context.Context, addr symbiotic.CrossChainAddress, opts ...symbiotic.EVMOption) (symbiotic.Epoch, error) GetOperators(ctx context.Context, address symbiotic.CrossChainAddress, timestamp symbiotic.Timestamp) ([]common.Address, error) } ⋮---- // Deriver coordinates the ETH services type Deriver struct { evmClient evmClient } ⋮---- // NewDeriver creates a new valset deriver func NewDeriver(evmClient evmClient) (*Deriver, error) ⋮---- func (v *Deriver) GetNetworkData(ctx context.Context, addr symbiotic.CrossChainAddress) (symbiotic.NetworkData, error) ⋮---- type dtoOperatorVotingPower struct { chainId uint64 votingPowers []symbiotic.OperatorVotingPower } ⋮---- func (v *Deriver) GetValidatorSet(ctx context.Context, epoch symbiotic.Epoch, config symbiotic.NetworkConfig) (symbiotic.ValidatorSet, error) ⋮---- // Get voting powers from all voting power providers ⋮---- // Get keys from the keys provider ⋮---- // form validators list from voting powers and keys using config ⋮---- // calc new quorum threshold ⋮---- AggregatorIndices: nil, // will be initialized later CommitterIndices: nil, // will be initialized later ⋮---- func GetSchedulerInfo(_ context.Context, valset symbiotic.ValidatorSet, config symbiotic.NetworkConfig) (aggIndices []uint32, commIndices []uint32, err error) ⋮---- // ensure validators sorted already, function expects sorted list ⋮---- // Helper function for wrap-around search func findNextAvailableIndex(startIndex uint32, validatorCount int, usedIndices map[uint32]struct ⋮---- // This should never happen if we don't request more roles than available validators ⋮---- func (v *Deriver) formValidators( config symbiotic.NetworkConfig, votingPowers []dtoOperatorVotingPower, keys []symbiotic.OperatorWithKeys, ) symbiotic.Validators ⋮---- func markValidatorsActive(config symbiotic.NetworkConfig, validators symbiotic.Validators) ⋮---- // Check minimum voting power if configured ⋮---- // Check if validator has at least one key ⋮---- func fillValidators(votingPowers []dtoOperatorVotingPower, keys []symbiotic.OperatorWithKeys) symbiotic.Validators ⋮---- // Create validators map to consolidate voting powers and keys ⋮---- // Process voting powers ⋮---- IsActive: false, // Default to active, will filter later ⋮---- // Add vaults and their voting powers ⋮---- // Add vault to validator's vaults ⋮---- // filter by ssz max-vaults limit ⋮---- // Process required keys for _, rk := range keys { // TODO: get required key tags from validator set config and fill with nils if needed ⋮---- // Add all keys for this operator ⋮---- // filter by ssz max-validators limit ```` ## File: symbiotic/symbiotic.go ````go package symbiotic ⋮---- import ( "github.com/symbioticfi/relay/symbiotic/client/evm" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ) ⋮---- "github.com/symbioticfi/relay/symbiotic/client/evm" "github.com/symbioticfi/relay/symbiotic/usecase/aggregator" "github.com/symbioticfi/relay/symbiotic/usecase/crypto" valsetDeriver "github.com/symbioticfi/relay/symbiotic/usecase/valset-deriver" ```` ## File: .dockerignore ```` # Ignore build outputs dist out # Ignore environment files .env .env.* # Ignore Docker-related files Dockerfile docker-compose.yml # Ignore version control files .git .gitignore # Ignore editor and OS-specific files *.swp *.DS_Store Thumbs.db e2e/ # Ignore IDE-specific files .idea/ .vscode/ .claude/ ```` ## File: .env.example ```` PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 ETH_RPC_URL_MASTER=http://127.0.0.1:8545 EPOCH_DURATION=60 DEPLOYMENT_BUFFER=600 SLASHING_WINDOW=1200 BLOCK_TIME=1 OPERATORS=4 VERIFICATION_TYPE=1 ```` ## File: .gitignore ```` .idea/ .claude/ .local/ CLAUDE.md go.sum .env .DS_Store .data* coverage.txt pkg/proof/circuits e2e/contracts e2e/temp-network ```` ## File: .gitmodules ```` [submodule "relay-bn254-example-circuit-keys"] path = circuits url = git@github.com:symbioticfi/relay-bn254-example-circuit-keys.git ```` ## File: .golangci.yml ````yaml version: "2" run: go: "1.25" build-tags: - integration tests: true linters: default: none enable: - asasalint - asciicheck - bidichk - bodyclose - contextcheck - copyloopvar - decorder # - dogsled - durationcheck - embeddedstructfieldcheck - errchkjson - errname - errorlint - exhaustive - exhaustruct - exptostd - fatcontext - forbidigo - funcorder - gocheckcompilerdirectives - gochecknoinits - gochecksumtype - goconst - gocritic # - godox - gomoddirectives - gomodguard - goprintffuncname - gosec - govet - grouper - importas - inamedparam - ineffassign - iotamixing - loggercheck - makezero - mirror - misspell - musttag - nakedret - nilerr - nilnesserr - noctx - nolintlint - nosprintfhostport - perfsprint - prealloc - predeclared - protogetter - reassign - revive - rowserrcheck - sloglint - spancheck - sqlclosecheck - staticcheck - testableexamples - testifylint - thelper - tparallel - unconvert - unparam - unused - usestdlibvars - usetesting - wastedassign - whitespace # - wrapcheck settings: gomoddirectives: replace-allow-list: - github.com/consensys/gnark - github.com/consensys/gnark-crypto importas: alias: - pkg: github.com/symbioticfi/relay/internal/gen/api/v1 alias: apiv1 cyclop: max-complexity: 30 package-average: 10 errcheck: check-type-assertions: true exhaustive: check: - switch - map exhaustruct: allow-empty-returns: true allow-empty: true include: - ^github.com/symbioticfi/relay/internal/client/repository/.*$ - ^github.com/symbioticfi/relay/internal/client/p2p/proto/.*$ - ^github.com/symbioticfi/relay/internal/gen/.*$ - ^github.com/symbioticfi/relay/internal/entity/.*$ - ^github.com/symbioticfi/relay/core/entity/.*$ - ^github.com/symbioticfi/relay/core/entity/.*$ exclude: - ^github.com/symbioticfi/relay/internal/client/repository/badger.Repository$ - ^github.com/ethereum/go-ethereum.CallMsg$ funlen: lines: 100 statements: 50 ignore-comments: true gocognit: min-complexity: 20 gocritic: disabled-checks: - commentFormatting - ifElseChain - appendAssign settings: captLocal: paramsOnly: false underef: skipRecvDeref: false gomodguard: blocked: modules: - github.com/golang/protobuf: recommendations: - google.golang.org/protobuf reason: see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules - github.com/satori/go.uuid: recommendations: - github.com/google/uuid reason: satori's package is not maintained - github.com/gofrs/uuid: recommendations: - github.com/gofrs/uuid/v5 reason: gofrs' package was not go module before v5 govet: disable: - fieldalignment enable-all: true settings: shadow: strict: true inamedparam: skip-single-param: true mnd: ignored-functions: - args.Error - flag.Arg - flag.Duration.* - flag.Float.* - flag.Int.* - flag.Uint.* - os.Chmod - os.Mkdir.* - os.OpenFile - os.WriteFile - prometheus.ExponentialBuckets.* - prometheus.LinearBuckets nolintlint: require-explanation: true require-specific: true allow-no-explanation: - funlen - gocognit - lll perfsprint: strconcat: false revive: severity: warning rules: - name: atomic - name: banned-characters - name: bare-return - name: bool-literal-in-expr - name: call-to-gc - name: comments-density - name: confusing-results - name: constant-logical-expr - name: context-as-argument - name: context-keys-type - name: datarace - name: deep-exit - name: defer - name: dot-imports - name: duplicated-imports - name: early-return - name: empty-block - name: empty-lines - name: enforce-map-style - name: enforce-repeated-arg-type-style - name: enforce-slice-style - name: error-naming - name: error-return - name: error-strings - name: errorf - name: file-header # - name: flag-parameter - name: function-result-limit - name: identical-branches - name: imports-blocklist - name: increment-decrement - name: indent-error-flow - name: modifies-parameter - name: modifies-value-receiver - name: nested-structs - name: optimize-operands-order - name: range-val-address - name: range-val-in-closure - name: range - name: receiver-naming - name: redefines-builtin-id - name: redundant-import-alias - name: string-format - name: string-of-int - name: struct-tag - name: superfluous-else - name: time-equal - name: time-naming - name: unconditional-recursion - name: unexported-naming - name: unexported-return - name: unnecessary-stmt - name: unreachable-code - name: useless-break - name: var-declaration - name: waitgroup-by-value rowserrcheck: packages: - github.com/jmoiron/sqlx sloglint: no-global: "" context: scope wrapcheck: ignore-package-globs: - github.com/symbioticfi/relay/internal/* - golang.org/x/sync/errgroup funcorder: constructor: true struct-method: false forbidigo: forbid: - pattern: ^fmt\.Errorf$ msg: "use errors.Errorf instead of fmt.Errorf" exclusions: generated: lax presets: - comments - common-false-positives - legacy - std-error-handling rules: - linters: - goconst - exhaustruct - wrapcheck path: _test\.go - path: _test\.go text: 'subtests should call t.Parallel' - path: (.+)\.go$ text: ST1003 - path: (.+)\.go$ text: 'shadow: declaration of "err" shadows declaration at line' - path: (.+)\.go$ text: G115 - path: cmd/utils/ text: "use of `fmt.Printf` forbidden" paths: - third_party$ - builtin$ - examples$ - hack/ issues: max-issues-per-linter: 500 max-same-issues: 500 formatters: enable: - gofmt - goimports exclusions: generated: lax paths: - third_party$ - builtin$ - examples$ ```` ## File: buf.badger.gen.yaml ````yaml version: v2 inputs: - directory: internal/client/repository/badger/proto managed: enabled: true plugins: - local: protoc-gen-go out: internal/client/repository/badger/proto opt: - paths=source_relative ```` ## File: buf.gen.yaml ````yaml version: v2 inputs: - directory: api/proto managed: enabled: true plugins: - local: protoc-gen-doc out: docs/api/v1 opt: - "html,index.html" - local: protoc-gen-doc out: docs/api/v1 opt: - "markdown,doc.md" - local: protoc-gen-go out: internal/gen/api opt: - paths=source_relative - local: protoc-gen-go-grpc out: internal/gen/api opt: - paths=source_relative - local: protoc-gen-grpc-gateway out: internal/gen/api opt: - paths=source_relative - generate_unbound_methods=true - local: protoc-gen-openapiv2 out: docs/api opt: - openapi_naming_strategy=simple ```` ## File: buf.lock ```` # Generated by buf. DO NOT EDIT. version: v2 deps: - name: buf.build/googleapis/googleapis commit: 72c8614f3bd0466ea67931ef2c43d608 digest: b5:13efeea24e633fd45327390bdee941207a8727e96cf01affb84c1e4100fd8f48a42bbd508df11930cd2884629bafad685df1ac3111bc78cdaefcd38c9371c6b1 ```` ## File: buf.p2p.gen.yaml ````yaml version: v2 inputs: - directory: internal/client/p2p/proto managed: enabled: true plugins: - local: protoc-gen-go out: internal/client/p2p/proto opt: - paths=source_relative - local: protoc-gen-go-grpc out: internal/client/p2p/proto opt: - paths=source_relative ```` ## File: buf.yaml ````yaml version: v2 modules: - path: api/proto deps: - buf.build/googleapis/googleapis lint: use: - STANDARD except: - PACKAGE_DIRECTORY_MATCH ```` ## File: CONTRIBUTING.md ````markdown # Contributing Guidelines We welcome contributions from the community! Please read the following guidelines carefully to ensure a smooth development workflow and consistent project quality. For detailed development setup, testing, and API change management, see the [Development Guide](DEVELOPMENT.md). --- ## Branching Strategy We follow a simplified Git Flow model with the following primary branches: - **`main`**: Contains stable, production-ready code. Releases are tagged from this branch. - **`dev`**: The main development branch. All new features and fixes should be merged here first. ### Branch Naming Conventions Please name your branches according to the purpose of the work: - `feature/your-short-description` — for new features - `fix/your-bug-description` — for bug fixes - `hotfix/urgent-fix` — for critical fixes (only in special cases, coordinated with maintainers) - `chore/your-task` — for maintenance or tooling updates - `docs/your-doc-change` — for documentation-only changes --- ## Pull Request Process - 🔀 **Always create pull requests targeting the `dev` branch**, never `main`. - ✅ Make sure your branch is up to date with `dev` before opening a PR. - ✅ Ensure your code builds and passes all tests. - ✅ Follow Go best practices and run a linter by running `make lint`. - 📝 Use clear and descriptive PR titles. - 📌 Link related issues in the PR description (`Fixes #123`, `Closes #456`, etc.). ### PR Checklist Before submitting, make sure your PR meets the following: - [ ] Target branch is `dev` - [ ] All tests pass - [ ] Lint checks pass - [ ] Code is covered with tests where applicable - [ ] Documentation is updated if needed --- ## Releases Releases are created by maintainers by tagging the `main` branch using semantic versioning: - `v1.2.3` — stable releases - `nightly-YYYYMMDD` — automated nightly builds on the `dev` branch > 🚫 Do not tag releases manually unless you are a core maintainer. --- ## Commit Style We encourage using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for commit messages, e.g.: ```` ## File: DEVELOPMENT.md ````markdown # Symbiotic Relay - Development Guide ## Table of Contents 1. [Introduction](#introduction) 2. [Architecture Overview](#architecture-overview) 3. [Development Setup](#development-setup) 4. [Running Tests](#running-tests) 5. [Local Environment](#local-environment) 6. [Managing API/Configuration Changes](#managing-api-changes) 7. [Code Generation](#code-generation) 8. [Linting](#linting) 9. [Logging Conventions](#logging-conventions) 10. [Building Docker Images](#building-docker-images) 11. [Contributing](#contributing) 12. [Additional Resources](#additional-resources) --- ## Introduction The Symbiotic Relay is a distributed middleware layer that facilitates cross-chain coordination, validator set management, and signature aggregation. This guide provides comprehensive information for developers working on the relay codebase, including setup, testing, and managing changes across the ecosystem. ## Architecture Overview ### Core Components The Symbiotic Relay consists of several key components working together: #### 1. **P2P Layer** (`internal/client/p2p/`) The peer-to-peer networking layer handles decentralized communication between relay nodes: - **GossipSub Protocol**: Uses libp2p's GossipSub for message broadcasting - **Topic-based Communication**: - `/relay/v1/signature/ready` - Signature ready notifications - `/relay/v1/proof/ready` - Aggregation proof ready notifications - **gRPC over P2P**: Direct node-to-node sync requests using gRPC over libp2p streams - **Discovery**: - mDNS for local network discovery - Kademlia DHT for distributed peer discovery - Static peer support for known bootstrap nodes #### 2. **Node Logic & Applications** The relay operates in multiple modes, configurable per node: - **Signer Nodes** (`internal/usecase/signer-app/`): - Listen for signature requests - Sign messages using BLS/Ecdsa keys - Broadcast signatures to the P2P network - **Aggregator Nodes** (`internal/usecase/aggregator-app/`): - Collect signatures from multiple signers - Apply aggregation policies - Generate BLS aggregated signatures or ZK proofs - Broadcast aggregation proofs - **Committer Nodes** (`internal/usecase/valset-listener/`): - Monitor validator set state on-chain - Submit aggregated proofs to settlement chains - Track epoch transitions #### 3. **API Layer** (`internal/usecase/api-server/`) Exposes gRPC API for external clients to create signature requests, query proofs/signatures and get validator/epoch info. Defined in `api/proto/v1/api.proto` #### 4. **Storage Layer** (`internal/client/repository/badger/`) - BadgerDB for persistent state storage - Caches for high-performance reads - Stores signatures, aggregation proofs, validator sets, and epochs #### 5. **Symbiotic Integration** (`symbiotic/`) - EVM client for on-chain interactions - Validator set derivation logic - Cryptographic primitives (BLS signatures, ZK proofs) --- ## Development Setup ### Prerequisites - **Go 1.25.3 or later** - **Node.js** (for contract compilation in E2E tests) - **Foundry/Forge** (for Solidity contracts) - **Docker & Docker Compose** (for E2E testing) - **Buf CLI** (installed via `make install-tools`) ### Initial Setup 1. **Clone the repository**: ```bash git clone https://github.com/symbioticfi/relay.git cd relay ``` 2. **Install development tools**: ```bash make install-tools ``` This installs: - `buf` - Protocol buffer compiler - `protoc-gen-go` and `protoc-gen-go-grpc` - Go protobuf generators - `mockgen` - Mock generation for testing - `protoc-gen-doc` - API documentation generator 3. **Generate code**: ```bash make generate ``` This generates: - API types from proto files - P2P message types - BadgerDB repository types - Client types - Mock implementations - Contract ABI bindings 4. **Build the relay sidecar binary**: ```bash make build-relay-sidecar OS=linux ARCH=amd64 ``` or for macOS ARM: ```bash make build-relay-sidecar OS=darwin ARCH=arm64 ``` 5. **Build the relay utils CLI binary**: ```bash make build-relay-utils OS=linux ARCH=amd64 ``` --- ## Running Tests ### Unit Tests Run all unit tests with coverage: ```bash make unit-test ``` To run tests for a specific package: ```bash go test -v ./internal/usecase/signer-app/ ``` ### End-to-End (E2E) Tests E2E tests spin up a complete relay network with blockchain nodes. #### Quick E2E Test Run ```bash # Setup the E2E environment (only needed once or after cleanup) cd e2e ./setup.sh # Start the network cd temp-network docker compose up -d cd ../.. # Run the tests make e2e-test ``` #### Custom E2E Configuration You can customize the E2E network topology using environment variables, see the setup.sh script for more envs: ```bash # Configure network before setup export OPERATORS=6 # Number of relay operator nodes (default: 4) export COMMITERS=2 # Number of committer nodes (default: 1) export AGGREGATORS=1 # Number of aggregator nodes (default: 1) export VERIFICATION_TYPE=1 # 0=ZK proofs, 1=BLS simple (default: 1) export EPOCH_TIME=30 # Epoch duration in seconds (default: 30) export BLOCK_TIME=2 # Block time in seconds (default: 1) export FINALITY_BLOCKS=2 # Blocks until finality (default: 2) # Run setup with custom config cd e2e ./setup.sh ``` #### Cleanup E2E Environment ```bash # Stop and remove containers cd e2e/temp-network docker compose down ``` --- ## Local Environment ### Setting Up Local Development Network For local development and testing: ```bash make local-setup ``` This command takes the same envs as the e2e setup for configuration. This command: 1. Generates relay sidecar configurations 2. Sets up a local blockchain network (Anvil) 3. Deploys contracts 4. Starts relay nodes in Docker --- ## Managing API/Configuration Changes ### Overview When you make changes to the API proto file (`api/proto/v1/api.proto`), those changes must be propagated across multiple repositories and examples to maintain consistency across the ecosystem. ### Step 1: Update Proto Definition 1. Make your changes to `api/proto/v1/api.proto` 2. Regenerate Go code and Docs: ```bash make generate ``` ### Step 2: Update Local Examples and E2E Tests **Update Go Client Examples:** ```bash cd api/client/examples # Update main.go to reflect API changes vim main.go # Test the example, follow the readme and test go run main.go ``` **Update E2E Tests and Configuration:** If API changes affect the relay sidecar configuration or client usage: **E2E Test Files** (`e2e/tests/`): - Update client instantiation in test setup files - Update test cases that use the changed RPC methods - Update `sidecar.yaml` if new configuration fields are required **E2E Scripts** (`e2e/scripts/`): - Update sidecar startup scripts if config template needs new fields - Update genesis generation script if relay utils CLI commands changed - Update network generation script if new environment variables are needed **Common changes:** - **New RPC methods** → Add corresponding test cases - **Config field changes** → Update sidecar configuration files and startup templates - **CLI command changes** → Update scripts that invoke relay utils commands - **Client interface changes** → Update test setup and client instantiation code ### Step 3: Update External Client Repositories #### TypeScript Client ([relay-client-ts](https://github.com/symbioticfi/relay-client-ts)) The TypeScript client has an automated workflow that regenerates the gRPC client when the proto file changes. However, you still need to: 1. **Wait for/Trigger the workflow** that updates the generated client code 2. **Update examples manually**: ```bash cd examples/ # Update example files to use new API vim basic-usage.ts npm run build npm run basic-usage ``` #### Rust Client ([relay-client-rs](https://github.com/symbioticfi/relay-client-rs)) Similar to TypeScript, the Rust client auto-generates the gRPC implementation: 1. **Wait for/Trigger the workflow** that updates the generated client code 2. **Update examples manually**: ```bash cd examples/ # Update example files to use new API vim basic_usage.rs cargo build cargo run --example basic_usage ``` ### Step 4: Update Symbiotic Super Sum Example The [symbiotic-super-sum](https://github.com/symbioticfi/symbiotic-super-sum) repository provides a comprehensive task-based example. **What to update:** 1. **Go Client Package Version**: ```bash cd off-chain # Update go.mod to use latest relay client go get github.com/symbioticfi/relay@ go mod tidy ``` 2. **Network Configuration**: - Check if any configuration changes are needed in network setup - The `generate_network.sh` script in symbiotic-super-sum is similar to the E2E setup - Update environment variables or config files if the relay now requires new settings 3. **Example Application Code**: - Update any client usage in the off-chain application - Test the example end-to-end 4. **Documentation**: - Update README if API usage patterns have changed ### Step 5: Update Cosmos Relay SDK The [cosmos-relay-sdk](https://github.com/symbioticfi/cosmos-relay-sdk) integrates the relay with Cosmos SDK chains. **What to update:** 1. **Go Client Package**: ```bash # Update the client package version go get github.com/symbioticfi/relay/api/client/v1@latest go mod tidy ``` 2. **Mock Relay Client** (`x/symstaking/types/mock_relay.go`): The mock relay client must match the updated client interface: Example of what needs updating: - If you added a new RPC method, add it to the mock - If you changed method signatures, update them in the mock - If you changed request/response types, update the mock accordingly 3. **Documentation**: - Update SDK docs to reflect new API capabilities --- ## Code Generation The project uses code generation extensively. Here's what each target generates: ### Generate All ```bash make generate ``` This runs all generation targets that need codegen, including mocks, proto messages, etc. --- ## Linting ### Run All Linters ```bash make lint ``` This runs: - `buf lint` for proto files - `golangci-lint` for Go code ### Auto-fix Linting Issues ```bash make go-lint-fix ``` --- ## Logging Conventions ### Overview The Symbiotic Relay uses Go's standard `log/slog` (structured logging) with a custom wrapper located in `pkg/log/`. This provides: - **Structured logging** with type-safe fields - **Context propagation** for automatic field inheritance - **Component-based tagging** for filtering and debugging - **Multiple output modes**: pretty (colored), text, and JSON **Configuration:** Set log level and mode in `sidecar.yaml`: ```yaml log: level: debug # debug, info, warn, error mode: pretty # pretty, text, json ``` ### Log Levels - When to Use | Level | When to Use | Examples | |-------------------------|-----------------------------------------------------------------------|----------------------------------------------------------------------------------------------| | **Debug** | Flow tracing, detailed decisions, skipped operations, variable values | "Skipped signing (not in validator set)", "Checked for missing epochs" | | **Info** (prod default) | Key state changes, service lifecycle events, completed operations | "Signature aggregation completed", "Started P2P listener", "Submitted proof to chain" | | **Warn** | Recoverable issues, unusual but handled situations, security concerns | "Message signing disabled", "Retrying after temporary failure", "Invalid signature received" | | **Error** | Unrecoverable failures, critical problems requiring attention | "Failed to load validator set", "Database connection lost", "Contract call failed" | **Important:** Log errors only at high-level error handlers (API handlers, main event loops, service entry points), not at every location where an error occurs. Internal functions should return errors without logging them, allowing the top-level handler to log once with full context. ### Context Propagation Pattern **Always use context-aware logging variants** (`slog.InfoContext`, `slog.DebugContext`, etc.) when context is available. ```go func (s *Service) HandleRequest(ctx context.Context, req *Request) error { // 1. Add component tag (required) ctx = log.WithComponent(ctx, "aggregator") // 2. Add request-specific context (if applicable) ctx = log.WithAttrs(ctx, slog.Uint64("epoch", uint64(req.Epoch)), slog.String("requestId", req.RequestID.Hex()), ) // 3. All subsequent logs automatically include these fields slog.InfoContext(ctx, "Started processing request") // ... rest of implementation return nil } ``` ### Standard Field Names All field names **must** use `camelCase` notation. Use these standard field names consistently: #### Request Context - `requestId` - Unique request identifier (use for cross-service correlation) - `epoch` - Epoch number (uint64) #### Identifiers - `keyTag` - Key tag identifier - `operator` - Operator address/ID - `publicKey` - Public key (formatted as hex) - `address` - Ethereum address - `validatorIndex` - Validator index in the set #### Operation Tracking - `error` - Error message/object (always use "error", not "err") - `duration` - Operation duration (use `time.Since()`) - `attempt` - Current retry attempt number - `maxRetries` - Maximum retry attempts #### Network/P2P - `topic` - P2P topic name - `sender` - Message sender identifier - `peer` - Peer identifier - `peerId` - Libp2p peer ID #### Component/Method - `component` - Component name (auto-added via `log.WithComponent()`) - `method` - gRPC method name or function identifier #### Blockchain - `chainId` - Chain identifier - `blockNumber` - Block number - `txHash` - Transaction hash - `contractAddress` - Smart contract address #### Custom Fields When adding custom fields not in this list: - Use descriptive `camelCase` names - Prefer specific names over generic ones (`validatorCount` not `count`) - Document new commonly-used fields by updating this list ### Error Logging Standards **1. Error Wrapping (Internal Functions):** Always wrap errors using `github.com/go-errors/errors` to capture stacktrace in the place of error: ```go import "github.com/go-errors/errors" func (s *Service) loadData(id string) error { data, err := s.repo.Get(id) if err != nil { // Wrap with context, preserve stack trace return errors.Errorf("failed to load data for id=%s: %w", id, err) } return nil } ``` **2. Error Logging (Boundaries Only):** Log errors at **boundaries** (API handlers, main loops, service entry points): **3. Always use `"error"` as the field name** (not "err"): ```go // ❌ Incorrect: Using "err" as field name slog.ErrorContext(ctx, "Failed to process request", "err", err) slog.WarnContext(ctx, "Retry attempt failed", "err", retryErr) // ✅ Correct: Always use "error" for consistency slog.ErrorContext(ctx, "Failed to process request", "error", err) slog.WarnContext(ctx, "Retry attempt failed", "error", retryErr) ``` ### Duration Tracking Always track and log operation durations for performance monitoring: ```go func (s *Service) ProcessSignature(ctx context.Context, sig *Signature) error { start := time.Now() // ... perform operation ... slog.InfoContext(ctx, "Signature processed successfully", "duration", time.Since(start), "requestId", sig.RequestID, ) return nil } ``` ### Log Message Format Log messages **must** follow these conventions: **1. Start with past tense verb:** ```go // ✅ Correct: Past tense verbs indicating completed actions slog.InfoContext(ctx, "Signature received") slog.InfoContext(ctx, "Validator set loaded") slog.InfoContext(ctx, "Proof submitted to chain") slog.DebugContext(ctx, "Checked for missing epochs") // ❌ Incorrect slog.InfoContext(ctx, "Receiving signature") // present continuous slog.InfoContext(ctx, "Load validator set") // imperative slog.InfoContext(ctx, "Signature receive") // noun only ``` **Note:** Present continuous tense ("Processing...", "Aggregating signatures...") may be valid for long-running operations where you want to communicate progress and show that the process is active, not stuck. However, always pair these with a past tense completion log: ```go // ✅ Acceptable for long-running operations slog.DebugContext(ctx, "Aggregating signatures from validators", "count", validatorCount) // ... long operation ... slog.InfoContext(ctx, "Aggregation completed", "duration", time.Since(start)) ``` **2. Use consistent terminology:** - "Started" / "Completed" for long operations - "Received" / "Sent" for messages - "Loaded" / "Stored" for data operations - "Failed" for errors (not "Error:", the log level indicates it's an error) ### Component Naming Conventions Use these standard component names with `log.WithComponent()`: | Component | Usage | |-------------------|----------------------------| | `"grpc"` | gRPC handlers | | `"signer"` | Signer application | | `"aggregator"` | Aggregator application | | `"sign_listener"` | Signature listener service | | `"listener"` | Validator set listener | | `"p2p"` | P2P network layer | | `"evm"` | EVM client interactions | Keep component names: - Lowercase - Short and recognizable - Consistent across the codebase ### *Prefer context-aware logging variants whenever possible ```go // ✅ Preferred (context-aware) slog.InfoContext(ctx, "Message processed", "count", count) slog.ErrorContext(ctx, "Failed to process", "error", err) // ⚠️ Avoid when context is available (legacy pattern) slog.Info("Message processed", "count", count) slog.Error("Failed to process", "error", err) ``` --- ## Building Docker Images Build the relay sidecar Docker image: ```bash make image ``` To build and push multi-architecture images: ```bash PUSH_IMAGE=true PUSH_LATEST=true make image ``` --- ## Contributing Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for our branching strategy, PR process, and commit conventions. ### Key Points: - **Target branch**: Always create PRs against `dev`, never `main` - **Tests**: Ensure all tests pass before submitting PR - **Linting**: Run `make lint` and fix all issues - **Documentation**: Update docs when changing APIs or behavior --- ## Additional Resources - **API Documentation**: [docs/api/v1/doc.md](docs/api/v1/doc.md) - **Main README**: [README.md](README.md) - **Contributing Guide**: [CONTRIBUTING.md](CONTRIBUTING.md) - **Official Docs**: https://docs.symbiotic.fi/category/relay-sdk - **Example Client Usage**: [api/client/examples/README.md](api/client/examples/README.md) ```` ## File: Dockerfile ````dockerfile FROM golang:1.25 AS builder WORKDIR /app # Cache go mod dependencies COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod \ go mod download COPY . ./ ARG APP_VERSION ARG BUILD_TIME ARG TARGETOS ENV GOOS=$TARGETOS ARG TARGETARCH ENV GOARCH=$TARGETARCH # Cache build artifacts RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=0 go build -ldflags "-extldflags '-static' -X 'github.com/symbioticfi/relay/cmd/utils/root.Version=${APP_VERSION}' -X 'github.com/symbioticfi/relay/cmd/utils/root.BuildTime=${BUILD_TIME}'" -o relay_utils ./cmd/utils && \ chmod a+x relay_utils RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=0 go build -ldflags "-extldflags '-static' -X 'github.com/symbioticfi/relay/cmd/relay/root.Version=${APP_VERSION}' -X 'github.com/symbioticfi/relay/cmd/relay/root.BuildTime=${BUILD_TIME}'" -o relay_sidecar ./cmd/relay && \ chmod a+x relay_sidecar FROM alpine:latest WORKDIR /app COPY --from=builder /app/relay_utils . COPY --from=builder /app/relay_sidecar . COPY --from=builder /app/docs ./docs ```` ## File: example.config.yaml ````yaml # Relay Sidecar Configuration Example # Logging log: level: "debug" mode: "pretty" # Storage storage-dir: ".data" # circuits-dir: "" # Optional: Path to ZK circuits directory # API Server Configuration api: listen: ":8080" verbose-logging: false http-gateway: false # Enable HTTP/JSON REST API gateway (default: false) # Metrics Configuration (optional) metrics: listen: ":9090" pprof: false # Driver Contract driver: chain-id: 31337 address: "0x4826533B4897376654Bb4d4AD88B7faFD0C98528" # Secret Keys secret-keys: - namespace: "symb" key-type: 0 key-id: 15 secret: "0xde0b6b3a7640000" - namespace: "evm" key-type: 1 key-id: 31337 secret: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" # Signal Configuration signal: worker-count: 10 buffer-size: 20 # Cache Configuration cache: network-config-size: 10 validator-set-size: 10 # Sync Configuration sync: enabled: true period: 5s timeout: 1m epochs: 5 # Key Cache key-cache: size: 100 enabled: true # P2P Configuration p2p: listen: "/ip4/0.0.0.0/tcp/8880" bootnodes: [] dht-mode: "disabled" mdns: true # EVM Configuration evm: chains: - "http://127.0.0.1:8545" max-calls: 30 # Aggregation Policy aggregation-policy-max-unsigners: 50 # Data Retention Configuration (optional) # Controls how much historical data to keep on this node retention: # Maximum number of historical validator set epochs to sync on fresh node startup # - 0 (default): Unlimited - sync from genesis epoch # - N > 0: Sync only the most recent N epochs # Note: Only applies to fresh nodes. Existing nodes continue from last synced epoch. # Should match your pruning retention period to avoid re-syncing pruned data. valset-epochs: 0 ```` ## File: go.mod ```` module github.com/symbioticfi/relay go 1.25.3 require ( github.com/RoaringBitmap/roaring/v2 v2.13.0 github.com/consensys/gnark v0.0.0-00010101000000-000000000000 // pinned with replace github.com/consensys/gnark-crypto v0.19.2 // pinned with replace github.com/dgraph-io/badger/v4 v4.8.0 github.com/docker/docker v28.5.1+incompatible github.com/elastic/go-freelru v0.16.0 github.com/ethereum/go-ethereum v1.16.5 github.com/ferranbt/fastssz v1.0.0 github.com/go-chi/chi/v5 v5.2.3 github.com/go-errors/errors v1.5.1 github.com/go-playground/validator/v10 v10.28.0 github.com/google/uuid v1.6.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 github.com/kelseyhightower/envconfig v1.4.0 github.com/libp2p/go-libp2p v0.44.0 github.com/libp2p/go-libp2p-gostream v0.6.0 github.com/libp2p/go-libp2p-kad-dht v0.34.0 github.com/libp2p/go-libp2p-pubsub v0.15.0 github.com/multiformats/go-multiaddr v0.16.1 github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 github.com/prometheus/client_golang v1.23.2 github.com/pterm/pterm v0.12.82 github.com/samber/lo v1.52.0 github.com/samber/slog-multi v1.5.0 github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 github.com/testcontainers/testcontainers-go v0.39.0 go.uber.org/mock v0.6.0 golang.org/x/net v0.46.0 golang.org/x/sync v0.17.0 golang.org/x/term v0.36.0 google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda google.golang.org/grpc v1.76.0 google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v2 v2.4.0 k8s.io/client-go v0.34.1 ) require ( atomicgo.dev/cursor v0.2.0 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect dario.cat/mergo v1.0.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.24.3 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/containerd/console v1.0.5 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/dgraph-io/ristretto/v2 v2.2.0 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/ebitengine/purego v0.9.0 // indirect github.com/emicklei/dot v1.9.0 // indirect github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/filecoin-project/go-clock v0.1.0 // indirect github.com/flynn/noise v1.1.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/gabriel-vasile/mimetype v1.4.11 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/flatbuffers v25.2.10+incompatible // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 // indirect github.com/gookit/color v1.6.0 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/holiman/uint256 v1.3.2 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ingonyama-zk/icicle-gnark/v3 v3.2.2 // indirect github.com/ipfs/boxo v0.34.0 // indirect github.com/ipfs/go-cid v0.6.0 // indirect github.com/ipfs/go-datastore v0.8.3 // indirect github.com/ipfs/go-log/v2 v2.8.1 // indirect github.com/ipld/go-ipld-prime v0.21.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/klauspost/compress v1.18.1 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/koron/go-ssdp v0.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.3.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect github.com/libp2p/go-libp2p-record v0.3.1 // indirect github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-netroute v0.4.0 // indirect github.com/libp2p/go-reuseport v0.4.0 // indirect github.com/libp2p/go-yamux/v5 v5.1.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 // indirect github.com/magiconair/properties v1.8.10 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect github.com/miekg/dns v1.1.68 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/go-archive v0.1.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/user v0.4.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.2 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/mschoch/smat v0.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-dns v0.4.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multicodec v0.10.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-multistream v0.6.1 // indirect github.com/multiformats/go-varint v0.1.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pion/datachannel v1.5.10 // indirect github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/dtls/v3 v3.0.7 // indirect github.com/pion/ice/v4 v4.0.10 // indirect github.com/pion/interceptor v0.1.41 // indirect github.com/pion/logging v0.2.4 // indirect github.com/pion/mdns/v2 v2.0.7 // indirect github.com/pion/randutil v0.1.0 // indirect github.com/pion/rtcp v1.2.16 // indirect github.com/pion/rtp v1.8.25 // indirect github.com/pion/sctp v1.8.40 // indirect github.com/pion/sdp/v3 v3.0.16 // indirect github.com/pion/srtp/v3 v3.0.8 // indirect github.com/pion/stun v0.6.1 // indirect github.com/pion/stun/v3 v3.0.1 // indirect github.com/pion/transport/v2 v2.2.10 // indirect github.com/pion/transport/v3 v3.0.8 // indirect github.com/pion/turn/v4 v4.1.2 // indirect github.com/pion/webrtc/v4 v4.1.6 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.2 // indirect github.com/prometheus/procfs v0.19.2 // indirect github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/quic-go v0.55.0 // indirect github.com/quic-go/webtransport-go v0.9.0 // indirect github.com/ronanh/intcomp v1.1.1 // indirect github.com/rs/zerolog v1.34.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect github.com/samber/slog-common v0.19.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/shirou/gopsutil/v4 v4.25.8 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.16 // indirect github.com/tklauser/go-sysconf v0.3.15 // indirect github.com/tklauser/numcpus v0.10.0 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/wlynxg/anet v0.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/otel/trace v1.38.0 // indirect go.uber.org/dig v1.19.0 // indirect go.uber.org/fx v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.43.0 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/mod v0.29.0 // indirect golang.org/x/sys v0.37.0 // indirect golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8 // indirect golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.38.0 // indirect gonum.org/v1/gonum v0.16.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.34.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect lukechampine.com/blake3 v1.4.1 // indirect ) // pinned versions replace ( github.com/consensys/gnark => github.com/consensys/gnark v0.14.0 github.com/consensys/gnark-crypto => github.com/consensys/gnark-crypto v0.19.0 ) ```` ## File: Makefile ```` PACKAGE=github.com/symbioticfi/relay IMAGE_REPO ?= relay_sidecar BUILD_TIME ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ) TAG ?= ifeq ($(strip $(TAG)),) CURRENT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD) PSEUDO_VERSION := $(shell go list -f {{.Version}} -m ${PACKAGE}@${CURRENT_BRANCH} 2>/dev/null || echo "unspecified-$(CURRENT_BRANCH)") # Trim the `v` prefix from golang pseudo version as the TAG if not set FINAL_TAG := $(shell echo $(PSEUDO_VERSION) | sed 's/^v//' | sed 's/-0\./-/') else # If TAG was explicitly passed, strip the v prefix TAG_ORIGINAL := $(TAG) FINAL_TAG := $(shell echo '$(TAG_ORIGINAL)' | sed 's/^v//') endif # add v prefix for APP_VERSION APP_VERSION := v$(FINAL_TAG) # create image tags without v prefix IMAGE_TAGS := -t ${IMAGE_REPO}:${FINAL_TAG} ifeq ($(PUSH_LATEST), true) IMAGE_TAGS := ${IMAGE_TAGS} -t ${IMAGE_REPO}:latest endif .PHONY: local-setup local-setup: cd e2e && \ GENERATE_SIDECARS=true bash setup.sh && \ cd temp-network && \ docker compose up -d .PHONY: clean-local-setup clean-local-setup: if [ -d "e2e/temp-network" ]; then \ docker compose --project-directory e2e/temp-network down; \ fi .PHONY: lint lint: install-tools buf-lint go-lint .PHONY: buf-lint buf-lint: buf lint .PHONY: go-lint go-lint: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.2 -v run ./... .PHONY: go-lint-fix go-lint-fix: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.2 -v run ./... --fix .PHONY: generate generate: install-tools generate-mocks generate-api-types generate-client-types generate-p2p-types generate-badger-types gen-abi generate-cli-docs .PHONY: install-tools install-tools: go install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc@v1.5.1 go install go.uber.org/mock/mockgen@v0.6.0 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.5.1 go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.6 go install github.com/bufbuild/buf/cmd/buf@v1.59.0 go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest .PHONY: generate-mocks generate-mocks: go generate ./... .PHONY: generate-api-types generate-api-types: buf generate .PHONY: generate-p2p-types generate-p2p-types: buf generate --template=buf.p2p.gen.yaml .PHONY: generate-badger-types generate-badger-types: buf generate --template=buf.badger.gen.yaml .PHONY: generate-client-types generate-client-types: go run hack/codegen/generate-client-types.go .PHONY: generate-cli-docs generate-cli-docs: @echo "Generating CLI documentation..." go run hack/docgen/generate-cli-docs.go @echo "CLI documentation generated in docs/cli/" .PHONY: unit-test unit-test: go test $(shell go list ./... | grep -v '/e2e/') -v -covermode atomic -race -coverprofile=cover.out.tmp -coverpkg=$(shell go list ./... | grep -v '/e2e/' | tr '\n' ',') cat cover.out.tmp | grep -v "gen" | grep -v "mocks" > coverage.tmp.txt # strip out generated files go tool cover -func coverage.tmp.txt > coverage.txt rm cover.out.tmp coverage.tmp.txt .PHONY: e2e-test e2e-test: cd e2e/tests && go test -v -timeout 30m .PHONY: gen-abi gen-abi: go run github.com/ethereum/go-ethereum/cmd/abigen@latest \ --abi symbiotic/client/evm/abi/IValSetDriver.abi.json \ --type IValSetDriver \ --pkg gen \ --out symbiotic/client/evm/gen/valsetDriver.go go run github.com/ethereum/go-ethereum/cmd/abigen@latest \ --abi symbiotic/client/evm/abi/ISettlement.abi.json \ --type ISettlement \ --pkg gen \ --out symbiotic/client/evm/gen/settlement.go go run github.com/ethereum/go-ethereum/cmd/abigen@latest \ --abi symbiotic/client/evm/abi/IKeyRegistry.abi.json \ --type IKeyRegistry \ --pkg gen \ --out symbiotic/client/evm/gen/keyRegistry.go go run github.com/ethereum/go-ethereum/cmd/abigen@latest \ --abi symbiotic/client/evm/abi/IVotingPowerProvider.abi.json \ --type IVotingPowerProvider \ --pkg gen \ --out symbiotic/client/evm/gen/votingPowerProvider.go # Generic build target that takes OS and architecture as parameters # Usage: make build-relay-utils OS=linux ARCH=amd64 # Usage: make build-relay-sidecar OS=darwin ARCH=arm64 .PHONY: build-relay-utils build-relay-utils: @if [ -z "$(OS)" ] || [ -z "$(ARCH)" ]; then \ echo "Error: OS and ARCH parameters are required"; \ echo "Usage: make build-relay-utils OS= ARCH="; \ exit 1; \ fi GOOS=$(OS) GOARCH=$(ARCH) CGO_ENABLED=0 go build -ldflags "-extldflags '-static' -X 'github.com/symbioticfi/relay/cmd/utils/root.Version=$(APP_VERSION)' -X 'github.com/symbioticfi/relay/cmd/utils/root.BuildTime=$(BUILD_TIME)'" -o relay_utils_$(OS)_$(ARCH) ./cmd/utils && \ chmod a+x relay_utils_$(OS)_$(ARCH) .PHONY: build-relay-sidecar build-relay-sidecar: @if [ -z "$(OS)" ] || [ -z "$(ARCH)" ]; then \ echo "Error: OS and ARCH parameters are required"; \ echo "Usage: make build-relay-sidecar OS= ARCH="; \ exit 1; \ fi GOOS=$(OS) GOARCH=$(ARCH) CGO_ENABLED=0 go build -ldflags "-extldflags '-static' -X 'github.com/symbioticfi/relay/cmd/relay/root.Version=$(APP_VERSION)' -X 'github.com/symbioticfi/relay/cmd/relay/root.BuildTime=$(BUILD_TIME)'" -o relay_sidecar_$(OS)_$(ARCH) ./cmd/relay && \ chmod a+x relay_sidecar_$(OS)_$(ARCH) # Legacy targets for backward compatibility .PHONY: build-relay-utils-linux build-relay-utils-linux: $(MAKE) build-relay-utils OS=linux ARCH=amd64 .PHONY: build-relay-utils-darwin build-relay-utils-darwin: $(MAKE) build-relay-utils OS=darwin ARCH=arm64 .PHONY: build-relay-sidecar-linux build-relay-sidecar-linux: $(MAKE) build-relay-sidecar OS=linux ARCH=amd64 .PHONY: build-relay-sidecar-darwin build-relay-sidecar-darwin: $(MAKE) build-relay-sidecar OS=darwin ARCH=arm64 .PHONY: image image: ifeq ($(PUSH_IMAGE), true) @docker buildx build --push --platform=linux/amd64,linux/arm64 . ${IMAGE_TAGS} --build-arg APP_VERSION=$(APP_VERSION) --build-arg BUILD_TIME=$(BUILD_TIME) # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter echo "image=${IMAGE_REPO}:${FINAL_TAG}" >> $$GITHUB_OUTPUT else @DOCKER_BUILDKIT=1 docker build . ${IMAGE_TAGS} --build-arg APP_VERSION=$(APP_VERSION) --build-arg BUILD_TIME=$(BUILD_TIME) endif .PHONY: fix-goimports fix-goimports: go run golang.org/x/tools/cmd/goimports@latest -w . ```` ## File: README.md ````markdown # Symbiotic Relay [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/symbioticfi/relay) > [!WARNING] > The code is a work in progress and not production ready yet. > Breaking changes may occur in the code updates as well as backward compatibility is not guaranteed. > Use with caution. ## Overview The Symbiotic Relay operates as a distributed middleware layer that facilitates: - **Validator Set Management**: Derives and maintains validator sets across different epochs based on on-chain state - **Signature Aggregation**: Collects individual validator signatures and aggregates them using BLS signatures or zero-knowledge proofs - **Cross-Chain Coordination**: Manages validator sets across multiple EVM-compatible blockchains ## Architecture The relay consists of several key components: - **P2P Layer**: Uses libp2p with GossipSub for decentralized communication - **Signer Nodes**: Sign messages using BLS/ECDSA keys - **Aggregator Nodes**: Collect and aggregate signatures with configurable policies - **Committer Nodes**: Submit aggregated proofs to settlement chains - **API Server**: Exposes gRPC API for external clients For detailed architecture information, see [DEVELOPMENT.md](DEVELOPMENT.md). ## Documentation - **[Development Guide](DEVELOPMENT.md)** - Comprehensive guide for developers including testing, API changes, and code generation - **[Relay Docs](https://docs.symbiotic.fi/category/relay-sdk)** - Official documentation - **[CLI Documentation](docs/cli/)** - Command-line interface reference for relay_sidecar and relay_utils - **[Contributing](CONTRIBUTING.md)** - Contribution guidelines and workflow ## Running Examples For a complete end-to-end example application using the relay, see: **[Symbiotic Super Sum](https://github.com/symbioticfi/symbiotic-super-sum)** - A task-based network example demonstrating relay integration ## API The relay exposes both gRPC and HTTP/JSON REST APIs for interacting with the network: ### gRPC API - **API Documentation**: [docs/api/v1/doc.md](docs/api/v1/doc.md) - **Proto Definitions**: [api/proto/v1/api.proto](api/proto/v1/api.proto) - **Go Client**: [api/client/v1/](api/client/v1/) - **Client Examples**: [api/client/examples/](api/client/examples/) ### HTTP/JSON REST API Gateway The relay includes an optional HTTP/JSON REST API gateway that translates HTTP requests to gRPC: - **Swagger File**: [docs/v1/api.swagger.json](docs/api/v1/api.swagger.json) - **OpenAPI/Swagger Spec**: Available at `/docs/api.swagger.json` when enabled - **Endpoints**: All gRPC methods accessible via RESTful HTTP at `/api/v1/*` Enable via configuration: ```yaml api: http-gateway: true ``` Or via command-line flag: ```bash ./relay_sidecar --api.http-gateway=true ``` ### Client Libraries - **Go**: Included in this repository at `github.com/symbioticfi/relay/api/client/v1` - **TypeScript**: [relay-client-ts](https://github.com/symbioticfi/relay-client-ts) - **Rust**: [relay-client-rs](https://github.com/symbioticfi/relay-client-rs) - **HTTP/cURL**: Use the HTTP gateway for language-agnostic access ## Quick Start ### Use Pre-built Releases Instead of building from source, you can download pre-built binaries from GitHub releases: ```bash # Download the latest release for your platform # Linux AMD64 wget https://github.com/symbioticfi/relay/releases/latest/download/relay_sidecar_linux_amd64 wget https://github.com/symbioticfi/relay/releases/latest/download/relay_utils_linux_amd64 chmod +x relay_sidecar_linux_amd64 relay_utils_linux_amd64 # macOS ARM64 wget https://github.com/symbioticfi/relay/releases/latest/download/relay_sidecar_darwin_arm64 wget https://github.com/symbioticfi/relay/releases/latest/download/relay_utils_darwin_arm64 chmod +x relay_sidecar_darwin_arm64 relay_utils_darwin_arm64 # Run the binaries ./relay_sidecar_linux_amd64 --config config.yaml ``` Browse all releases at: https://github.com/symbioticfi/relay/releases ### Use Docker Images Pre-built Docker images are available from Docker Hub: ```bash # Pull the latest image docker pull symbioticfi/relay:latest # Or pull a specific version docker pull symbioticfi/relay: # Run the relay sidecar docker run -v $(pwd)/config.yaml:/config.yaml \ symbioticfi/relay:latest \ --config /config.yaml ``` Docker Hub: https://hub.docker.com/r/symbioticfi/relay ## Build localy ### Dependencies - **Go 1.24.3+** - **Docker & Docker Compose** (for local setup and E2E tests) - **Node.js & Foundry** (for contract compilation in E2E) ### Build Binaries Build the relay sidecar and utils binaries: ```bash # For Linux make build-relay-sidecar OS=linux ARCH=amd64 make build-relay-utils OS=linux ARCH=amd64 # For macOS ARM make build-relay-sidecar OS=darwin ARCH=arm64 make build-relay-utils OS=darwin ARCH=arm64 ``` ### Build Docker Image ```bash make image TAG=dev ``` ## Local Setup ### Automated Local Network Set up a complete local relay network with blockchain nodes and multiple relay sidecars: ```bash make local-setup ``` This command: 1. Builds the relay Docker image 2. Sets up local blockchain nodes (Anvil) 3. Deploys contracts 4. Generates sidecar configurations 5. Starts relay nodes in Docker **Customize the network** using environment variables (see [DEVELOPMENT.md](DEVELOPMENT.md) for details): ```bash OPERATORS=6 COMMITERS=2 AGGREGATORS=1 make local-setup ``` ## Configuration File Structure > **Note**: For a complete reference of all configuration options and command-line flags, see the [relay_sidecar CLI documentation](docs/cli/relay/relay_sidecar.md). Create a `config.yaml` file with the following structure: ```yaml # Logging log: level: "debug" # Options: debug, info, warn, error mode: "pretty" # Options: json, text, pretty # Storage storage-dir: ".data" # Directory for persistent data circuits-dir: "" # Path to ZK circuits (optional, empty disables ZK proofs) # API Server api: listen: ":8080" # API server address verbose-logging: false # Enable verbose API logging # Metrics (optional) metrics: listen: ":9090" # Metrics endpoint address pprof: false # Enable pprof debug endpoints # Driver Contract driver: chain-id: 31337 # Chain ID where driver contract is deployed address: "0x..." # Driver contract address # Secret Keys secret-keys: - namespace: "symb" # Namespace for the key key-type: 0 # 0=BLS-BN254, 1=ECDSA key-id: 15 # Key identifier secret: "0x..." # Private key hex - namespace: "evm" key-type: 1 key-id: 31337 secret: "0x..." - namespace: "p2p" key-type: 1 key-id: 1 secret: "0x..." # Alternatively, use keystore # keystore: # path: "/path/to/keystore.json" # password: "your-password" # Signal Configuration, used for internal messages and event queues signal: worker-count: 10 # Number of signal workers buffer-size: 20 # Signal buffer size # Cache Configuration, used for in memorylookups for db queries cache: network-config-size: 10 # Network config cache size validator-set-size: 10 # Validator set cache size # Sync Configuration, sync signatures and proofs over p2p to recover missing information sync: enabled: true # Enable P2P sync period: 5s # Sync period timeout: 1m # Sync timeout epochs: 5 # Number of epochs to sync # Key Cache, used for fast public key lookups key-cache: size: 100 # Key cache size enabled: true # Enable key caching # P2P Configuration p2p: listen: "/ip4/0.0.0.0/tcp/8880" # P2P listen address bootnodes: # List of bootstrap nodes (optional) - /dns4/node1/tcp/8880/p2p/... dht-mode: "server" # Options: auto, server, client, disabled, default: server (ideally should not change) mdns: true # Enable mDNS local discovery (useful for local networks) # EVM Configuration evm: chains: # List of settlement chain RPC endpoints - "http://localhost:8545" - "http://localhost:8546" max-calls: 30 # Max calls in multicall batches # Aggregation Policy aggregation-policy-max-unsigners: 50 # Max unsigners for low-cost policy # Data Retention (optional) # Controls how much historical data to keep on this node retention: valset-epochs: 0 # Number of historical epochs to retain on fresh node startup # 0 = unlimited (sync from genesis) # N > 0 = sync only last N epochs (for fresh nodes only) ``` #### Data Retention Control historical data sync for new nodes: ```bash --retention.valset-epochs=20 # Keep only last 20 validator set epochs on fresh node startup ``` **Important Notes**: - Only affects fresh nodes (no existing epoch data) - Set to match your planned pruning retention period - Must be >= `--sync.epochs` if both are set - Does not backfill gaps if increased on existing node #### Configuration via Command-Line Flags You can override config file values with command-line flags: ```bash ./relay_sidecar \ --config config.yaml \ --log.level debug \ --storage-dir /var/lib/relay \ --api.listen ":8080" \ --p2p.listen "/ip4/0.0.0.0/tcp/8880" \ --driver.chain-id 1 \ --driver.address "0x..." \ --secret-keys "symb/0/15/0x...,evm/1/31337/0x..." \ --evm.chains "http://localhost:8545" ``` #### Configuration via Environment Variables Environment variables use the `SYMB_` prefix with underscores instead of dashes and dots: ```bash export SYMB_LOG_LEVEL=debug export SYMB_LOG_MODE=pretty export SYMB_STORAGE_DIR=/var/lib/relay export SYMB_API_LISTEN=":8080" export SYMB_P2P_LISTEN="/ip4/0.0.0.0/tcp/8880" export SYMB_DRIVER_CHAIN_ID=1 export SYMB_DRIVER_ADDRESS="0x..." ./relay_sidecar --config config.yaml ``` #### Configuration Priority Configuration is loaded in the following order (highest priority first): 1. Command-line flags 2. Environment variables (with `SYMB_` prefix) 3. Configuration file (specified by `--config`) #### Example Configuration Generation For reference, see how configurations are generated in the E2E setup: ```bash # See the template in e2e/scripts/sidecar-start.sh (lines 11-27) cat e2e/scripts/sidecar-start.sh ``` To customize the local setup configuration, modify the template in `e2e/scripts/sidecar-start.sh` and run: ```bash make local-setup ``` ### Running the Relay Sidecar Once you have your configuration file ready: ```bash ./relay_sidecar --config config.yaml ``` Or with Docker: ```bash docker run -v $(pwd)/config.yaml:/config.yaml symbioticfi/relay:latest --config /config.yaml ``` ## Contributing We welcome contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for: - Branching strategy and PR process - Code style and linting requirements - Testing requirements For development workflows, API changes, and testing procedures, see [DEVELOPMENT.md](DEVELOPMENT.md). ````