diff --git a/.changeset/brave-dots-breathe.md b/.changeset/brave-dots-breathe.md new file mode 100644 index 00000000000..f1ae4f4d21e --- /dev/null +++ b/.changeset/brave-dots-breathe.md @@ -0,0 +1,7 @@ +--- +"chainlink": minor +--- + +Added a new CLI command, `blocks find-lca,` which finds the latest block that is available in both the database and on the chain for the specified chain. +Added a new CLI command, `node remove-blocks,` which removes all blocks and logs greater than or equal to the specified block number. +#nops #added diff --git a/.changeset/curvy-weeks-cover.md b/.changeset/curvy-weeks-cover.md new file mode 100644 index 00000000000..0b19df8ad16 --- /dev/null +++ b/.changeset/curvy-weeks-cover.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#wip Keystone contract wrappers updated diff --git a/.changeset/dull-dingos-remember.md b/.changeset/dull-dingos-remember.md new file mode 100644 index 00000000000..7c1b748cff7 --- /dev/null +++ b/.changeset/dull-dingos-remember.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +use safe lib for approve #bugfix diff --git a/.changeset/fresh-moles-explode.md b/.changeset/fresh-moles-explode.md new file mode 100644 index 00000000000..205002b40a0 --- /dev/null +++ b/.changeset/fresh-moles-explode.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +core/chains/evm/logpoller: Stricter finality checks in LogPoller, to be more robust during rpc failover events #updated diff --git a/.changeset/fuzzy-pans-destroy.md b/.changeset/fuzzy-pans-destroy.md new file mode 100644 index 00000000000..3cff19f8d8a --- /dev/null +++ b/.changeset/fuzzy-pans-destroy.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Use sqlutil instead of pg.Opts/Q/Queryer #internal diff --git a/.changeset/olive-knives-happen.md b/.changeset/olive-knives-happen.md new file mode 100644 index 00000000000..7f522c96ff1 --- /dev/null +++ b/.changeset/olive-knives-happen.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Generic Plugin `onchainSigningStrategy` support diff --git a/.changeset/pink-schools-provide.md b/.changeset/pink-schools-provide.md new file mode 100644 index 00000000000..6b2aa5ea0c4 --- /dev/null +++ b/.changeset/pink-schools-provide.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix Fixed an issue where the `rebroadcast-transactions` commands did not execute config validation. diff --git a/.changeset/pretty-kangaroos-tell.md b/.changeset/pretty-kangaroos-tell.md new file mode 100644 index 00000000000..946869b1ca0 --- /dev/null +++ b/.changeset/pretty-kangaroos-tell.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add check for valid semvar value for changeset file #internal diff --git a/.changeset/quick-fishes-heal.md b/.changeset/quick-fishes-heal.md new file mode 100644 index 00000000000..966e74c843a --- /dev/null +++ b/.changeset/quick-fishes-heal.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- +#changed +Added prefix `RPCClient returned error ({RPC_NAME})` to RPC errors to simplify filtering of RPC related issues. diff --git a/.changeset/smooth-comics-love.md b/.changeset/smooth-comics-love.md new file mode 100644 index 00000000000..6d41284978d --- /dev/null +++ b/.changeset/smooth-comics-love.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +update keystone gethwrapper with remove operator function #internal diff --git a/.changeset/sour-jars-cross.md b/.changeset/sour-jars-cross.md new file mode 100644 index 00000000000..b904e8e3dd0 --- /dev/null +++ b/.changeset/sour-jars-cross.md @@ -0,0 +1,13 @@ +--- +"chainlink": patch +--- + +#added + +Add configurability to mercury transmitter + +```toml +[Mercury.Transmitter] +TransmitQueueMaxSize = 10_000 # Default +TransmitTimeout = "5s" # Default +``` diff --git a/.changeset/tasty-lions-rhyme.md b/.changeset/tasty-lions-rhyme.md new file mode 100644 index 00000000000..b80f1337bce --- /dev/null +++ b/.changeset/tasty-lions-rhyme.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +add getters #internal diff --git a/.changeset/tidy-trees-tie.md b/.changeset/tidy-trees-tie.md new file mode 100644 index 00000000000..7ff415e9de4 --- /dev/null +++ b/.changeset/tidy-trees-tie.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#changed Updating the log trigger log provider's readMaxBatchSize to 56 diff --git a/.changeset/tricky-bats-exist.md b/.changeset/tricky-bats-exist.md new file mode 100644 index 00000000000..3c748353859 --- /dev/null +++ b/.changeset/tricky-bats-exist.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +minor fixes #bugfix diff --git a/.changeset/two-countries-lay.md b/.changeset/two-countries-lay.md new file mode 100644 index 00000000000..f3d78e6a2e6 --- /dev/null +++ b/.changeset/two-countries-lay.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +update keystone gethwrapper #internal diff --git a/.changeset/warm-impalas-return.md b/.changeset/warm-impalas-return.md new file mode 100644 index 00000000000..167d831692c --- /dev/null +++ b/.changeset/warm-impalas-return.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added JuelsPerFeeCoinCache is enabled by default for OCR2 jobs, added `Disable` field under [pluginConfig.JuelsPerFeeCoinCache] tag to disable this feature (e.g. Disable=true) diff --git a/.changeset/witty-icons-rhyme.md b/.changeset/witty-icons-rhyme.md new file mode 100644 index 00000000000..25d9cf3b1d3 --- /dev/null +++ b/.changeset/witty-icons-rhyme.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +offchain settlement fix #bugfix diff --git a/.ct.yml b/.ct.yml deleted file mode 100644 index 18a6afe861d..00000000000 --- a/.ct.yml +++ /dev/null @@ -1,10 +0,0 @@ -# See: https://github.com/helm/chart-testing -target-branch: develop -chart-dirs: 'charts' -check-version-increment: false -validate-maintainers: false -charts-repos: - - mockserver=https://www.mock-server.com - - opentelemetry-collector=https://open-telemetry.github.io/opentelemetry-helm-charts - - tempo=https://grafana.github.io/helm-charts - - grafana=https://grafana.github.io/helm-charts diff --git a/.github/actions/setup-create-base64-upgrade-config/action.yml b/.github/actions/setup-create-base64-upgrade-config/action.yml index daa2d400262..8f514784725 100644 --- a/.github/actions/setup-create-base64-upgrade-config/action.yml +++ b/.github/actions/setup-create-base64-upgrade-config/action.yml @@ -17,6 +17,23 @@ inputs: default: "public.ecr.aws/chainlink/chainlink" upgradeVersion: description: The git commit sha to use for the image tag + runId: + description: The run id + testLogCollect: + description: Whether to always collect logs, even for passing tests + default: "false" + lokiEndpoint: + description: Loki push endpoint + lokiTenantId: + description: Loki tenant id + lokiBasicAuth: + description: Loki basic auth + logstreamLogTargets: + description: Where to send logs (e.g. file, loki) + grafanaUrl: + description: Grafana URL + grafanaDashboardUrl: + description: Grafana dashboard URL runs: using: composite @@ -31,6 +48,14 @@ runs: CHAINLINK_POSTGRES_VERSION: ${{ inputs.chainlinkPostgresVersion }} UPGRADE_IMAGE: ${{ inputs.upgradeImage }} UPGRADE_VERSION: ${{ inputs.upgradeVersion }} + RUN_ID: ${{ inputs.runId }} + TEST_LOG_COLLECT: ${{ inputs.testLogCollect }} + LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} + LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} + LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} + LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} + GRAFANA_URL: ${{ inputs.grafanaUrl }} + GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} run: | function convert_to_toml_array() { local IFS=',' @@ -47,6 +72,14 @@ runs: selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") + if [ -n "$TEST_LOG_COLLECT" ]; then + test_log_collect=true + else + test_log_collect=false + fi + + log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") + cat << EOF > config.toml [Network] selected_networks=$selected_networks @@ -59,6 +92,23 @@ runs: [ChainlinkUpgradeImage] image="$UPGRADE_IMAGE" version="$UPGRADE_VERSION" + postgres_version="$CHAINLINK_POSTGRES_VERSION" + + [Logging] + test_log_collect=$test_log_collect + run_id="$RUN_ID" + + [Logging.LogStream] + log_targets=$log_targets + + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_ENDPOINT" + basic_auth_secret="$LOKI_BASIC_AUTH" + + [Logging.Grafana] + base_url="$GRAFANA_URL" + dashboard_url="$GRAFANA_DASHBOARD_URL" EOF BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) diff --git a/.github/scripts/check-changeset-tags.sh b/.github/scripts/check-changeset-tags.sh index 579661fe704..f82c16d5769 100755 --- a/.github/scripts/check-changeset-tags.sh +++ b/.github/scripts/check-changeset-tags.sh @@ -29,6 +29,14 @@ if [[ ! -f "$CHANGESET_FILE_PATH" ]]; then exit 1 fi +changeset_content=$(sed -n '/^---$/,/^---$/{ /^---$/!p; }' $CHANGESET_FILE_PATH) +semvar_value=$(echo "$changeset_content" | awk -F": " '/"chainlink"/ {print $2}') + +if [[ "$semvar_value" != "major" && "$semvar_value" != "minor" && "$semvar_value" != "patch" ]]; then + echo "Invalid changeset semvar value for 'chainlink'. Must be 'major', 'minor', or 'patch'." + exit 1 +fi + while IFS= read -r line; do for tag in "${tags_list[@]}"; do if [[ "$line" == *"$tag"* ]]; then diff --git a/.github/workflows/automation-nightly-tests.yml b/.github/workflows/automation-nightly-tests.yml index c3b874548ac..b44a7f56e65 100644 --- a/.github/workflows/automation-nightly-tests.yml +++ b/.github/workflows/automation-nightly-tests.yml @@ -95,6 +95,14 @@ jobs: chainlinkVersion: "latest" upgradeImage: ${{ env.CHAINLINK_IMAGE }} upgradeVersion: ${{ github.sha }} + runId: ${{ github.run_id }} + testLogCollect: "true" + lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 env: diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index 167dccf3bbf..dade0f331b9 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -226,7 +226,15 @@ jobs: UPGRADE_IMAGE: ${{ steps.determine-build.outputs.upgrade_image }} PYROSCOPE_SERVER: ${{ matrix.tests.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 PYROSCOPE_ENVIRONMENT: ${{ matrix.tests.pyroscope_env }} - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + RUN_ID: ${{ github.run_id }} + TEST_LOG_COLLECT: "true" + LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + LOGSTREAM_LOG_TARGETS: ${{ vars.LOGSTREAM_LOG_TARGETS }} + GRAFANA_URL: ${{ vars.GRAFANA_URL }} + GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" run: | echo ::add-mask::$UPGRADE_IMAGE echo ::add-mask::$OLD_IMAGE @@ -242,6 +250,14 @@ jobs: pyroscope_enabled=false fi + if [ -n "$TEST_LOG_COLLECT" ]; then + test_log_collect=true + else + test_log_collect=false + fi + + log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") + cat << EOF > config.toml [Network] selected_networks=$selected_networks @@ -254,6 +270,22 @@ jobs: image="$UPGRADE_IMAGE" version="$UPGRADE_VERSION" + [Logging] + test_log_collect=$test_log_collect + run_id="$RUN_ID" + + [Logging.LogStream] + log_targets=$log_targets + + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_ENDPOINT" + basic_auth_secret="$LOKI_BASIC_AUTH" + + [Logging.Grafana] + base_url="$GRAFANA_URL" + dashboard_url="$GRAFANA_DASHBOARD_URL" + [Pyroscope] enabled=$pyroscope_enabled server_url="$PYROSCOPE_SERVER" diff --git a/.github/workflows/helm-chart-publish.yml b/.github/workflows/helm-chart-publish.yml deleted file mode 100644 index 927ed4b0166..00000000000 --- a/.github/workflows/helm-chart-publish.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Helm Publish - -on: - workflow_dispatch: - -jobs: - helm_release: - runs-on: ubuntu-latest - environment: build-develop - permissions: - id-token: write - contents: read - steps: - - name: Checkout repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - name: Configure aws credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN_GATI }} - role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} - aws-region: ${{ secrets.AWS_REGION }} - mask-aws-account-id: true - role-session-name: helm-publish.helm-release - - - name: Get Github Token - id: get-gh-token - uses: smartcontractkit/chainlink-github-actions/github-app-token-issuer@5874ff7211cf5a5a2670bb010fbff914eaaae138 # v2.3.12 - with: - url: ${{ secrets.GATI_LAMBDA_FUNCTION_URL }} - - - name: Install Helm - uses: azure/setup-helm@b7246b12e77f7134dc2d460a3d5bad15bbe29390 # v4.1.0 - - - name: Run chart-releaser - uses: helm/chart-releaser-action@a917fd15b20e8b64b94d9158ad54cd6345335584 # v1.6.0 - with: - charts_dir: charts - config: .github/cr.yaml - env: - CR_TOKEN: "${{ steps.get-gh-token.outputs.access-token }}" diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml deleted file mode 100644 index f0dd25c5dbb..00000000000 --- a/.github/workflows/helm-chart.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Helm Chart - -on: - pull_request: - paths: - - "charts/**" - - ".github/workflows/helm-chart.yml" - -jobs: - ci-lint-helm-charts: - runs-on: ubuntu-latest - steps: - - name: ci-lint-helm-charts - uses: smartcontractkit/.github/actions/ci-lint-charts@7fa39741b11e66ed59f8aad786d4b9356c389f3f # ci-lint-charts@0.2.0 - with: - # chart testing inputs - chart-testing-extra-args: "--lint-conf=lintconf.yaml" - charts-dir: charts/chainlink-cluster - # grafana inputs - metrics-job-name: ci-lint-helm-charts - gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} - gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - - ci-kubeconform: - runs-on: ubuntu-latest - steps: - - name: ci-kubeconform - uses: smartcontractkit/.github/actions/ci-kubeconform@1ae8a9a984814c4daf50aa96f03be2cba0ef3fec # ci-kubeconform@0.2.0 - with: - # kubeform inputs - charts-dir: charts/chainlink-cluster - # grafana inputs - metrics-job-name: ci-kubeconform - gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} - gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 6c7312293be..b840a077bbd 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -218,40 +218,6 @@ jobs: AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} dep_evm_sha: ${{ inputs.evm-ref }} - build-test-image: - if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'schedule' || contains(join(github.event.pull_request.labels.*.name, ' '), 'build-test-image') - environment: integration - permissions: - id-token: write - contents: read - name: Build Test Image - runs-on: ubuntu22.04-16cores-64GB - needs: [changes] - steps: - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ${{ env.COLLECTION_ID }}-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Test Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Test Image - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - compare-tests: needs: [changes] runs-on: ubuntu-latest @@ -565,12 +531,12 @@ jobs: pyroscope_env: ci-smoke-vrf-evm-simulated - name: vrfv2 id: vrfv2 - nodes: 4 + nodes: 5 os: ubuntu-latest pyroscope_env: ci-smoke-vrf2-evm-simulated - name: vrfv2plus id: vrfv2plus - nodes: 7 + nodes: 8 os: ubuntu-latest pyroscope_env: ci-smoke-vrf2plus-evm-simulated - name: forwarder_ocr @@ -728,7 +694,7 @@ jobs: cache_restore_only: "true" QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + QA_KUBECONFIG: "" should_tidy: "false" - name: Show Otel-Collector Logs if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' @@ -832,6 +798,7 @@ jobs: # Run the setup if the matrix finishes but this time save the cache if we have a cache hit miss # this will also only run if both of the matrix jobs pass eth-smoke-go-mod-cache: + environment: integration needs: [eth-smoke-tests] runs-on: ubuntu-latest @@ -865,7 +832,7 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - needs: [build-chainlink, changes, build-test-image] + needs: [build-chainlink, changes] # Only run migration tests on new tags if: startsWith(github.ref, 'refs/tags/') env: @@ -878,6 +845,17 @@ jobs: TEST_LOG_LEVEL: debug TEST_SUITE: migration steps: + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + with: + id: ${{ env.COLLECTION_ID }}-migration-tests + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Version Migration Tests + test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' + continue-on-error: true - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: @@ -888,7 +866,12 @@ jobs: run: | untrimmed_ver=$(curl --header "Authorization: token ${{ secrets.GITHUB_TOKEN }}" --request GET https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .name) latest_version="${untrimmed_ver:1}" - echo "latest_version=${latest_version} | tee -a $GITHUB_OUTPUT" + # Check if latest_version is empty + if [ -z "$latest_version" ]; then + echo "Error: The latest_version is empty. The migration tests need a verison to run." + exit 1 + fi + echo "latest_version=${latest_version}" >> "$GITHUB_OUTPUT" - name: Name Versions run: | echo "Running migration tests from version '${{ steps.get_latest_version.outputs.latest_version }}' to: '${{ inputs.evm-ref || github.sha }}'" @@ -900,13 +883,22 @@ jobs: chainlinkVersion: ${{ steps.get_latest_version.outputs.latest_version }} upgradeImage: ${{ env.UPGRADE_IMAGE }} upgradeVersion: ${{ env.UPGRADE_VERSION }} + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Run Migration Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@519851800779323566b7b7c22cc21bff95dbb639 # v2.3.11 with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage + test_command_to_run: cd ./integration-tests && go test -timeout 20m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage test_download_vendor_packages_command: cd ./integration-tests && go mod download cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ steps.get_latest_version.outputs.latest_version }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: node-migration-test-logs artifacts_location: | ./integration-tests/migration/logs @@ -918,28 +910,24 @@ jobs: cache_restore_only: "true" QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + QA_KUBECONFIG: "" go_coverage_src_dir: /var/tmp/go-coverage go_coverage_dest_dir: ${{ github.workspace }}/.covdata + should_tidy: "false" - name: Upload Coverage Data uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: cl-node-coverage-data-migration-tests path: .covdata retention-days: 1 - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + - name: Notify Slack + if: failure() && github.event_name != 'workflow_dispatch' + uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 + env: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} with: - id: ${{ env.COLLECTION_ID }}-migration-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Version Migration Tests - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true + channel-id: "#team-test-tooling-internal" + slack-message: ":x: :mild-panic-intensifies: Node Migration Tests Failed: ${{ job.html_url }}\n${{ format('https://github.com/smartcontractkit/chainlink/actions/runs/{0}', github.run_id) }}" ## Solana Section get_solana_sha: diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index 5940313fc65..b2dc3d4153c 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -258,10 +258,7 @@ jobs: uses: smartcontractkit/.github/actions/ci-publish-npm@4b0ab756abcb1760cb82e1e87b94ff431905bffc # ci-publish-npm@0.4.0 with: npm-token: ${{ secrets.NPM_TOKEN }} - github-token: ${{ secrets.GITHUB_TOKEN }} - github-release-tag-name: ${{ github.ref_name }} - github-release-changelog-path: "contracts/CHANGELOG.md" - create-github-release: true + create-github-release: false publish-command: "pnpm publish-prod --no-git-checks" package-json-directory: contracts diff --git a/.gitignore b/.gitignore index 88dbe55aedf..bcf51bea35b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ tools/clroot/db.sqlite3-wal .envrc .env* .dbenv -!charts/chainlink-cluster/.env.example !crib/.env.example !.github/actions/setup-postgres/.env .direnv diff --git a/GNUmakefile b/GNUmakefile index 524786585e9..48e15e39fb4 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -33,7 +33,7 @@ gomodtidy: ## Run go mod tidy on all modules. cd ./integration-tests && go mod tidy cd ./integration-tests/load && go mod tidy cd ./dashboard-lib && go mod tidy - cd ./charts/chainlink-cluster && go mod tidy + cd ./crib && go mod tidy .PHONY: docs docs: ## Install and run pkgsite to view Go docs @@ -96,7 +96,7 @@ generate: abigen codecgen mockery protoc ## Execute all go:generate commands. cd ./integration-tests && go generate -x ./... cd ./integration-tests/load && go generate -x ./... cd ./dashboard-lib && go generate -x ./... - cd ./charts/chainlink-cluster && go generate -x ./... + cd ./crib && go generate -x ./... .PHONY: testscripts testscripts: chainlink-test ## Install and run testscript against testdata/scripts/* files. diff --git a/charts/chainlink-cluster/.gitignore b/charts/chainlink-cluster/.gitignore deleted file mode 100644 index 9e704020530..00000000000 --- a/charts/chainlink-cluster/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Helm -charts/ -requirements.lock -.rendered -values-profiles/* -!values-profiles/values-dev.yaml.example -!values-profiles/README.md \ No newline at end of file diff --git a/charts/chainlink-cluster/.helmignore b/charts/chainlink-cluster/.helmignore deleted file mode 100644 index b88381301b2..00000000000 --- a/charts/chainlink-cluster/.helmignore +++ /dev/null @@ -1,25 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ -.devspace/ -scripts/ diff --git a/charts/chainlink-cluster/Chart.lock b/charts/chainlink-cluster/Chart.lock deleted file mode 100644 index 11ebdfdf691..00000000000 --- a/charts/chainlink-cluster/Chart.lock +++ /dev/null @@ -1,15 +0,0 @@ -dependencies: -- name: mockserver - repository: https://www.mock-server.com - version: 5.14.0 -- name: opentelemetry-collector - repository: https://open-telemetry.github.io/opentelemetry-helm-charts - version: 0.82.0 -- name: tempo - repository: https://grafana.github.io/helm-charts - version: 1.7.2 -- name: grafana - repository: https://grafana.github.io/helm-charts - version: 7.3.2 -digest: sha256:37722063f68689c42ac1d6549ddfae4756370c1659b8ac1c0d7da8916c6fad3d -generated: "2024-04-23T17:49:50.347667-04:00" diff --git a/charts/chainlink-cluster/Chart.yaml b/charts/chainlink-cluster/Chart.yaml deleted file mode 100644 index d8d3dd98b22..00000000000 --- a/charts/chainlink-cluster/Chart.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: v2 -name: chainlink-cluster -description: Chainlink nodes cluster -version: 0.4.2 -appVersion: "2.6.0" -dependencies: - - name: mockserver - version: "5.14.0" - repository: "https://www.mock-server.com" - condition: mockserver.enabled - - name: opentelemetry-collector - version: "0.82.0" - repository: "https://open-telemetry.github.io/opentelemetry-helm-charts" - condition: opentelemetry-collector.enabled - - name: tempo - version: "1.7.2" - repository: "https://grafana.github.io/helm-charts" - condition: tempo.enabled - - name: grafana - version: "7.3.2" - repository: "https://grafana.github.io/helm-charts" - condition: grafana.enabled diff --git a/charts/chainlink-cluster/README.md b/charts/chainlink-cluster/README.md deleted file mode 100644 index 403ab9b876a..00000000000 --- a/charts/chainlink-cluster/README.md +++ /dev/null @@ -1,174 +0,0 @@ -# Chainlink cluster - -Example CL nodes cluster for system level tests -Install `kubefwd` (no nixpkg for it yet, planned) - -```sh -brew install txn2/tap/kubefwd -``` - -If you want to build images you need [docker](https://docs.docker.com/engine/install/) service running - -Enter the shell (from the root project dir) - -```sh -nix develop -``` - -# Develop - -## New cluster - -We are using [devspace](https://www.devspace.sh/docs/getting-started/installation?x0=3) - -Configure the cluster, see `deployments.app.helm.values` and [values.yaml](./values.yaml) comments for more details - -Set up your K8s access - -```sh -export DEVSPACE_IMAGE="..." -./setup.sh ${my-personal-namespace-name-crib} -``` - -Create a .env file based on the .env.sample file - -```sh -cp .env.sample .env -# Fill in the required values in .env -``` - -Build and deploy the current state of your repository - -```sh -devspace deploy -``` - -Default `ttl` is `72h`, use `ttl` command to update if you need more time - -Valid values are `1h`, `2m`, `3s`, etc. Go time format is invalid `1h2m3s` - -```sh -devspace run ttl ${namespace} 120h -``` - -If you want to deploy an image tag that is already available in ECR, use: - -```sh -devspace deploy --override-image-tag "" -``` - -If you want to deploy an image tag from a public ECR repo, use: - -```sh -export DEVSPACE_IMAGE=public.ecr.aws/chainlink/chainlink -devspace deploy --override-image-tag 2.9.0 -``` - -To apply custom TOML configuration specific for your nodes, create a `values-dev.yaml` file in the `./values-profiles` directory. Start by copying the example file: - -```sh -cp values-profiles/values-dev.yaml.example values-profiles/values-dev.yaml - -``` - -Then customize the values-dev.yaml file as needed. To use this configuration during deployment, pass the --profile local-dev flag: - -```sh -devspace deploy --profile local-dev -``` - -Forward ports to check UI or run tests - -```sh -devspace run connect ${my-personal-namespace-name-crib} -``` - -List ingress hostnames - -```sh -devspace run ingress-hosts -``` - -Destroy the cluster - -```sh -devspace purge -``` - -## Running load tests - -Check this [doc](../../integration-tests/load/ocr/README.md) - -If you used `devspace dev ...` always use `devspace reset pods` to switch the pods back - -# Helm - -If you would like to use `helm` directly, please uncomment data in `values.yaml` - -## Install from local files - -```sh -helm install -f values.yaml cl-cluster . -``` - -Forward all apps (in another terminal) - -```sh -sudo kubefwd svc -n cl-cluster -``` - -Then you can connect and run your tests - -## Install from release - -Add the repository - -```sh -helm repo add chainlink-cluster https://raw.githubusercontent.com/smartcontractkit/chainlink/helm-release/ -helm repo update -``` - -Set default namespace - -```sh -kubectl create ns cl-cluster -kubectl config set-context --current --namespace cl-cluster -``` - -## Create a new release - -Bump version in `Chart.yml` add your changes and add `helm_release` label to any PR to trigger a release - -## Helm Test - -```sh -helm test cl-cluster -``` - -## Uninstall - -```sh -helm uninstall cl-cluster -``` - -# Grafana dashboard - -We are using [Grabana](https://github.com/K-Phoen/grabana) lib to create dashboards programmatically - -You can also select dashboard platform in `INFRA_PLATFORM` either `kubernetes` or `docker` - -```sh -export LOKI_TENANT_ID=promtail -export LOKI_URL=... -export GRAFANA_URL=... -export GRAFANA_TOKEN=... -export PROMETHEUS_DATA_SOURCE_NAME=Thanos -export LOKI_DATA_SOURCE_NAME=Loki -export INFRA_PLATFORM=kubernetes -export GRAFANA_FOLDER=CRIB -export DASHBOARD_NAME=Core-Cluster-Load - -devspace run dashboard_deploy -``` - -Open Grafana folder `DashboardCoreDebug` and find dashboard `ChainlinkClusterDebug` diff --git a/charts/chainlink-cluster/templates/chainlink-cm.yaml b/charts/chainlink-cluster/templates/chainlink-cm.yaml deleted file mode 100644 index bd0c911331c..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-cm.yaml +++ /dev/null @@ -1,77 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: {{ $.Release.Name }}-{{ $cfg.name }}-cm - release: {{ $.Release.Name }} - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm -data: - apicredentials: | - notreal@fakeemail.ch - fj293fbBnlQ!f9vNs - node-password: T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ - init.sql: | - CREATE - EXTENSION pg_stat_statements; - default.toml: | - {{- if (hasKey $cfg "toml") }} - {{ $cfg.toml | nindent 4 }} - {{- else if and (hasKey $.Values.chainlink.global "toml") $.Values.chainlink.global.toml }} - {{ $.Values.chainlink.global.toml | nindent 4 }} - {{- else }} - RootDir = './clroot' - [Log] - JSONConsole = true - Level = 'debug' - [WebServer] - AllowOrigins = '*' - SecureCookies = false - SessionTimeout = '999h0m0s' - [Feature] - FeedsManager = true - LogPoller = true - UICSAKeys = true - [OCR] - Enabled = true - DefaultTransactionQueueDepth = 0 - [P2P] - [P2P.V2] - Enabled = true - ListenAddresses = ['0.0.0.0:6690'] - AnnounceAddresses = ['0.0.0.0:6690'] - DeltaDial = '500ms' - DeltaReconcile = '5s' - {{- range $chainCfg := $.Values.geth.chains }} - [[EVM]] - ChainID = {{ $chainCfg.networkId | quote }} - MinContractPayment = '0' - AutoCreateKey = true - FinalityDepth = 1 - {{- if (hasKey $chainCfg "customEVMConfigToml") }} - {{- $chainCfg.customEVMConfigToml | nindent 4 }} - {{- end }} - [[EVM.Nodes]] - Name = 'node-{{ $chainCfg.networkId }}' - WSURL = 'ws://geth-{{ $chainCfg.networkId }}:8546' - HTTPURL = 'http://geth-{{ $chainCfg.networkId }}:8544' - {{- end }} - [WebServer.TLS] - HTTPSPort = 0 - {{- end }} - overrides.toml: | - {{- if (hasKey $cfg "overridesToml") }} - {{- $cfg.overridesToml | nindent 4 }} - {{- else if and (hasKey $.Values.chainlink.global "overridesToml") $.Values.chainlink.global.overridesToml }} - {{- $.Values.chainlink.global.overridesToml | nindent 4 }} - {{ else }} - {{- end }} - secrets.toml: | - {{ if (hasKey $cfg "secretsToml") }} - {{ $cfg.secretsToml | nindent 4 }} - {{ else }} - {{ end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-db-deployment.yaml b/charts/chainlink-cluster/templates/chainlink-db-deployment.yaml deleted file mode 100644 index 0ca7c4afd71..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-db-deployment.yaml +++ /dev/null @@ -1,154 +0,0 @@ -{{- if .Values.db.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: apps/v1 -{{ if $.Values.db.stateful }} -kind: StatefulSet -{{ else }} -kind: Deployment -{{ end }} -metadata: - name: {{ $.Release.Name }}-{{ $cfg.name }}-db - labels: - app: {{ $.Release.Name }}-db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} -spec: - {{ if $.Values.db.stateful }} - serviceName: {{ $.Release.Name }}-db-${{ $cfg.name }} - podManagementPolicy: Parallel - volumeClaimTemplates: - - metadata: - name: postgres - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.db.capacity }} - {{ end }} - selector: - matchLabels: - app: {{ $.Release.Name }}-db - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: db - havoc-network-group: db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} - template: - metadata: - labels: - app: {{ $.Release.Name }}-db - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: db - havoc-network-group: db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} - annotations: - prometheus.io/scrape: 'true' - app.kubernetes.io/managed-by: "Helm" - meta.helm.sh/release-namespace: "{{ $.Release.Namespace }}" - {{- range $key, $value := $.Values.podAnnotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - spec: - volumes: - # TODO: breakout this config map into a separate one for the db. - - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - configMap: - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - securityContext: - {{- toYaml $.Values.db.podSecurityContext | nindent 8 }} - containers: - - name: chainlink-db - securityContext: - {{- toYaml $.Values.db.securityContext | nindent 12 }} - image: {{ default "postgres:11.15" $.Values.db.image }} - command: - - docker-entrypoint.sh - args: - - "-c" - - "shared_preload_libraries=pg_stat_statements" - - "-c" - - "pg_stat_statements.track=all" - ports: - - name: postgres - containerPort: 5432 - env: - - name: POSTGRES_DB - value: chainlink - - name: POSTGRES_PASSWORD - value: verylongdatabasepassword - - name: PGPASSWORD - value: verylongdatabasepassword - - name: PGUSER - value: postgres - lifecycle: - preStop: - exec: - command: [ "/bin/sh", "-c", "while $(psql -d chainlink -c \"SELECT COUNT(*) FROM pg_stat_activity WHERE datname = 'chainlink' AND state = 'active';\" -tA ); echo \"waiting for connection to become 0\"; sleep 10; fi; done" ] - livenessProbe: - exec: - command: - - pg_isready - - -U - - postgres - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - readinessProbe: - exec: - command: - - pg_isready - - -U - - postgres - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - startupProbe: - exec: - command: - - pg_isready - - -U - - postgres - initialDelaySeconds: 15 - periodSeconds: 5 - failureThreshold: 20 - {{ if (hasKey $.Values.db "resources") }} - resources: - requests: - memory: {{ default "256Mi" $.Values.db.resources.requests.memory }} - cpu: {{ default "250m" $.Values.db.resources.requests.cpu }} - limits: - memory: {{ default "256Mi" $.Values.db.resources.limits.memory }} - cpu: {{ default "250m" $.Values.db.resources.limits.cpu }} - {{ else }} - {{ end }} - volumeMounts: - - mountPath: /docker-entrypoint-initdb.d/init.sql - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - subPath: init.sql - {{ if $.Values.db.stateful }} - - mountPath: /var/lib/postgresql/data - name: postgres - subPath: postgres-db - {{ end }} -{{- with $.Values.nodeSelector }} - nodeSelector: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.affinity }} - affinity: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} -{{- end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-db-networkpolicy.yaml b/charts/chainlink-cluster/templates/chainlink-db-networkpolicy.yaml deleted file mode 100644 index 53664884f26..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-db-networkpolicy.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.db.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-db -spec: - podSelector: - matchLabels: - app: {{ $.Release.Name }}-db - policyTypes: - - Ingress - ingress: - - from: - # Allow all node pods to access the database pods. - - podSelector: - matchLabels: - app: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 5432 -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-db-service.yaml b/charts/chainlink-cluster/templates/chainlink-db-service.yaml deleted file mode 100644 index 5ed7d0ca4dd..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-db-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.db.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: Service -metadata: - name: {{ $.Release.Name }}-db-{{ $cfg.name }} -spec: - selector: - app: {{ $.Release.Name }}-db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 5432 - targetPort: 5432 ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-node-deployment.yaml b/charts/chainlink-cluster/templates/chainlink-node-deployment.yaml deleted file mode 100644 index e91a400967a..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-node-deployment.yaml +++ /dev/null @@ -1,130 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $index, $cfg := .Values.chainlink.nodes }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ if eq $index 0 }}{{ $.Release.Name }}-{{ $cfg.name }}-bootstrap{{ else }}{{ $.Release.Name }}-{{ $cfg.name }}{{ end }} - labels: - app: {{ $.Release.Name }} - instance: {{ $cfg.name }} - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - strategy: - # Need to recreate the pod to deal with lease lock held by old pod. - type: Recreate - selector: - matchLabels: - app: {{ $.Release.Name }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - {{ if eq $index 0 }}{{ else }} - havoc-component-group: node - {{ end }} - {{ if eq $index 0 }}{{ else }} - havoc-network-group: {{ if gt $index 2 }}"1"{{ else }}"2"{{ end }} - {{ end }} - instance: {{ $cfg.name }} - release: {{ $.Release.Name }} - template: - metadata: - labels: - app: {{ $.Release.Name }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - {{ if eq $index 0 }}{{ else }} - havoc-component-group: node - {{ end }} - {{ if eq $index 0 }}{{ else }} - havoc-network-group: {{ if gt $index 2 }}"1"{{ else }}"2"{{ end }} - {{ end }} - - instance: {{ $cfg.name }} - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} - annotations: - prometheus.io/scrape: 'true' - {{- range $key, $value := $.Values.podAnnotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - spec: - volumes: - - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - configMap: - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - securityContext: - {{- toYaml $.Values.chainlink.podSecurityContext | nindent 8 }} - containers: - - name: node - securityContext: - {{- toYaml $.Values.chainlink.securityContext | nindent 12 }} - image: {{ default "public.ecr.aws/chainlink/chainlink" $cfg.image }} - imagePullPolicy: Always - command: [ "bash", "-c", "while ! pg_isready -U postgres --host {{ $.Release.Name }}-db-{{ $cfg.name }} --port 5432; do echo \"waiting for database to start\"; sleep 1; done && chainlink -c /etc/node-secrets-volume/default.toml -c /etc/node-secrets-volume/overrides.toml -secrets /etc/node-secrets-volume/secrets.toml node start -d -p /etc/node-secrets-volume/node-password -a /etc/node-secrets-volume/apicredentials --vrfpassword=/etc/node-secrets-volume/apicredentials" ] - ports: - - name: access - containerPort: {{ $.Values.chainlink.web_port }} - - name: p2p - containerPort: {{ $.Values.chainlink.p2p_port }} - env: - - name: CL_DATABASE_URL - value: postgresql://postgres:verylongdatabasepassword@{{ $.Release.Name }}-db-{{ $cfg.name }}/chainlink?sslmode=disable - - name: CL_DEV - value: "false" - {{- range $name, $value := $.Values.chainlink.extraEnvVars }} - - name: "{{ $name }}" - value: "{{ $value }}" - {{- end }} - volumeMounts: - - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - mountPath: /etc/node-secrets-volume/ - livenessProbe: - httpGet: - path: /health - port: {{ $.Values.chainlink.web_port }} - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - readinessProbe: - httpGet: - path: /health - port: {{ $.Values.chainlink.web_port }} - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - startupProbe: - httpGet: - path: / - port: {{ $.Values.chainlink.web_port }} - initialDelaySeconds: 15 - periodSeconds: 5 - failureThreshold: 20 - {{ if (hasKey $cfg "resources") }} - resources: - requests: - memory: {{ default "1024Mi" $cfg.resources.requests.memory }} - cpu: {{ default "300m" $cfg.resources.requests.cpu }} - limits: - memory: {{ default "1024Mi" $cfg.resources.limits.memory }} - cpu: {{ default "300m" $cfg.resources.limits.cpu }} - {{ else }} - {{ end }} -{{- with $.Values.nodeSelector }} - nodeSelector: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.affinity }} - affinity: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} -{{- end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-node-networkpolicy.yaml b/charts/chainlink-cluster/templates/chainlink-node-networkpolicy.yaml deleted file mode 100644 index 8f465288767..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-node-networkpolicy.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.chainlink.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-node -spec: - podSelector: - matchLabels: - app: {{ $.Release.Name }} - policyTypes: - - Ingress - ingress: - # Allow all ingress traffic between the node pods. - - from: - - podSelector: - matchLabels: - app: {{ $.Release.Name }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-node-service.yaml b/charts/chainlink-cluster/templates/chainlink-node-service.yaml deleted file mode 100644 index 71b9ca498d2..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-node-service.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: Service -metadata: - name: {{ $.Release.Name }}-{{ $cfg.name }} -spec: - ports: - - name: node-port - port: {{ $.Values.chainlink.web_port }} - targetPort: {{ $.Values.chainlink.web_port }} - - name: p2p-port - port: {{ $.Values.chainlink.p2p_port }} - targetPort: {{ $.Values.chainlink.p2p_port }} - selector: - instance: {{ $cfg.name }} - type: ClusterIP ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml b/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml deleted file mode 100644 index bb8c5d2b1a6..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.chainlink.enabled .Values.prometheusMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: PodMonitor -metadata: - name: {{ $.Release.Name }}-pod-monitor - labels: - release: grafana-agent -spec: - namespaceSelector: - matchNames: - - {{ $.Release.Namespace }} - podMetricsEndpoints: - - port: access - selector: - matchLabels: - app: {{ $.Release.Name }} -{{- end }} ---- \ No newline at end of file diff --git a/charts/chainlink-cluster/templates/chainlink-secret.yaml b/charts/chainlink-cluster/templates/chainlink-secret.yaml deleted file mode 100644 index f0531b16511..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-secret.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ $.Release.Name }}-{{ $cfg.name }}node-creds-secret -type: Opaque -data: - nodepassword: VC50TEhrY213ZVBUL3AsXXNZdW50andIS0FzcmhtIzRlUnM0THVLSHd2SGVqV1lBQzJKUDRNOEhpbXdnbWJhWgo= - apicredentials: bm90cmVhbEBmYWtlZW1haWwuY2hudHdvY2hhaW5zCg== - node-password: VC50TEhrY213ZVBUL3AsXXNZdW50andIS0FzcmhtIzRlUnM0THVLSHd2SGVqV1lBQzJKUDRNOEhpbXdnbWJhWgo= ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-config-map.yaml b/charts/chainlink-cluster/templates/geth-config-map.yaml deleted file mode 100644 index 6a5f4bacc0d..00000000000 --- a/charts/chainlink-cluster/templates/geth-config-map.yaml +++ /dev/null @@ -1,155 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- range $cfg := .Values.geth.chains }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: geth-{{ $cfg.networkId }}-cm - release: {{ $.Release.Name }} - name: geth-{{ $cfg.networkId }}-cm -data: - key1: | - {"address":"f39fd6e51aad88f6f4ce6ab8827279cfffb92266","crypto":{"cipher":"aes-128-ctr","ciphertext":"c36afd6e60b82d6844530bd6ab44dbc3b85a53e826c3a7f6fc6a75ce38c1e4c6","cipherparams":{"iv":"f69d2bb8cd0cb6274535656553b61806"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"80d5f5e38ba175b6b89acfc8ea62a6f163970504af301292377ff7baafedab53"},"mac":"f2ecec2c4d05aacc10eba5235354c2fcc3776824f81ec6de98022f704efbf065"},"id":"e5c124e9-e280-4b10-a27b-d7f3e516b408","version":3} - key2: | - {"address":"70997970c51812dc3a010c7d01b50e0d17dc79c8","crypto":{"cipher":"aes-128-ctr","ciphertext":"f8183fa00bc112645d3e23e29a233e214f7c708bf49d72750c08af88ad76c980","cipherparams":{"iv":"796d08e3e1f71bde89ed826abda96cda"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"03c864a22a1f7b06b1da12d8b93e024ac144f898285907c58b2abc135fc8a35c"},"mac":"5fe91b1a1821c0d9f85dfd582354ead9612e9a7e9adc38b06a2beff558c119ac"},"id":"d2cab765-5e30-42ae-bb91-f090d9574fae","version":3} - key3: | - {"address":"3c44cdddb6a900fa2b585dd299e03d12fa4293bc","crypto":{"cipher":"aes-128-ctr","ciphertext":"2cd6ab87086c47f343f2c4d957eace7986f3b3c87fc35a2aafbefb57a06d9f1c","cipherparams":{"iv":"4e16b6cd580866c1aa642fb4d7312c9b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"0cabde93877f6e9a59070f9992f7a01848618263124835c90d4d07a0041fc57c"},"mac":"94b7776ea95b0ecd8406c7755acf17b389b7ebe489a8942e32082dfdc1f04f57"},"id":"ade1484b-a3bb-426f-9223-a1f5e3bde2e8","version":3} - key4: | - {"address":"90f79bf6eb2c4f870365e785982e1f101e93b906","crypto":{"cipher":"aes-128-ctr","ciphertext":"15144214d323871e00f7b205368128061c91b77a27b7deec935f8f5b734f0d42","cipherparams":{"iv":"bb22ba8051ef9f60abded7a9f4f2c6ae"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"07331ef3035567c00830b4e50d5dd68bc877974b4ce38cd42fef755be01556c9"},"mac":"2294eacadaf2761851814451d8c7dcca20a606a0344335d98f09403aba4e82ca"},"id":"96af8cc7-97e1-4bba-8968-632b034986c2","version":3} - key5: | - {"address":"15d34aaf54267db7d7c367839aaf71a00a2c6a65","crypto":{"cipher":"aes-128-ctr","ciphertext":"057878284a6c74d3ad99910adddd6b477b383837dbf2280efea585f0f0fdb012","cipherparams":{"iv":"e6eab29d60b526f305f8d47badf48687"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"dfdca8066d2486da5cb9a909d03744e2a8c6537930271e85e7cd8a5d952c0f22"},"mac":"f8352be41c9a06d69111ca4d8fcff0eef079b68b1173cad99803538991716c5d"},"id":"a35bb452-0d57-42d5-8d25-5a00a40a4db8","version":3} - key6: | - {"address":"9965507d1a55bcc2695c58ba16fb37d819b0a4dc","crypto":{"cipher":"aes-128-ctr","ciphertext":"5a73201500307c6aa98edd44d962b344a893768331454a61595ec848e738e9d2","cipherparams":{"iv":"5282de2b3e2b305019a2fed5c62f3383"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"6ad001831d097f175fff7d6cf61301e9620b32afd9a7a6437e6030af14576a96"},"mac":"0a55eddbd13c713aa8b8c4106b2fb62bc1d1e18e7177207a444f83a4d8426ed5"},"id":"27aed2b2-cb94-4d37-8819-b15219187bb5","version":3} - key7: | - {"address":"976ea74026e726554db657fa54763abd0c3a0aa9","crypto":{"cipher":"aes-128-ctr","ciphertext":"a6edf11e81b38e60a549696236cb9efc026e87adc45a9521ea7b2c45a2a9fbb9","cipherparams":{"iv":"82f4c79cd4b28a8585a9c78d758f832b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"87400e16ecc320dadff85eccbf4dbaaea2dd91e50047e4aa391799bb319c1fd8"},"mac":"80c83dad05998db6c673a97096fcfad54636458f4a3c82483686b253f8cc9b69"},"id":"fc7d7694-6206-48fc-bb25-36b523f90df6","version":3} - key8: | - {"address":"14dc79964da2c08b23698b3d3cc7ca32193d9955","crypto":{"cipher":"aes-128-ctr","ciphertext":"410f258bc8b12a0250cba22cbc5e413534fcf90bf322ced6943189ad9e43b4b9","cipherparams":{"iv":"1dd6077a8bee9b3bf2ca90e6abc8a237"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"5d3358bf99bbcb82354f40e5501abf4336bc141ee05d8feed4fbe7eb8c08c917"},"mac":"9cd959fa1e8129a8deb86e0264ec81d6cde79b5a19ae259b7d00543c9037908a"},"id":"689d7ad2-fe46-4c09-9c2a-a50e607989b8","version":3} - key9: | - {"address":"23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f","crypto":{"cipher":"aes-128-ctr","ciphertext":"13dccac740314edea20d44e6f3592575bbcb739ec5892d635326cff3c386eb86","cipherparams":{"iv":"bf42d811cd41fa97ddcae3425f8c3211"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d2fa67cbb5e86d5bf9a90e27b8747bac493614b45778d43e9da1c14e06b2401d"},"mac":"7d2797cf344704d8f36265238d3938e06952c78ab7dfcbac53dc7f472c93d933"},"id":"4c8e899e-80f0-4417-9b1e-c5e29049f1e7","version":3} - key10: | - {"address":"a0ee7a142d267c1f36714e4a8f75612f20a79720","crypto":{"cipher":"aes-128-ctr","ciphertext":"56bc8766f47aeafae74eea333e1e890a3776d7fae6c48cbdbffb270655ce050d","cipherparams":{"iv":"a66129e6a110b3ddf93b4355aa147c58"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"15c4e8bcc80920139eb236d91194825f1fce27dd2af281e0f2752d8a5dbc48bd"},"mac":"db01e720866ce8bb7897dfc7773e064003ad53429a79732ee769cf6d02273570"},"id":"87b2d76f-1b70-4e4f-8b2a-5d1915c1177c","version":3} - key11: | - {"address":"bcd4042de499d14e55001ccbb24a551f3b954096","crypto":{"cipher":"aes-128-ctr","ciphertext":"e455eda6e38d246c03b930f845adfc8721ca75e9f47135cd4c18dbc3e5c5440a","cipherparams":{"iv":"0b1a0a24acc1ad25b0f170f751c2cb27"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"69f324ed0787794878bf5f84d4dbbc70dec1274cad666399edc48640605f64c8"},"mac":"f07da09c460a69f943f5639545d2b3f72c1e9789f0421ad41d3078ea3db12c96"},"id":"7ec7bb3c-c486-4785-a4fc-f8f4b2fc7764","version":3} - key12: | - {"address":"71be63f3384f5fb98995898a86b02fb2426c5788","crypto":{"cipher":"aes-128-ctr","ciphertext":"4194377a05fd3d13e0a3155dad974a003fe5f7a3b5acb35d7d97c50daa8990d4","cipherparams":{"iv":"607670778baf62b1e86394cf1980487a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d63b890ad7f4fcc857681faabe9319dffc53893966ef0810bf64c4f319b0ffc5"},"mac":"bfaf924959e65c8030ece259d52ed52d5d21bd74f1a67ae545d4bb289a479e16"},"id":"0c6af842-384f-49b6-b5b7-199a1e05486b","version":3} - key13: | - {"address":"fabb0ac9d68b0b445fb7357272ff202c5651694a","crypto":{"cipher":"aes-128-ctr","ciphertext":"6bad79e57a9b80e1b2aa7292a2f72613615a43da2796abeac071ad06a2decff6","cipherparams":{"iv":"91f24b0da7179a0e62803cb2cba6bb49"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"153a063a0dcf7abe7fd730ba908d00856783f0814e1b684a6a08b519d5dbadda"},"mac":"b007d01324b2d05c9a0333e4fbf826681ee2f5ddb4007c6fab20ef923481ba8f"},"id":"fb09dfff-ac3b-46c5-8d88-f4549007977b","version":3} - key14: | - {"address":"1cbd3b2770909d4e10f157cabc84c7264073c9ec","crypto":{"cipher":"aes-128-ctr","ciphertext":"3a7b9d84afb8d6241974cf35a34cbce077aae04f4c0aea1730167c9d8266bd74","cipherparams":{"iv":"329b510bce6e63a53827a0c307c041b5"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"6648c7f4ed24d1134dcf5983a5ca4bc5ae16787f0813530d5ae4c9c61dd3623f"},"mac":"65098dcdaabfb404539aeeea20f41b24886f9d3a55b9a841e2769692e19b75e8"},"id":"2053c6ce-da95-44d2-af1f-1939319aaa45","version":3} - key15: | - {"address":"df3e18d64bc6a983f673ab319ccae4f1a57c7097","crypto":{"cipher":"aes-128-ctr","ciphertext":"ab5802ecd849b0931d822a59597f9b59277526c13dcf792d1f6771ff0a63c902","cipherparams":{"iv":"c10e50c9f7359d281bfddd90ffeee967"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"97848515d8c93caab641882fea9b1428de32a8cf006d998893d01c03a0c2f48c"},"mac":"a2c5fbf7f78e498ee4a8bb242b4a03d4fb77f4135218a5af1d4b99ebd8991c9d"},"id":"83fa51c4-48f7-4d1d-b368-c9bd9d8841ee","version":3} - key16: | - {"address":"cd3b766ccdd6ae721141f452c550ca635964ce71","crypto":{"cipher":"aes-128-ctr","ciphertext":"05f18b7afa63c3748f3c5c99c8f036df1295f7660380e3c6a3fc6252f40566aa","cipherparams":{"iv":"3346ffa57c1b04f678d373cce4e4383a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c21f4d22a2324039b3f7cd6dbfa757bc489fa676d700b3ee88d0e3b334698720"},"mac":"7762c08bb673333946e87c33108349d10850c559104e863c5b0826cd6e64df78"},"id":"67b3c79c-d696-4e1b-a381-d67553bc674b","version":3} - key17: | - {"address":"2546bcd3c84621e976d8185a91a922ae77ecec30","crypto":{"cipher":"aes-128-ctr","ciphertext":"accd54a6b3969a4aed305baa0cd35ce4b54dcc92d866ff8b3d23536609a282eb","cipherparams":{"iv":"93be3f925ddea06113b3dcac650e9b6b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"092f7823a668981e14f715ae7352fa176461cddd94267f9dd6f23f9fe663ba9a"},"mac":"bb4792148205a4f0d8dfc5cd04725d0a4785a6d7e6ca0c208ffc0b005947821b"},"id":"368b24f6-6d1b-4fd5-a506-d73b5bb4aac8","version":3} - key18: | - {"address":"bda5747bfd65f08deb54cb465eb87d40e51b197e","crypto":{"cipher":"aes-128-ctr","ciphertext":"8bc3bf720dce7d010617edaf6db4ed35701c13ff67cd9dce742de77b4b4b3df0","cipherparams":{"iv":"50075ca52dd388719b27e3029f01a484"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"8e365100caeda20cc0a13c28517d62fc41d5cae1da4dae3fef51daf4b323da81"},"mac":"5ed7ad5aca897fd03ebeb08a7fcfa38d2eadc240b6eb6ad53f7c06c6ee9085de"},"id":"8b627671-46e5-4081-a25a-c928b135a87e","version":3} - key19: | - {"address":"dd2fd4581271e230360230f9337d5c0430bf44c0","crypto":{"cipher":"aes-128-ctr","ciphertext":"39c1bbd9c070465fb7828be95b3b0978482aab16b8b1f11db0022321bcaa9172","cipherparams":{"iv":"35bd60a818c50e65fee00031f0a33d8e"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"eecd539685126cfc1f444070d7528c5f570d71c48994118af8c50c316ef72a99"},"mac":"93224b4767a57a8cd394c37087f0dfc9393b381f09c45c5abc55cec5d719181f"},"id":"321978cb-f1bf-4790-8a29-5e5878f8dbb9","version":3} - key20: | - {"address":"8626f6940e2eb28930efb4cef49b2d1f2c9c1199","crypto":{"cipher":"aes-128-ctr","ciphertext":"8a3f1dc7b110c5ce59007f6e55fd7f055b41e518b1f34e93b4185aa44d8a1f92","cipherparams":{"iv":"02fe1b25039baf5abbdd448b932b2ab5"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"a75a6b250851f76f36132aad3ca944493b7d20a07bd4c7b1d8574596a240b35f"},"mac":"679d96ef17c9ac86960e61ced85eb551ba1895cfde2c8bb099e38dc1251a44f0"},"id":"5d3a08df-78f3-43e8-8978-75652502c962","version":3} - password.txt: | - init.sh: | - #!/bin/bash - if [ ! -d /chain/chain-data/keystore ]; then - echo "/chain/chain-data/keystore not found, running 'geth init'..." - geth init --datadir /chain/chain-data/ /chain/genesis.json - echo "...done!" - cp /chain/config/key* /chain/chain-data/keystore - fi - - cd /chain/chain-data && geth "$@" - genesis.json: | - { - "config": { - "chainId": {{ $cfg.networkId }}, - "homesteadBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "eip160Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "muirGlacierBlock": 0, - "berlinBlock": 0, - "londonBlock": 0, - "clique": { - "period": 2, - "epoch": 30000 - } - }, - "nonce": "0x0000000000000042", - "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "1", - "coinbase": "0x3333333333333333333333333333333333333333", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "8000000000", - "alloc": { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { - "balance": "20000000000000000000000" - }, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": { - "balance": "20000000000000000000000" - }, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": { - "balance": "20000000000000000000000" - }, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": { - "balance": "20000000000000000000000" - }, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": { - "balance": "20000000000000000000000" - }, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": { - "balance": "20000000000000000000000" - }, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": { - "balance": "20000000000000000000000" - }, - "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955": { - "balance": "20000000000000000000000" - }, - "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f": { - "balance": "20000000000000000000000" - }, - "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720": { - "balance": "20000000000000000000000" - }, - "0xBcd4042DE499D14e55001CcbB24a551F3b954096": { - "balance": "20000000000000000000000" - }, - "0x71bE63f3384f5fb98995898A86B02Fb2426c5788": { - "balance": "20000000000000000000000" - }, - "0xFABB0ac9d68B0B445fB7357272Ff202C5651694a": { - "balance": "20000000000000000000000" - }, - "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec": { - "balance": "20000000000000000000000" - }, - "0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097": { - "balance": "20000000000000000000000" - }, - "0xcd3B766CCDd6AE721141F452C550Ca635964ce71": { - "balance": "20000000000000000000000" - }, - "0x2546BcD3c84621e976D8185a91A922aE77ECEc30": { - "balance": "20000000000000000000000" - }, - "0xbDA5747bFD65F08deb54cb465eB87D40e51B197E": { - "balance": "20000000000000000000000" - }, - "0xdD2FD4581271e230360230F9337D5c0430Bf44C0": { - "balance": "20000000000000000000000" - }, - "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199": { - "balance": "20000000000000000000000" - } - } - } ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-deployment.yaml b/charts/chainlink-cluster/templates/geth-deployment.yaml deleted file mode 100644 index 6eccdbd20b4..00000000000 --- a/charts/chainlink-cluster/templates/geth-deployment.yaml +++ /dev/null @@ -1,130 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- range $cfg := .Values.geth.chains }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: geth-{{ $cfg.networkId }} - labels: - app: geth - release: {{ $.Release.Name }} - instance: geth-{{ $cfg.networkId }} -spec: - selector: - matchLabels: - app: geth - release: {{ $.Release.Name }} - instance: geth-{{ $cfg.networkId }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: "blockchain" - havoc-network-group: "blockchain" - template: - metadata: - labels: - app: geth - instance: geth-{{ $cfg.networkId }} - release: {{ $.Release.Name }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: "blockchain" - havoc-network-group: "blockchain" - annotations: - {{- range $key, $value := $.Values.podAnnotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - spec: - volumes: - - name: configmap-volume - configMap: - name: geth-{{ $cfg.networkId }}-cm - - name: devchain-volume - emptyDir: {} - securityContext: - {{- toYaml $.Values.geth.podSecurityContext | nindent 8 }} - containers: - - name: geth-network - securityContext: - {{- toYaml $.Values.geth.securityContext | nindent 12 }} - image: "{{ default "ethereum/client-go" $.Values.geth.image }}:{{ default "stable" $.Values.geth.version }}" - command: [ "sh", "/chain/init.sh" ] - volumeMounts: - - name: devchain-volume - mountPath: /chain/chain-data - - name : configmap-volume - mountPath: /chain/genesis.json - subPath: genesis.json - - name : configmap-volume - mountPath: /chain/init.sh - subPath: init.sh - - name: configmap-volume - mountPath: /chain/config - args: - - '--password' - - '/chain/config/password.txt' - - '--datadir' - - '/chain/chain-data/' - - '--unlock' - - '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266' - - '--mine' - - '--miner.etherbase' - - '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266' - - '--ipcdisable' - - '--http.api' - - 'admin,debug,clique,eth,miner,net,personal,txpool,web3' - - '--http' - - '--http.vhosts' - - '*' - - '--http.addr' - - '0.0.0.0' - - '--http.port=8544' - - '--ws' - - '--ws.origins' - - '*' - - '--ws.addr' - - '0.0.0.0' - - '--ws.port=8546' - - '--graphql' - - '-graphql.corsdomain' - - '*' - - '--allow-insecure-unlock' - - '--rpc.allow-unprotected-txs' - - '--http.corsdomain' - - '*' - - '--vmdebug' - - '--networkid={{ $cfg.networkId }}' - - '--rpc.txfeecap' - - '0' - - '--dev.period' - - '{{ $.Values.geth.blocktime }}' - - '--miner.gasprice' - - '10000000000' - ports: - - name: http-rpc - containerPort: 8544 - - name: ws-rpc - containerPort: 8546 - {{ if (hasKey $.Values.geth "resources") }} - resources: - requests: - memory: {{ default "1024Mi" $.Values.geth.resources.requests.memory }} - cpu: {{ default "1000m" $.Values.geth.resources.requests.cpu }} - limits: - memory: {{ default "1024Mi" $.Values.geth.resources.limits.memory }} - cpu: {{ default "1000m" $.Values.geth.resources.limits.cpu }} - {{ else }} - {{ end }} -{{- with $.Values.nodeSelector }} - nodeSelector: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.affinity }} - affinity: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} -{{- end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-networkpolicy.yaml b/charts/chainlink-cluster/templates/geth-networkpolicy.yaml deleted file mode 100644 index 2a37a92aaaa..00000000000 --- a/charts/chainlink-cluster/templates/geth-networkpolicy.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- if .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-geth -spec: - podSelector: - matchLabels: - app: geth - policyTypes: - - Ingress - ingress: - - from: - # Allow http and websocket connections from the node pods. - - podSelector: - matchLabels: - app: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 8544 - - protocol: TCP - port: 8546 -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-service.yaml b/charts/chainlink-cluster/templates/geth-service.yaml deleted file mode 100644 index 63a86a3d1d7..00000000000 --- a/charts/chainlink-cluster/templates/geth-service.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- range $cfg := .Values.geth.chains }} -apiVersion: v1 -kind: Service -metadata: - name: geth-{{ $cfg.networkId }} -spec: - selector: - instance: geth-{{ $cfg.networkId }} - release: {{ $.Release.Name }} - ports: - - name: ws-rpc - port: {{ default "8546" $.Values.geth.wsrpc_port}} - targetPort: ws-rpc - - name: http-rpc - port: {{ default "8544" $.Values.geth.httprpc_port}} - targetPort: http-rpc - type: ClusterIP ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/ingress.yaml b/charts/chainlink-cluster/templates/ingress.yaml deleted file mode 100644 index 9573ac54eb9..00000000000 --- a/charts/chainlink-cluster/templates/ingress.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.ingress.enabled -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ $.Release.Name }} - labels: - app: {{ $.Release.Name }} - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} - annotations: - alb.ingress.kubernetes.io/backend-protocol: HTTP - alb.ingress.kubernetes.io/certificate-arn: {{ $.Values.ingress.annotation_certificate_arn | quote }} - alb.ingress.kubernetes.io/group.name: {{ $.Values.ingress.annotation_group_name | quote }} - alb.ingress.kubernetes.io/scheme: internal - alb.ingress.kubernetes.io/target-type: ip - external-dns.alpha.kubernetes.io/ttl: "120" - {{- if .Values.ingress.extra_annotations }} - {{- range $key, $value := .Values.ingress.extra_annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- end }} -spec: - {{- with .Values.ingress.ingressClassName }} - ingressClassName: {{ . }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host }} - http: - paths: - {{- range .http.paths }} - - path: "/*" - pathType: ImplementationSpecific - backend: - service: - name: {{ .backend.service.name }} - port: - number: {{ .backend.service.port.number }} - {{- end }} - {{- end }} -{{- end -}} diff --git a/charts/chainlink-cluster/templates/mockserver-networkpolicy.yaml b/charts/chainlink-cluster/templates/mockserver-networkpolicy.yaml deleted file mode 100644 index 0fa48dcfc41..00000000000 --- a/charts/chainlink-cluster/templates/mockserver-networkpolicy.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.mockserver.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-mockserver -spec: - podSelector: - matchLabels: - app: mockserver - policyTypes: - - Ingress - ingress: - - from: - # Allow http traffic from the node pods. - - podSelector: - matchLabels: - app: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 1080 -{{- end }} diff --git a/charts/chainlink-cluster/templates/networkpolicy-default.yaml b/charts/chainlink-cluster/templates/networkpolicy-default.yaml deleted file mode 100644 index 10927c26eb6..00000000000 --- a/charts/chainlink-cluster/templates/networkpolicy-default.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if and .Values.mockserver.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: default -spec: - podSelector: - matchLabels: {} - policyTypes: - - Ingress - - Egress - ingress: - {{- if and .Values.networkPolicyDefault.ingress.allowCustomCidrs (not (empty .Values.networkPolicyDefault.ingress.customCidrs)) }} - # Using a comma separated list to make it easy to pass in with: - # `helm template ... --set networkPolicyDefault.ingress.customCidrs=...` - {{- $cidrs := splitList "," .Values.networkPolicyDefault.ingress.customCidrs }} - - from: - {{- range $cidr := $cidrs }} - - ipBlock: - cidr: {{ $cidr | quote }} - {{- end }} - {{- else }} - # Deny all ingress if no rules are specified. Rules can still be specified in other templates. - - {} - {{- end }} - egress: - - to: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: "{{ $.Release.Namespace }}" - - to: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: kube-system - podSelector: - matchLabels: - k8s-app: kube-dns - ports: - - protocol: TCP - port: 53 - - protocol: UDP - port: 53 -{{- end }} \ No newline at end of file diff --git a/charts/chainlink-cluster/templates/tests/test-connection.yaml b/charts/chainlink-cluster/templates/tests/test-connection.yaml deleted file mode 100644 index b03b6a570c7..00000000000 --- a/charts/chainlink-cluster/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: cl-nodes-connection-test - annotations: - "helm.sh/hook": test -spec: - containers: - {{- range $cfg := .Values.chainlink.nodes }} - - name: curl-{{ $cfg.name }} - image: radial/busyboxplus:curl - command: ['curl'] - args: [ '{{ $.Release.Name }}-{{ $cfg.name }}:{{ $.Values.chainlink.web_port }}' ] - {{- end }} - restartPolicy: Never \ No newline at end of file diff --git a/charts/chainlink-cluster/values.yaml b/charts/chainlink-cluster/values.yaml deleted file mode 100644 index d6315f488fd..00000000000 --- a/charts/chainlink-cluster/values.yaml +++ /dev/null @@ -1,439 +0,0 @@ -# override resources for keys "chainlink", "db", or "geth" if needed -# resources: -# requests: -# cpu: 350m -# memory: 1024Mi -# limits: -# cpu: 350m -# memory: 1024Mi -# images can be overriden for the same keys: -# image: ethereum/client-go -# version: stable -chainlink: - enabled: true - global: - # `toml` is initially set to null. Uncomment and modify the following example as needed. - # Example configuration parameters for all Chainlink nodes. Can be overridden by individual node configurations and via `overridesToml`. - # toml: |- - # [Log] - # Level = 'info' - # [WebServer] - # HTTPPort = 6688 - toml: null - # `overridesToml` is initially set to null. Uncomment and modify the following example as needed. - # Example configuration parameters that override the main configuration. - # overridesToml: |- - # [Log] - # Level = 'debug' - # [WebServer] - # HTTPPort = 6690 - overridesToml: null - podSecurityContext: - fsGroup: 14933 - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 14933 - runAsGroup: 14933 - web_port: 6688 - p2p_port: 6690 - nodes: - - name: node-1 - image: "public.ecr.aws/chainlink/chainlink:latest" - # default resources are 300m/1Gi - # first node need more resources to build faster inside container - # at least 2Gi of memory is required otherwise build will fail (OOM) - resources: - requests: - cpu: 2000m - memory: 2048Mi - limits: - cpu: 2000m - memory: 2048Mi - # override default config per node - # for example, use OCRv2 P2P setup, the whole config - # toml: | - # RootDir = './clroot' - # [Log] - # JSONConsole = true - # Level = 'debug' - # [WebServer] - # AllowOrigins = '*' - # SecureCookies = false - # SessionTimeout = '999h0m0s' - # [OCR2] - # Enabled = true - # [P2P] - # [P2P.V2] - # Enabled = false - # AnnounceAddresses = [] - # DefaultBootstrappers = [] - # DeltaDial = '15s' - # DeltaReconcile = '1m0s' - # ListenAddresses = [] - # [[EVM]] - # ChainID = '1337' - # MinContractPayment = '0' - # [[EVM.Nodes]] - # Name = 'node-0' - # WSURL = 'ws://geth:8546' - # HTTPURL = 'http://geth:8544' - # [WebServer.TLS] - # HTTPSPort = 0 - # or use overridesToml to override some part of configuration - # overridesToml: | - - name: node-2 - - name: node-3 - - name: node-4 - - name: node-5 - - name: node-6 - -# each CL node have a dedicated PostgreSQL 11.15 -# use StatefulSet by setting: -# -# stateful: true -# capacity 10Gi -# -# if you are running long tests -db: - enabled: true - podSecurityContext: - fsGroup: 999 - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 999 - runAsGroup: 999 - stateful: false - image: "postgres:15.6" - resources: - requests: - cpu: 1 - memory: 1024Mi - limits: - cpu: 1 - memory: 1024Mi -# default cluster shipped with latest Geth ( dev mode by default ) -geth: - enabled: true - podSecurityContext: - fsGroup: 999 - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 999 - runAsGroup: 999 - version: v1.12.0 - wsRpcPort: 8546 - httpRpcPort: 8544 - blocktime: 1 - chains: - - networkId: 1337 - # use to inject custom configuration for each chain, e.g. GasEstimator - # - customEVMConfigToml: | - # [EVM.GasEstimator] - # PriceMax = '200 gwei' - # LimitDefault = 6000000 - # FeeCapDefault = '200 gwei' - # [EVM.GasEstimator.BlockHistory] - # BlockHistorySize = 200 - # EIP1559FeeCapBufferBlocks = 0 - - networkId: 2337 - resources: - requests: - cpu: 1 - memory: 1024Mi - limits: - cpu: 1 - memory: 1024Mi -# mockserver is https://www.mock-server.com/where/kubernetes.html -# used to stub External Adapters -mockserver: - enabled: true - releasenameOverride: mockserver - service: - type: ClusterIP - app: - runAsUser: 999 - readOnlyRootFilesystem: false - port: 1080 - resources: - requests: - cpu: 1 - memory: 1024Mi - limits: - cpu: 1 - memory: 1024Mi -opentelemetry-collector: - enabled: true - mode: deployment - image: - repository: otel/opentelemetry-collector - tag: 0.95.0 - command: - name: otelcol - extraVolumes: - - name: trace-data - emptyDir: {} - extraVolumeMounts: - - name: trace-data - mountPath: /tracing - podSecurityContext: - fsGroup: 10001 - securityContext: - runAsNonRoot: true - runAsUser: 10001 - runAsGroup: 10001 - config: - receivers: - otlp: - protocols: - grpc: - endpoint: ${env:MY_POD_IP}:4317 - http: - endpoint: ${env:MY_POD_IP}:4318 - exporters: - otlp: - endpoint: app-tempo:4317 - tls: - insecure: true - service: - telemetry: - logs: - level: "debug" - pipelines: - traces: - receivers: [otlp] - exporters: [otlp] - -tempo: - enabled: true - image: - tag: "1.7.2" - # default storage path: /var/tempo/ - securityContext: - runAsNonRoot: true - runAsUser: 10001 - runAsGroup: 10001 - tempo: - storage: - trace: - backend: local # backend configuration to use - wal: - path: /tmp/tempo/wal # where to store the wal locally - local: - path: /tmp/tempo/blocks - -grafana: - enabled: true - image: - tag: 10.4.1 - rbac: - namespaced: true - datasources: - datasources.yaml: - apiVersion: 1 - datasources: - - name: Tempo - type: tempo - access: proxy - orgId: 1 - url: http://app-tempo:3100 - basicAuth: false - isDefault: true - version: 1 - editable: false - uid: tempo - jsonData: - httpMethod: GET - serviceMap: - datasourceUid: prometheus - env: - GF_AUTH_ANONYMOUS_ENABLED: "true" - GF_AUTH_ANONYMOUS_ORG_ROLE: "Admin" - GF_AUTH_DISABLE_LOGIN_FORM: "true" - GF_FEATURE_TOGGLES_ENABLE: "traceqlEditor tempoSearch tempoServiceGraph" - -ingress: - enabled: false - annotations: {} - ingressClassName: alb - hosts: - - host: chainlink-node-1.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-1 - port: - number: 6688 - - host: chainlink-node-2.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-2 - port: - number: 6688 - - host: chainlink-node-3.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-3 - port: - number: 6688 - - host: chainlink-node-4.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-4 - port: - number: 6688 - - host: chainlink-node-5.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-5 - port: - number: 6688 - - host: chainlink-node-6.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-6 - port: - number: 6688 - - host: chainlink-geth-http.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: geth - port: - number: 8544 - - host: chainlink-geth-ws.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: geth - port: - number: 8546 - - host: chainlink-mockserver.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: mockserver - port: - number: 1080 - - host: chainlink-grafana.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: grafana - port: - number: 80 -# monitoring.coreos.com/v1 PodMonitor for each node -prometheusMonitor: true - -# deployment placement, standard helm stuff -podAnnotations: -nodeSelector: -tolerations: -affinity: - -networkPolicies: - enabled: true - customPolicies: - grafanaToTempoEgress: - podSelector: - matchLabels: - app: grafana - egress: - - to: - - podSelector: - matchLabels: - app: tempo - ports: - - protocol: TCP - port: 3100 - tempoIngressFromGrafana: - podSelector: - matchLabels: - app: tempo - ingress: - - from: - - podSelector: - matchLabels: - app: grafana - ports: - - protocol: TCP - port: 3100 - chainlinkToOtelCollectorEgress: - podSelector: - matchLabels: - app: chainlink - egress: - - to: - - podSelector: - matchLabels: - app: otel-collector - ports: - - protocol: TCP - port: 4317 - otelCollectorToTempoEgress: - podSelector: - matchLabels: - app: otel-collector - egress: - - to: - - podSelector: - matchLabels: - app: tempo - ports: - - protocol: TCP - port: 4317 - -# Configure the default network policy. -networkPolicyDefault: - ingress: - allowCustomCidrs: false - # String of comma separated CIDRs - customCidrs: null - # Example: - # customCidrs: "10.0.0.0/16,192.168.0.1/24" diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index a70f1961e36..00000000000 --- a/codecov.yml +++ /dev/null @@ -1,15 +0,0 @@ -comment: false - -coverage: - status: - project: - default: - threshold: 1% - -github_checks: - annotations: false - -ignore: - - 'contracts/' # Disabled due to solidity-coverage not reporting coverage - - 'core/internal' - - 'core/scripts' diff --git a/common/client/models.go b/common/client/models.go index 66f1e9cf88b..fd0c3915940 100644 --- a/common/client/models.go +++ b/common/client/models.go @@ -28,6 +28,35 @@ var sendTxSevereErrors = []SendTxReturnCode{Fatal, Underpriced, Unsupported, Exc // sendTxSuccessfulCodes - error codes which signal that transaction was accepted by the node var sendTxSuccessfulCodes = []SendTxReturnCode{Successful, TransactionAlreadyKnown} +func (c SendTxReturnCode) String() string { + switch c { + case Successful: + return "Successful" + case Fatal: + return "Fatal" + case Retryable: + return "Retryable" + case Underpriced: + return "Underpriced" + case Unknown: + return "Unknown" + case Unsupported: + return "Unsupported" + case TransactionAlreadyKnown: + return "TransactionAlreadyKnown" + case InsufficientFunds: + return "InsufficientFunds" + case ExceedsMaxFee: + return "ExceedsMaxFee" + case FeeOutOfValidRange: + return "FeeOutOfValidRange" + case OutOfCounters: + return "OutOfCounters" + default: + return fmt.Sprintf("SendTxReturnCode(%d)", c) + } +} + type NodeTier int const ( diff --git a/common/client/models_test.go b/common/client/models_test.go new file mode 100644 index 00000000000..2d5dc31b373 --- /dev/null +++ b/common/client/models_test.go @@ -0,0 +1,16 @@ +package client + +import ( + "strings" + "testing" +) + +func TestSendTxReturnCode_String(t *testing.T) { + // ensure all the SendTxReturnCodes have proper name + for c := 1; c < int(sendTxReturnCodeLen); c++ { + strC := SendTxReturnCode(c).String() + if strings.Contains(strC, "SendTxReturnCode(") { + t.Errorf("Expected %s to have a proper string representation", strC) + } + } +} diff --git a/common/client/multi_node.go b/common/client/multi_node.go index cc8daed599c..fa413df91aa 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -561,6 +561,13 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return n.RPC().PendingSequenceAt(ctx, addr) } +type sendTxErrors map[SendTxReturnCode][]error + +// String - returns string representation of the errors map. Required by logger to properly represent the value +func (errs sendTxErrors) String() string { + return fmt.Sprint(map[SendTxReturnCode][]error(errs)) +} + func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SendEmptyTransaction( ctx context.Context, newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt any, err error), @@ -602,7 +609,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP ctx, cancel := c.chStop.Ctx(ctx) defer cancel() requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) - errorsByCode := map[SendTxReturnCode][]error{} + errorsByCode := sendTxErrors{} var softTimeoutChan <-chan time.Time var resultsCount int loop: @@ -639,7 +646,7 @@ loop: func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) reportSendTxAnomalies(tx TX, txResults <-chan sendTxResult) { defer c.wg.Done() - resultsByCode := map[SendTxReturnCode][]error{} + resultsByCode := sendTxErrors{} // txResults eventually will be closed for txResult := range txResults { resultsByCode[txResult.ResultCode] = append(resultsByCode[txResult.ResultCode], txResult.Err) @@ -653,7 +660,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } } -func aggregateTxResults(resultsByCode map[SendTxReturnCode][]error) (txResult error, err error) { +func aggregateTxResults(resultsByCode sendTxErrors) (txResult error, err error) { severeErrors, hasSevereErrors := findFirstIn(resultsByCode, sendTxSevereErrors) successResults, hasSuccess := findFirstIn(resultsByCode, sendTxSuccessfulCodes) if hasSuccess { diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 9c09bd57d70..9f6904fcaf2 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -796,13 +796,13 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name string ExpectedTxResult string ExpectedCriticalErr string - ResultsByCode map[SendTxReturnCode][]error + ResultsByCode sendTxErrors }{ { Name: "Returns success and logs critical error on success and Fatal", ExpectedTxResult: "success", ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Successful: {errors.New("success")}, Fatal: {errors.New("fatal")}, }, @@ -811,7 +811,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Returns TransactionAlreadyKnown and logs critical error on TransactionAlreadyKnown and Fatal", ExpectedTxResult: "tx_already_known", ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ TransactionAlreadyKnown: {errors.New("tx_already_known")}, Unsupported: {errors.New("unsupported")}, }, @@ -820,7 +820,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Prefers sever error to temporary", ExpectedTxResult: "underpriced", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Retryable: {errors.New("retryable")}, Underpriced: {errors.New("underpriced")}, }, @@ -829,7 +829,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Returns temporary error", ExpectedTxResult: "retryable", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Retryable: {errors.New("retryable")}, }, }, @@ -837,7 +837,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Insufficient funds is treated as error", ExpectedTxResult: "", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Successful: {nil}, InsufficientFunds: {errors.New("insufficientFunds")}, }, @@ -846,13 +846,13 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Logs critical error on empty ResultsByCode", ExpectedTxResult: "expected at least one response on SendTransaction", ExpectedCriticalErr: "expected at least one response on SendTransaction", - ResultsByCode: map[SendTxReturnCode][]error{}, + ResultsByCode: sendTxErrors{}, }, { Name: "Zk out of counter error", ExpectedTxResult: "not enough keccak counters to continue the execution", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ OutOfCounters: {errors.New("not enough keccak counters to continue the execution")}, }, }, @@ -870,6 +870,9 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { assert.EqualError(t, txResult, testCase.ExpectedTxResult) } + logger.Sugared(logger.Test(t)).Info("Map: " + fmt.Sprint(testCase.ResultsByCode)) + logger.Sugared(logger.Test(t)).Criticalw("observed invariant violation on SendTransaction", "resultsByCode", testCase.ResultsByCode, "err", err) + if testCase.ExpectedCriticalErr == "" { assert.NoError(t, err) } else { @@ -884,5 +887,4 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { delete(codesToCover, codeToIgnore) } assert.Empty(t, codesToCover, "all of the SendTxReturnCode must be covered by this test") - } diff --git a/common/client/poller.go b/common/client/poller.go new file mode 100644 index 00000000000..b21f28fe604 --- /dev/null +++ b/common/client/poller.go @@ -0,0 +1,98 @@ +package client + +import ( + "context" + "sync" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + + "github.com/smartcontractkit/chainlink/v2/common/types" +) + +// Poller is a component that polls a function at a given interval +// and delivers the result to a channel. It is used by multinode to poll +// for new heads and implements the Subscription interface. +type Poller[T any] struct { + services.StateMachine + pollingInterval time.Duration + pollingFunc func(ctx context.Context) (T, error) + pollingTimeout time.Duration + logger logger.Logger + channel chan<- T + errCh chan error + + stopCh services.StopChan + wg sync.WaitGroup +} + +// NewPoller creates a new Poller instance +func NewPoller[ + T any, +](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, channel chan<- T, logger logger.Logger) Poller[T] { + return Poller[T]{ + pollingInterval: pollingInterval, + pollingFunc: pollingFunc, + pollingTimeout: pollingTimeout, + channel: channel, + logger: logger, + errCh: make(chan error), + stopCh: make(chan struct{}), + } +} + +var _ types.Subscription = &Poller[any]{} + +func (p *Poller[T]) Start() error { + return p.StartOnce("Poller", func() error { + p.wg.Add(1) + go p.pollingLoop() + return nil + }) +} + +// Unsubscribe cancels the sending of events to the data channel +func (p *Poller[T]) Unsubscribe() { + _ = p.StopOnce("Poller", func() error { + close(p.stopCh) + p.wg.Wait() + close(p.errCh) + return nil + }) +} + +func (p *Poller[T]) Err() <-chan error { + return p.errCh +} + +func (p *Poller[T]) pollingLoop() { + defer p.wg.Done() + + ticker := time.NewTicker(p.pollingInterval) + defer ticker.Stop() + + for { + select { + case <-p.stopCh: + return + case <-ticker.C: + // Set polling timeout + pollingCtx, cancelPolling := context.WithTimeout(context.Background(), p.pollingTimeout) + p.stopCh.CtxCancel(pollingCtx, cancelPolling) + // Execute polling function + result, err := p.pollingFunc(pollingCtx) + cancelPolling() + if err != nil { + p.logger.Warnf("polling error: %v", err) + continue + } + // Send result to channel or block if channel is full + select { + case p.channel <- result: + case <-p.stopCh: + return + } + } + } +} diff --git a/common/client/poller_test.go b/common/client/poller_test.go new file mode 100644 index 00000000000..3f11c759adb --- /dev/null +++ b/common/client/poller_test.go @@ -0,0 +1,207 @@ +package client + +import ( + "context" + "fmt" + "math/big" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" +) + +func Test_Poller(t *testing.T) { + lggr := logger.Test(t) + + t.Run("Test multiple start", func(t *testing.T) { + pollFunc := func(ctx context.Context) (Head, error) { + return nil, nil + } + + channel := make(chan Head, 1) + defer close(channel) + + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + err := poller.Start() + require.NoError(t, err) + + err = poller.Start() + require.Error(t, err) + poller.Unsubscribe() + }) + + t.Run("Test polling for heads", func(t *testing.T) { + // Mock polling function that returns a new value every time it's called + var pollNumber int + pollLock := sync.Mutex{} + pollFunc := func(ctx context.Context) (Head, error) { + pollLock.Lock() + defer pollLock.Unlock() + pollNumber++ + h := head{ + BlockNumber: int64(pollNumber), + BlockDifficulty: big.NewInt(int64(pollNumber)), + } + return h.ToMockHead(t), nil + } + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + // Create poller and start to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + require.NoError(t, poller.Start()) + defer poller.Unsubscribe() + + // Receive updates from the poller + pollCount := 0 + pollMax := 50 + for ; pollCount < pollMax; pollCount++ { + h := <-channel + assert.Equal(t, int64(pollCount+1), h.BlockNumber()) + } + }) + + t.Run("Test polling errors", func(t *testing.T) { + // Mock polling function that returns an error + var pollNumber int + pollLock := sync.Mutex{} + pollFunc := func(ctx context.Context) (Head, error) { + pollLock.Lock() + defer pollLock.Unlock() + pollNumber++ + return nil, fmt.Errorf("polling error %d", pollNumber) + } + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) + + // Create poller and subscribe to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, olggr) + require.NoError(t, poller.Start()) + defer poller.Unsubscribe() + + // Ensure that all errors were logged as expected + logsSeen := func() bool { + for pollCount := 0; pollCount < 50; pollCount++ { + numLogs := observedLogs.FilterMessage(fmt.Sprintf("polling error: polling error %d", pollCount+1)).Len() + if numLogs != 1 { + return false + } + } + return true + } + require.Eventually(t, logsSeen, time.Second, time.Millisecond) + }) + + t.Run("Test polling timeout", func(t *testing.T) { + pollFunc := func(ctx context.Context) (Head, error) { + if <-ctx.Done(); true { + return nil, ctx.Err() + } + return nil, nil + } + + // Set instant timeout + pollingTimeout := time.Duration(0) + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) + + // Create poller and subscribe to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + require.NoError(t, poller.Start()) + defer poller.Unsubscribe() + + // Ensure that timeout errors were logged as expected + logsSeen := func() bool { + return observedLogs.FilterMessage("polling error: context deadline exceeded").Len() >= 1 + } + require.Eventually(t, logsSeen, time.Second, time.Millisecond) + }) + + t.Run("Test unsubscribe during polling", func(t *testing.T) { + wait := make(chan struct{}) + pollFunc := func(ctx context.Context) (Head, error) { + close(wait) + // Block in polling function until context is cancelled + if <-ctx.Done(); true { + return nil, ctx.Err() + } + return nil, nil + } + + // Set long timeout + pollingTimeout := time.Minute + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) + + // Create poller and subscribe to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + require.NoError(t, poller.Start()) + + // Unsubscribe while blocked in polling function + <-wait + poller.Unsubscribe() + + // Ensure error was logged + logsSeen := func() bool { + return observedLogs.FilterMessage("polling error: context canceled").Len() >= 1 + } + require.Eventually(t, logsSeen, time.Second, time.Millisecond) + }) +} + +func Test_Poller_Unsubscribe(t *testing.T) { + lggr := logger.Test(t) + pollFunc := func(ctx context.Context) (Head, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + h := head{ + BlockNumber: 0, + BlockDifficulty: big.NewInt(0), + } + return h.ToMockHead(t), nil + } + } + + t.Run("Test multiple unsubscribe", func(t *testing.T) { + channel := make(chan Head, 1) + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + err := poller.Start() + require.NoError(t, err) + + <-channel + poller.Unsubscribe() + poller.Unsubscribe() + }) + + t.Run("Test unsubscribe with closed channel", func(t *testing.T) { + channel := make(chan Head, 1) + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + err := poller.Start() + require.NoError(t, err) + + <-channel + close(channel) + poller.Unsubscribe() + }) +} diff --git a/contracts/.changeset/funny-eagles-know.md b/contracts/.changeset/funny-eagles-know.md new file mode 100644 index 00000000000..46827824ad8 --- /dev/null +++ b/contracts/.changeset/funny-eagles-know.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#wip addCapability udpates diff --git a/contracts/.changeset/hot-weeks-agree.md b/contracts/.changeset/hot-weeks-agree.md new file mode 100644 index 00000000000..5bd77e9ebe5 --- /dev/null +++ b/contracts/.changeset/hot-weeks-agree.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add function to remove node operators from capability registry diff --git a/contracts/.changeset/kind-snakes-invent.md b/contracts/.changeset/kind-snakes-invent.md new file mode 100644 index 00000000000..abd00ce9c85 --- /dev/null +++ b/contracts/.changeset/kind-snakes-invent.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add getters #internal diff --git a/contracts/.changeset/new-guests-accept.md b/contracts/.changeset/new-guests-accept.md new file mode 100644 index 00000000000..080fe17b2bc --- /dev/null +++ b/contracts/.changeset/new-guests-accept.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +minor fixes #bugfix diff --git a/contracts/.changeset/poor-panthers-build.md b/contracts/.changeset/poor-panthers-build.md new file mode 100644 index 00000000000..2c21cae5d7a --- /dev/null +++ b/contracts/.changeset/poor-panthers-build.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Offchain settlement fix #bugfix diff --git a/contracts/.changeset/shiny-dragons-sparkle.md b/contracts/.changeset/shiny-dragons-sparkle.md new file mode 100644 index 00000000000..7657b5f1446 --- /dev/null +++ b/contracts/.changeset/shiny-dragons-sparkle.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +use safe lib for approve #bugfix diff --git a/contracts/.changeset/tender-jokes-do.md b/contracts/.changeset/tender-jokes-do.md new file mode 100644 index 00000000000..5500fe0ca00 --- /dev/null +++ b/contracts/.changeset/tender-jokes-do.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Implement function to add node operators to the capability registry' diff --git a/contracts/CHANGELOG.md b/contracts/CHANGELOG.md index 667a5ad2529..3139312e325 100644 --- a/contracts/CHANGELOG.md +++ b/contracts/CHANGELOG.md @@ -1,6 +1,6 @@ -# @chainlink/contracts CHANGELOG.md +# @chainlink/contracts -## 1.1.0 +## 1.1.0 - 2024-04-23 ### Minor Changes diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 38547ce3a57..4ec8057b975 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -73,6 +73,18 @@ wrappers-all: pnpmdep mockery abigen ## Recompiles solidity contracts and their # go_generate contains a call to compile all contracts before generating wrappers go generate ../core/gethwrappers/go_generate.go +# Custom wrapper generation for OCR2VRF as their contracts do not exist in this repo +.PHONY: go-solidity-wrappers-ocr2vrf +go-solidity-wrappers-ocr2vrf: pnpmdep abigen ## Recompiles OCR2VRF solidity contracts and their go wrappers. + ./scripts/native_solc_compile_all_ocr2vrf + # replace the go:generate_disabled directive with the regular go:generate directive + sed -i '' 's/go:generate_disabled/go:generate/g' ../core/gethwrappers/ocr2vrf/go_generate.go + go generate ../core/gethwrappers/ocr2vrf + go generate ../core/internal/mocks + # put the go:generate_disabled directive back + sed -i '' 's/go:generate/go:generate_disabled/g' ../core/gethwrappers/ocr2vrf/go_generate.go + + help: @echo "" @echo " .__ .__ .__ .__ __" diff --git a/contracts/README.md b/contracts/README.md index 8df69057229..26b0a823298 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -50,6 +50,22 @@ contribution information. Thank you! +### Changesets + +We use [changesets](https://github.com/changesets/changesets) to manage versioning the contracts. + +Every PR that modifies any configuration or code, should most likely accompanied by a changeset file. + +To install `changesets`: + 1. Install `pnpm` if it is not already installed - [docs](https://pnpm.io/installation). + 2. Run `pnpm install`. + +Either after or before you create a commit, run the `pnpm changeset` command in the `contracts` directory to create an accompanying changeset entry which will reflect on the CHANGELOG for the next release. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), + +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + ## License [MIT](https://choosealicense.com/licenses/mit/) diff --git a/contracts/scripts/native_solc_compile_all_ocr2vrf b/contracts/scripts/native_solc_compile_all_ocr2vrf new file mode 100755 index 00000000000..755edd34f56 --- /dev/null +++ b/contracts/scripts/native_solc_compile_all_ocr2vrf @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -e + +echo " ┌──────────────────────────────────────────────┐" +echo " │ Compiling OCR2 VRF contracts... │" +echo " └──────────────────────────────────────────────┘" + +SOLC_VERSION="0.8.19" +OPTIMIZE_RUNS=1000000 +# The VRF contracts are not contained in the `chainlink` repository. +# Change me. +FOLDER="ocr2vrf-origin" + +echo "Compiling OCR2VRF contracts..." + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1; cd ../../ && pwd -P )" +python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt + +solc-select install $SOLC_VERSION +solc-select use $SOLC_VERSION +export SOLC_VERSION=$SOLC_VERSION + + +compileContract () { + local contract + contract=$(basename "$1" ".sol") + + solc --overwrite --optimize --optimize-runs "$2" --metadata-hash none \ + -o "$ROOT"/contracts/solc/v0.8.19/"$contract" \ + --abi --bin \ + --allow-paths "$ROOT"/../$FOLDER/contracts \ + "$ROOT"/"$1" +} + +# OCR2VRF +compileContract ../$FOLDER/contracts/DKG.sol $OPTIMIZE_RUNS +compileContract ../$FOLDER/contracts/VRFBeacon.sol $OPTIMIZE_RUNS +compileContract ../$FOLDER/contracts/VRFCoordinator.sol 1 +compileContract ../$FOLDER/contracts/test/TestBeaconVRFConsumer.sol $OPTIMIZE_RUNS +compileContract ../$FOLDER/contracts/test/LoadTestBeaconVRFConsumer.sol $OPTIMIZE_RUNS diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol index 90fdd82bfe7..c0952963366 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +++ b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -1,4 +1,4 @@ -// abi-checksum: 0x8860e73056784b47ec03fe67533e66ebf1a6d8e6e708c8046a71ecbe3b9334d9 +// abi-checksum: 0x2cc33080c864676d572ad7ae658ea4a4621b3fd4c4664d84f9945b2324348434 // SPDX-License-Identifier: MIT // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! pragma solidity ^0.8.4; @@ -229,6 +229,12 @@ interface IAutomationRegistryMaster2_3 { function getAllowedReadOnlyAddress() external view returns (address); function getAutomationForwarderLogic() external view returns (address); function getBalance(uint256 id) external view returns (uint96 balance); + function getBillingConfig( + address billingToken + ) external view returns (AutomationRegistryBase2_3.BillingConfig memory); + function getBillingOverrides( + uint256 upkeepID + ) external view returns (AutomationRegistryBase2_3.BillingOverrides memory); function getBillingToken(uint256 upkeepID) external view returns (address); function getBillingTokenConfig(address token) external view returns (AutomationRegistryBase2_3.BillingConfig memory); function getBillingTokens() external view returns (address[] memory); @@ -276,6 +282,7 @@ interface IAutomationRegistryMaster2_3 { function getTransmitterInfo( address query ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + function getTransmittersWithPayees() external view returns (AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory); function getTriggerType(uint256 upkeepId) external pure returns (uint8); function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); @@ -355,6 +362,11 @@ interface AutomationRegistryBase2_3 { uint32 maxPerformDataSize; uint32 maxRevertDataSize; } + + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } } interface IAutomationV21PlusCommon { @@ -405,5 +417,5 @@ interface IAutomationV21PlusCommon { // THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: /* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] */ diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 19e1cdc7460..03138696436 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -703,6 +703,23 @@ contract SetConfig is SetUp { ); } + function testSetConfigOnTransmittersAndPayees() public { + AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory transmitterPayeeInfos = registry + .getTransmittersWithPayees(); + assertEq(transmitterPayeeInfos.length, TRANSMITTERS.length); + + for (uint256 i = 0; i < transmitterPayeeInfos.length; i++) { + address transmitterAddress = transmitterPayeeInfos[i].transmitterAddress; + address payeeAddress = transmitterPayeeInfos[i].payeeAddress; + + address expectedTransmitter = TRANSMITTERS[i]; + address expectedPayee = PAYEES[i]; + + assertEq(transmitterAddress, expectedTransmitter); + assertEq(payeeAddress, expectedPayee); + } + } + function testSetConfigWithNewTransmittersSuccess() public { registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); @@ -923,6 +940,9 @@ contract NOPsSettlement is SetUp { assertEq(i, index); assertEq(0, balance); } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); } function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { @@ -1018,6 +1038,9 @@ contract NOPsSettlement is SetUp { assertEq(i, index); assertEq(0, balance); } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); } function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol index ab9d7ae0b20..8d4bf17ce91 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol @@ -81,7 +81,7 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC } /** * @member upkeepContract address to perform upkeep on - * @member amount quantity of LINK upkeep is funded with (specified in wei) + * @member amount quantity of billing token upkeep is funded with (specified in the billing token's decimals) * @member adminAddress address to cancel upkeep and withdraw remaining funds * @member gasLimit amount of gas to provide the target contract when performing upkeep * @member triggerType the type of trigger for the upkeep @@ -204,19 +204,17 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC /** * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event * @param requestParams struct of all possible registration parameters - * @param hash the committment of the registration request */ - function approve(RegistrationParams calldata requestParams, bytes32 hash) external onlyOwner { + function approve(RegistrationParams calldata requestParams) external onlyOwner { + bytes32 hash = keccak256(abi.encode(requestParams)); + PendingRequest memory request = s_pendingRequests[hash]; if (request.admin == address(0)) { revert RequestNotFound(); } - bytes32 expectedHash = keccak256(abi.encode(requestParams)); - if (hash != expectedHash) { - revert HashMismatch(); - } + delete s_pendingRequests[hash]; - _approve(requestParams, expectedHash); + _approve(requestParams, hash); } /** @@ -393,6 +391,8 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC /** * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event + * @dev safeApprove is deprecated and removed from the latest (v5) OZ release, Use safeIncreaseAllowance when we upgrade OZ (we are on v4.8) + * @dev we stick to the safeApprove because of the older version (v4.8) of safeIncreaseAllowance can't handle USDT correctly, but newer version can */ function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { IAutomationRegistryMaster2_3 registry = s_registry; @@ -406,18 +406,17 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC params.triggerConfig, params.offchainConfig ); - bool success; + if (address(params.billingToken) == address(i_LINK)) { - success = i_LINK.transferAndCall(address(registry), params.amount, abi.encode(upkeepId)); - } else { - success = params.billingToken.approve(address(registry), params.amount); - if (success) { - registry.addFunds(upkeepId, params.amount); + bool success = i_LINK.transferAndCall(address(registry), params.amount, abi.encode(upkeepId)); + if (!success) { + revert TransferFailed(address(registry)); } + } else { + params.billingToken.safeApprove(address(registry), params.amount); + registry.addFunds(upkeepId, params.amount); } - if (!success) { - revert TransferFailed(address(registry)); - } + emit RegistrationApproved(hash, params.name, upkeepId); return upkeepId; } diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol index 93d3376a4f6..318b382ab32 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol @@ -207,13 +207,13 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain report.upkeepIds[i], upkeepTransmitInfo[i].upkeep ); - transmitVars.totalPremium += receipt.premiumJuels; - transmitVars.totalReimbursement += receipt.gasReimbursementJuels; + transmitVars.totalPremium += receipt.premiumInJuels; + transmitVars.totalReimbursement += receipt.gasReimbursementInJuels; emit UpkeepPerformed( report.upkeepIds[i], upkeepTransmitInfo[i].performSuccess, - receipt.gasReimbursementJuels + receipt.premiumJuels, // TODO - this is currently the LINK amount, but may change to billing token + receipt.gasReimbursementInJuels + receipt.premiumInJuels, // TODO - this is currently the LINK amount, but may change to billing token upkeepTransmitInfo[i].gasUsed, gasOverhead, report.triggers[i] @@ -320,6 +320,10 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain chainModule: onchainConfig.chainModule }); + uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; + uint32 newLatestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); + uint32 newConfigCount = s_storage.configCount + 1; + s_storage = Storage({ checkGasLimit: onchainConfig.checkGasLimit, maxPerformGas: onchainConfig.maxPerformGas, @@ -330,17 +334,13 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, financeAdmin: onchainConfig.financeAdmin, nonce: s_storage.nonce, - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber + configCount: newConfigCount, + latestConfigBlockNumber: newLatestConfigBlockNumber }); s_fallbackGasPrice = onchainConfig.fallbackGasPrice; s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; s_fallbackNativePrice = onchainConfig.fallbackNativePrice; - uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; - s_storage.latestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); - s_storage.configCount += 1; - bytes memory onchainConfigBytes = abi.encode(onchainConfig); s_latestConfigDigest = _configDigestFromConfigData( diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol index 275b25b28d0..cb90bddf1f9 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol @@ -41,7 +41,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint8 internal constant UPKEEP_VERSION_BASE = 4; // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation - // These values are calibrated using hardhat tests which simulates various cases and verifies that + // These values are calibrated using hardhat tests which simulate various cases and verify that // the variables result in accurate estimation uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 93_000; // Fixed gas overhead for conditional upkeeps uint256 internal constant REGISTRY_LOG_OVERHEAD = 118_000; // Fixed gas overhead for log upkeeps @@ -331,7 +331,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { * @member index of oracle in s_signersList/s_transmittersList * @member balance a node's balance in LINK * @member lastCollected the total balance at which the node last withdrew - @ @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK + * @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK */ struct Transmitter { bool active; @@ -340,6 +340,11 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint96 lastCollected; } + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } + struct Signer { bool active; // Index of oracle in s_signersList/s_transmittersList @@ -428,16 +433,16 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { /** * @notice struct containing receipt information about a payment or cost estimation - * @member gasCharge the amount to charge a user for gas spent using the billing token's native decimals - * @member premium the premium charged to the user, shared between all nodes, using the billing token's native decimals - * @member gasReimbursementJuels the amount to reimburse a node for gas spent - * @member premiumJuels the premium paid to NOPs, shared between all nodes + * @member gasChargeInBillingToken the amount to charge a user for gas spent using the billing token's native decimals + * @member premiumInBillingToken the premium charged to the user, shared between all nodes, using the billing token's native decimals + * @member gasReimbursementInJuels the amount to reimburse a node for gas spent + * @member premiumInJuels the premium paid to NOPs, shared between all nodes */ struct PaymentReceipt { - uint96 gasCharge; - uint96 premium; - uint96 gasReimbursementJuels; - uint96 premiumJuels; + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; } event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); @@ -678,12 +683,12 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint256 gasPaymentHexaicosaUSD = (gasWei * (paymentParams.gasLimit + paymentParams.gasOverhead) + paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed - // gasCharge is scaled by the billing token's decimals - receipt.gasCharge = SafeCast.toUint96( + // gasChargeInBillingToken is scaled by the billing token's decimals + receipt.gasChargeInBillingToken = SafeCast.toUint96( (gasPaymentHexaicosaUSD * numeratorScalingFactor) / (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) ); - receipt.gasReimbursementJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); + receipt.gasReimbursementInJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); // premium calculation uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD @@ -691,11 +696,11 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { paymentParams.billingTokenParams.gasFeePPB * paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; // premium is scaled by the billing token's decimals - receipt.premium = SafeCast.toUint96( + receipt.premiumInBillingToken = SafeCast.toUint96( (premiumHexaicosaUSD * numeratorScalingFactor) / (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) ); - receipt.premiumJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); + receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); return receipt; } @@ -759,7 +764,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { }) ); - return receipt.gasCharge + receipt.premium; + return receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; } /** @@ -997,22 +1002,23 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { // balance is in the token's native decimals uint96 balance = upkeep.balance; // payment is in the token's native decimals - uint96 payment = receipt.gasCharge + receipt.premium; + uint96 payment = receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user // can't cover the amount owed - if (balance < receipt.gasCharge) { + if (balance < receipt.gasChargeInBillingToken) { // if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON payment = balance; - receipt.gasReimbursementJuels = SafeCast.toUint96( + receipt.gasReimbursementInJuels = SafeCast.toUint96( (balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD ); - receipt.premiumJuels = 0; + receipt.premiumInJuels = 0; } else if (balance < payment) { // if the user can cover the gas fee, but not the premium, then reduce the premium payment = balance; - receipt.premiumJuels = SafeCast.toUint96( - ((balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD) - receipt.gasReimbursementJuels + receipt.premiumInJuels = SafeCast.toUint96( + ((balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD) - + receipt.gasReimbursementInJuels ); } @@ -1115,13 +1121,12 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { * @notice updates the signers and transmitters lists */ function _updateTransmitters(address[] memory signers, address[] memory transmitters) internal { + uint96 transmittersListLength = uint96(s_transmittersList.length); + uint96 totalPremium = s_hotVars.totalPremium; + // move all pooled payments out of the pool to each transmitter's balance for (uint256 i = 0; i < s_transmittersList.length; i++) { - _updateTransmitterBalanceFromPool( - s_transmittersList[i], - s_hotVars.totalPremium, - uint96(s_transmittersList.length) - ); + _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, transmittersListLength); } // remove any old signer/transmitter addresses diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol index 99fc97ce5ce..70ac2c6a38c 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol @@ -198,6 +198,7 @@ contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable { delete s_upkeepOffchainConfig[id]; // nullify existing proposed admin change if an upkeep is being migrated delete s_proposedAdmin[id]; + delete s_upkeepAdmin[id]; s_upkeepIDs.remove(id); emit UpkeepMigrated(id, upkeep.balance, destination); } diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol index 546c85454f7..d4565615ad1 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol @@ -161,30 +161,38 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { _onlyFinanceAdminAllowed(); if (s_payoutMode == PayoutMode.ON_CHAIN) revert MustSettleOnchain(); + uint96 totalPremium = s_hotVars.totalPremium; uint256 activeTransmittersLength = s_transmittersList.length; uint256 deactivatedTransmittersLength = s_deactivatedTransmitters.length(); uint256 length = activeTransmittersLength + deactivatedTransmittersLength; uint256[] memory payments = new uint256[](length); address[] memory payees = new address[](length); + for (uint256 i = 0; i < activeTransmittersLength; i++) { address transmitterAddr = s_transmittersList[i]; uint96 balance = _updateTransmitterBalanceFromPool( transmitterAddr, - s_hotVars.totalPremium, + totalPremium, uint96(activeTransmittersLength) ); + payments[i] = balance; payees[i] = s_transmitterPayees[transmitterAddr]; s_transmitters[transmitterAddr].balance = 0; } + for (uint256 i = 0; i < deactivatedTransmittersLength; i++) { address deactivatedAddr = s_deactivatedTransmitters.at(i); Transmitter memory transmitter = s_transmitters[deactivatedAddr]; + payees[i + activeTransmittersLength] = s_transmitterPayees[deactivatedAddr]; payments[i + activeTransmittersLength] = transmitter.balance; s_transmitters[deactivatedAddr].balance = 0; } + // reserve amount of LINK is reset to 0 since no user deposits of LINK are expected in offchain mode + s_reserveAmounts[IERC20(address(i_link))] = 0; + for (uint256 idx = s_deactivatedTransmitters.length(); idx > 0; idx--) { s_deactivatedTransmitters.remove(s_deactivatedTransmitters.at(idx - 1)); } @@ -541,7 +549,7 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { } /** - * @notice returns the upkeep privilege config + * @notice returns the admin's privilege config */ function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { return s_adminPrivilegeConfig[admin]; @@ -555,7 +563,7 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { } /** - * @notice returns the upkeep's forwarder contract + * @notice returns if the dedupKey exists or not */ function hasDedupKey(bytes32 dedupKey) external view returns (bool) { return s_dedupKeys[dedupKey]; @@ -582,4 +590,35 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { function linkAvailableForPayment() public view returns (int256) { return _linkAvailableForPayment(); } + + /** + * @notice returns the BillingOverrides config for a given upkeep + */ + function getBillingOverrides(uint256 upkeepID) external view returns (BillingOverrides memory) { + return s_billingOverrides[upkeepID]; + } + + /** + * @notice returns the BillingConfig for a given billing token, this includes decimals and price feed etc + */ + function getBillingConfig(IERC20 billingToken) external view returns (BillingConfig memory) { + return s_billingConfigs[billingToken]; + } + + /** + * @notice returns all active transmitters with their associated payees + */ + function getTransmittersWithPayees() external view returns (TransmitterPayeeInfo[] memory) { + uint256 transmitterCount = s_transmittersList.length; + TransmitterPayeeInfo[] memory transmitters = new TransmitterPayeeInfo[](transmitterCount); + + for (uint256 i = 0; i < transmitterCount; i++) { + address transmitterAddress = s_transmittersList[i]; + address payeeAddress = s_transmitterPayees[transmitterAddress]; + + transmitters[i] = TransmitterPayeeInfo(transmitterAddress, payeeAddress); + } + + return transmitters; + } } diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 7c870bed7fb..17f5a3dd73f 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -3,29 +3,149 @@ pragma solidity ^0.8.0; import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; - -struct Capability { - // Capability type, e.g. "data-streams-reports" - // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ - // Not "type" because that's a reserved keyword in Solidity. - bytes32 capabilityType; - // Semver, e.g., "1.2.3" - // bytes32(string); must be valid Semver + max 32 characters. - bytes32 version; -} +import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { - mapping(bytes32 => Capability) private s_capabilities; + // Add the library methods + using EnumerableSet for EnumerableSet.Bytes32Set; + + struct NodeOperator { + /// @notice The address of the admin that can manage a node + /// operator + address admin; + /// @notice Human readable name of a Node Operator managing the node + string name; + } + + // CapabilityResponseType indicates whether remote response requires + // aggregation or is an already aggregated report. There are multiple + // possible ways to aggregate. + enum CapabilityResponseType { + // No additional aggregation is needed on the remote response. + REPORT, + // A number of identical observations need to be aggregated. + OBSERVATION_IDENTICAL + } + + struct Capability { + // Capability type, e.g. "data-streams-reports" + // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ + // Not "type" because that's a reserved keyword in Solidity. + bytes32 capabilityType; + // Semver, e.g., "1.2.3" + // bytes32(string); must be valid Semver + max 32 characters. + bytes32 version; + // responseType indicates whether remote response requires + // aggregation or is an OCR report. There are multiple possible + // ways to aggregate. + CapabilityResponseType responseType; + // An address to the capability configuration contract. Having this defined + // on a capability enforces consistent configuration across DON instances + // serving the same capability. Configuration contract MUST implement + // CapabilityConfigurationContractInterface. + // + // The main use cases are: + // 1) Sharing capability configuration across DON instances + // 2) Inspect and modify on-chain configuration without off-chain + // capability code. + // + // It is not recommended to store configuration which requires knowledge of + // the DON membership. + address configurationContract; + } + + /// @notice This error is thrown when trying to set a node operator's + /// admin address to the zero address + error InvalidNodeOperatorAdmin(); + + /// @notice This error is thrown when trying add a capability that already + /// exists. + error CapabilityAlreadyExists(); + + /// @notice This error is thrown when trying to add a capability with a + /// configuration contract that does not implement the required interface. + /// @param proposedConfigurationContract The address of the proposed + /// configuration contract. + error InvalidCapabilityConfigurationContractInterface(address proposedConfigurationContract); + + /// @notice This event is emitted when a new node operator is added + /// @param nodeOperatorId The ID of the newly added node operator + /// @param admin The address of the admin that can manage the node + /// operator + /// @param name The human readable name of the node operator + event NodeOperatorAdded(uint256 nodeOperatorId, address indexed admin, string name); + + /// @notice This event is emitted when a node operator is removed + /// @param nodeOperatorId The ID of the node operator that was removed + event NodeOperatorRemoved(uint256 nodeOperatorId); + /// @notice This event is emitted when a new capability is added + /// @param capabilityId The ID of the newly added capability event CapabilityAdded(bytes32 indexed capabilityId); + mapping(bytes32 => Capability) private s_capabilities; + EnumerableSet.Bytes32Set private s_capabilityIds; + + /// @notice Mapping of node operators + mapping(uint256 nodeOperatorId => NodeOperator) private s_nodeOperators; + + /// @notice The latest node operator ID + /// @dev No getter for this as this is an implementation detail + uint256 private s_nodeOperatorId; + function typeAndVersion() external pure override returns (string memory) { return "CapabilityRegistry 1.0.0"; } + /// @notice Adds a list of node operators + /// @param nodeOperators List of node operators to add + function addNodeOperators(NodeOperator[] calldata nodeOperators) external onlyOwner { + for (uint256 i; i < nodeOperators.length; ++i) { + NodeOperator memory nodeOperator = nodeOperators[i]; + if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); + uint256 nodeOperatorId = s_nodeOperatorId; + s_nodeOperators[nodeOperatorId] = NodeOperator({admin: nodeOperator.admin, name: nodeOperator.name}); + ++s_nodeOperatorId; + emit NodeOperatorAdded(nodeOperatorId, nodeOperator.admin, nodeOperator.name); + } + } + + /// @notice Removes a node operator + /// @param nodeOperatorIds The IDs of the node operators to remove + function removeNodeOperators(uint256[] calldata nodeOperatorIds) external onlyOwner { + for (uint256 i; i < nodeOperatorIds.length; ++i) { + uint256 nodeOperatorId = nodeOperatorIds[i]; + delete s_nodeOperators[nodeOperatorId]; + emit NodeOperatorRemoved(nodeOperatorId); + } + } + + /// @notice Gets a node operator's data + /// @param nodeOperatorId The ID of the node operator to query for + /// @return NodeOperator The node operator data + function getNodeOperator(uint256 nodeOperatorId) external view returns (NodeOperator memory) { + return s_nodeOperators[nodeOperatorId]; + } + function addCapability(Capability calldata capability) external onlyOwner { bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); + + if (s_capabilityIds.contains(capabilityId)) revert CapabilityAlreadyExists(); + + if (capability.configurationContract != address(0)) { + if ( + capability.configurationContract.code.length == 0 || + !IERC165(capability.configurationContract).supportsInterface( + ICapabilityConfiguration.getCapabilityConfiguration.selector + ) + ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); + } + + s_capabilityIds.add(capabilityId); s_capabilities[capabilityId] = capability; + emit CapabilityAdded(capabilityId); } @@ -34,7 +154,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } /// @notice This functions returns a Capability ID packed into a bytes32 for cheaper access - /// @return A unique identifier for the capability + /// @return bytes32 A unique identifier for the capability function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { return keccak256(abi.encodePacked(capabilityType, version)); } diff --git a/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol new file mode 100644 index 00000000000..20447c9680a --- /dev/null +++ b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @notice Interface for capability configuration contract. It MUST be +/// implemented for a contract to be used as a capability configuration. +/// The contract MAY store configuration that is shared across multiple +/// DON instances and capability versions. +/// @dev This interface does not guarantee the configuration contract's +/// correctness. It is the responsibility of the contract owner to ensure +/// that the configuration contract emits the CapabilityConfigurationSet +/// event when the configuration is set. +interface ICapabilityConfiguration { + /// @notice Emitted when a capability configuration is set. + event CapabilityConfigurationSet(); + + /// @notice Returns the capability configuration for a particular DON instance. + /// @dev donId is required to get DON-specific configuration. It avoids a + /// situation where configuration size grows too large. + /// @param donId The DON instance ID. These are stored in the CapabilityRegistry. + /// @return configuration DON's configuration for the capability. + function getCapabilityConfiguration(uint256 donId) external view returns (bytes memory configuration); + + // Solidity does not support generic returns types, so this cannot be part of + // the interface. However, the implementation contract MAY implement this + // function to enable configuration decoding on-chain. + // function decodeCapabilityConfiguration(bytes configuration) external returns (TypedCapabilityConfigStruct config) +} diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol new file mode 100644 index 00000000000..4517a256b15 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {Constants} from "./Constants.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract BaseTest is Test, Constants { + CapabilityRegistry internal s_capabilityRegistry; + CapabilityConfigurationContract internal s_capabilityConfigurationContract; + + function setUp() public virtual { + vm.startPrank(ADMIN); + s_capabilityRegistry = new CapabilityRegistry(); + s_capabilityConfigurationContract = new CapabilityConfigurationContract(); + } + + function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { + CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](2); + nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_ONE_ADMIN, name: NODE_OPERATOR_ONE_NAME}); + nodeOperators[1] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_TWO_ADMIN, name: NODE_OPERATOR_TWO_NAME}); + return nodeOperators; + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol deleted file mode 100644 index f5d539d8e34..00000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {Capability, CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistryTest is Test { - function setUp() public virtual {} - - function testAddCapability() public { - CapabilityRegistry capabilityRegistry = new CapabilityRegistry(); - - capabilityRegistry.addCapability(Capability("data-streams-reports", "1.0.0")); - - bytes32 capabilityId = capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); - Capability memory capability = capabilityRegistry.getCapability(capabilityId); - - assertEq(capability.capabilityType, "data-streams-reports"); - assertEq(capability.version, "1.0.0"); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol new file mode 100644 index 00000000000..d9e4b6b8383 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; + +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_AddCapabilityTest is BaseTest { + CapabilityRegistry.Capability private basicCapability = + CapabilityRegistry.Capability({ + capabilityType: "data-streams-reports", + version: "1.0.0", + responseType: CapabilityRegistry.CapabilityResponseType.REPORT, + configurationContract: address(0) + }); + + CapabilityRegistry.Capability private capabilityWithConfigurationContract = + CapabilityRegistry.Capability({ + capabilityType: "read-ethereum-mainnet-gas-price", + version: "1.0.2", + responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, + configurationContract: address(s_capabilityConfigurationContract) + }); + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_capabilityRegistry.addCapability(basicCapability); + } + + function test_RevertWhen_CapabilityExists() public { + // Successfully add the capability the first time + s_capabilityRegistry.addCapability(basicCapability); + + // Try to add the same capability again + vm.expectRevert(CapabilityRegistry.CapabilityAlreadyExists.selector); + s_capabilityRegistry.addCapability(basicCapability); + } + + function test_RevertWhen_ConfigurationContractNotDeployed() public { + address nonExistentContract = address(1); + capabilityWithConfigurationContract.configurationContract = nonExistentContract; + + vm.expectRevert( + abi.encodeWithSelector( + CapabilityRegistry.InvalidCapabilityConfigurationContractInterface.selector, + nonExistentContract + ) + ); + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + } + + function test_RevertWhen_ConfigurationContractDoesNotMatchInterface() public { + CapabilityRegistry contractWithoutERC165 = new CapabilityRegistry(); + + vm.expectRevert(); + capabilityWithConfigurationContract.configurationContract = address(contractWithoutERC165); + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + } + + function test_AddCapability_NoConfigurationContract() public { + s_capabilityRegistry.addCapability(basicCapability); + + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + + assertEq(storedCapability.capabilityType, basicCapability.capabilityType); + assertEq(storedCapability.version, basicCapability.version); + assertEq(uint256(storedCapability.responseType), uint256(basicCapability.responseType)); + assertEq(storedCapability.configurationContract, basicCapability.configurationContract); + } + + function test_AddCapability_WithConfiguration() public { + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + bytes32(capabilityWithConfigurationContract.capabilityType), + bytes32(capabilityWithConfigurationContract.version) + ); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + + assertEq(storedCapability.capabilityType, capabilityWithConfigurationContract.capabilityType); + assertEq(storedCapability.version, capabilityWithConfigurationContract.version); + assertEq(uint256(storedCapability.responseType), uint256(capabilityWithConfigurationContract.responseType)); + assertEq(storedCapability.configurationContract, capabilityWithConfigurationContract.configurationContract); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol new file mode 100644 index 00000000000..388c3ca9cdd --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_AddNodeOperatorsTest is BaseTest { + event NodeOperatorAdded(uint256 nodeOperatorId, address indexed admin, string name); + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_NodeOperatorAdminAddressZero() public { + changePrank(ADMIN); + CapabilityRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); + nodeOperators[0].admin = address(0); + vm.expectRevert(CapabilityRegistry.InvalidNodeOperatorAdmin.selector); + s_capabilityRegistry.addNodeOperators(nodeOperators); + } + + function test_AddNodeOperators() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorAdded(0, NODE_OPERATOR_ONE_ADMIN, NODE_OPERATOR_ONE_NAME); + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorAdded(1, NODE_OPERATOR_TWO_ADMIN, NODE_OPERATOR_TWO_NAME); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + + CapabilityRegistry.NodeOperator memory nodeOperatorOne = s_capabilityRegistry.getNodeOperator(0); + assertEq(nodeOperatorOne.admin, NODE_OPERATOR_ONE_ADMIN); + assertEq(nodeOperatorOne.name, NODE_OPERATOR_ONE_NAME); + + CapabilityRegistry.NodeOperator memory nodeOperatorTwo = s_capabilityRegistry.getNodeOperator(1); + assertEq(nodeOperatorTwo.admin, NODE_OPERATOR_TWO_ADMIN); + assertEq(nodeOperatorTwo.name, NODE_OPERATOR_TWO_NAME); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol new file mode 100644 index 00000000000..31b043fab3e --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_RemoveNodeOperatorsTest is BaseTest { + event NodeOperatorRemoved(uint256 nodeOperatorId); + + uint256 private constant TEST_NODE_OPERATOR_ONE_ID = 0; + uint256 private constant TEST_NODE_OPERATOR_TWO_ID = 1; + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_CalledByNonOwner() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + uint256[] memory nodeOperatorsToRemove = new uint256[](2); + nodeOperatorsToRemove[1] = 1; + s_capabilityRegistry.removeNodeOperators(nodeOperatorsToRemove); + } + + function test_RemovesNodeOperator() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorRemoved(TEST_NODE_OPERATOR_ONE_ID); + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorRemoved(TEST_NODE_OPERATOR_TWO_ID); + uint256[] memory nodeOperatorsToRemove = new uint256[](2); + nodeOperatorsToRemove[1] = 1; + s_capabilityRegistry.removeNodeOperators(nodeOperatorsToRemove); + + CapabilityRegistry.NodeOperator memory nodeOperatorOne = s_capabilityRegistry.getNodeOperator(0); + assertEq(nodeOperatorOne.admin, address(0)); + assertEq(nodeOperatorOne.name, ""); + + CapabilityRegistry.NodeOperator memory nodeOperatorTwo = s_capabilityRegistry.getNodeOperator(1); + assertEq(nodeOperatorTwo.admin, address(0)); + assertEq(nodeOperatorTwo.name, ""); + } +} diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol new file mode 100644 index 00000000000..b7eb85debb1 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; + +contract Constants { + address internal ADMIN = address(1); + address internal STRANGER = address(2); + address internal NODE_OPERATOR_ONE_ADMIN = address(3); + string internal NODE_OPERATOR_ONE_NAME = "node-operator-one"; + address internal NODE_OPERATOR_TWO_ADMIN = address(4); + string internal NODE_OPERATOR_TWO_NAME = "node-operator-two"; +} diff --git a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol new file mode 100644 index 00000000000..0c3d8e0597d --- /dev/null +++ b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; +import {ERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol"; + +contract CapabilityConfigurationContract is ICapabilityConfiguration, ERC165 { + mapping(uint256 => bytes) private s_donConfiguration; + + function getCapabilityConfiguration(uint256 donId) external view returns (bytes memory configuration) { + return s_donConfiguration[donId]; + } +} diff --git a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts index 02191dab999..31712e1380b 100644 --- a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts @@ -802,7 +802,6 @@ describe('AutomationRegistrar2_3', () => { }) describe('#approve', () => { - let hash: string let params: RegistrationParams beforeEach(async () => { @@ -834,47 +833,40 @@ describe('AutomationRegistrar2_3', () => { const tx = await linkToken .connect(requestSender) .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - hash = receipt.logs[2].topics[1] + await tx.wait() }) it('reverts if not called by the owner', async () => { - const tx = registrar.connect(stranger).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig: emptyBytes, - amount, - billingToken: linkToken.address, - }, - hash, - ) + const tx = registrar.connect(stranger).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig: emptyBytes, + amount, + billingToken: linkToken.address, + }) await evmRevert(tx, 'Only callable by owner') }) it('reverts if the hash does not exist', async () => { - const tx = registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig: emptyBytes, - amount, - billingToken: linkToken.address, - }, - '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', - ) + const tx = registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig: emptyBytes, + amount, + billingToken: linkToken.address, + }) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) }) @@ -917,67 +909,58 @@ describe('AutomationRegistrar2_3', () => { for (let i = 0; i < invalidFields.length; i++) { const field = invalidFields[i] const badParams = Object.assign({}, params, field) as RegistrationParams - const tx = registrar.connect(registrarOwner).approve(badParams, hash) + const tx = registrar.connect(registrarOwner).approve(badParams) await expect( tx, `expected ${JSON.stringify(field)} to cause failure, but succeeded`, - ).to.be.revertedWithCustomError(registrar, errorMsgs.hashPayload) + ).to.be.revertedWithCustomError(registrar, errorMsgs.requestNotFound) } }) it('approves an existing registration request', async () => { - const tx = await registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig, - amount, - billingToken: linkToken.address, - }, - hash, - ) + const tx = await registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig, + amount, + billingToken: linkToken.address, + }) await expect(tx).to.emit(registrar, 'RegistrationApproved') }) it('deletes the request afterwards / reverts if the request DNE', async () => { - await registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig, - amount, - billingToken: linkToken.address, - }, - hash, - ) - const tx = registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig, - amount, - billingToken: linkToken.address, - }, - hash, - ) + await registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig, + amount, + billingToken: linkToken.address, + }) + const tx = registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig, + amount, + billingToken: linkToken.address, + }) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) }) }) @@ -1049,22 +1032,19 @@ describe('AutomationRegistrar2_3', () => { await registrar.connect(registrarOwner).cancel(hash) let tx = registrar.connect(registrarOwner).cancel(hash) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) - tx = registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig: emptyBytes, - amount, - billingToken: linkToken.address, - }, - hash, - ) + tx = registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig: emptyBytes, + amount, + billingToken: linkToken.address, + }) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) }) }) diff --git a/core/bridges/orm_test.go b/core/bridges/orm_test.go index 85e8b9ecdef..b85b6be00dd 100644 --- a/core/bridges/orm_test.go +++ b/core/bridges/orm_test.go @@ -144,7 +144,7 @@ func TestORM_TestCachedResponse(t *testing.T) { orm := bridges.NewORM(db) trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(ctx, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) _, err = orm.GetCachedResponse(ctx, "dot", specID, 1*time.Second) diff --git a/core/capabilities/registry_test.go b/core/capabilities/registry_test.go index 3bed31a957a..ccff0a5360e 100644 --- a/core/capabilities/registry_test.go +++ b/core/capabilities/registry_test.go @@ -42,6 +42,7 @@ func TestRegistry(t *testing.T) { capabilities.CapabilityTypeAction, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -70,6 +71,7 @@ func TestRegistry_NoDuplicateIDs(t *testing.T) { capabilities.CapabilityTypeAction, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -82,6 +84,7 @@ func TestRegistry_NoDuplicateIDs(t *testing.T) { capabilities.CapabilityTypeConsensus, "capability-2-description", "v1.0.0", + nil, ) require.NoError(t, err) c2 := &mockCapability{CapabilityInfo: ci} @@ -106,6 +109,7 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { capabilities.CapabilityTypeAction, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -126,6 +130,7 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { capabilities.CapabilityTypeTarget, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -159,6 +164,7 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { capabilities.CapabilityTypeConsensus, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) diff --git a/core/capabilities/remote/target.go b/core/capabilities/remote/target.go index 92b0724512a..655f4f84abb 100644 --- a/core/capabilities/remote/target.go +++ b/core/capabilities/remote/target.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -12,7 +13,7 @@ import ( // remoteTargetCaller/Receiver are shims translating between capability API calls and network messages type remoteTargetCaller struct { capInfo commoncap.CapabilityInfo - donInfo *types.DON + donInfo *capabilities.DON dispatcher types.Dispatcher lggr logger.Logger } @@ -22,14 +23,14 @@ var _ types.Receiver = &remoteTargetCaller{} type remoteTargetReceiver struct { capInfo commoncap.CapabilityInfo - donInfo *types.DON + donInfo *capabilities.DON dispatcher types.Dispatcher lggr logger.Logger } var _ types.Receiver = &remoteTargetReceiver{} -func NewRemoteTargetCaller(capInfo commoncap.CapabilityInfo, donInfo *types.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetCaller { +func NewRemoteTargetCaller(capInfo commoncap.CapabilityInfo, donInfo *capabilities.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetCaller { return &remoteTargetCaller{ capInfo: capInfo, donInfo: donInfo, @@ -72,7 +73,7 @@ func (c *remoteTargetCaller) Receive(msg *types.MessageBody) { c.lggr.Debugw("not implemented - received message", "capabilityId", c.capInfo.ID, "payload", msg.Payload) } -func NewRemoteTargetReceiver(capInfo commoncap.CapabilityInfo, donInfo *types.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetReceiver { +func NewRemoteTargetReceiver(capInfo commoncap.CapabilityInfo, donInfo *capabilities.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetReceiver { return &remoteTargetReceiver{ capInfo: capInfo, donInfo: donInfo, diff --git a/core/capabilities/remote/target_test.go b/core/capabilities/remote/target_test.go index a9e72d778df..0f9bad51f67 100644 --- a/core/capabilities/remote/target_test.go +++ b/core/capabilities/remote/target_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" remoteMocks "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -18,7 +18,7 @@ import ( func TestTarget_Placeholder(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) - donInfo := &types.DON{ + donInfo := &capabilities.DON{ Members: []p2ptypes.PeerID{{}}, } dispatcher := remoteMocks.NewDispatcher(t) diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index d06254657c7..12d539a2dc0 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -24,8 +24,8 @@ type triggerPublisher struct { config types.RemoteTriggerConfig underlying commoncap.TriggerCapability capInfo commoncap.CapabilityInfo - capDonInfo types.DON - workflowDONs map[string]types.DON + capDonInfo commoncap.DON + workflowDONs map[string]commoncap.DON dispatcher types.Dispatcher messageCache *messageCache[registrationKey, p2ptypes.PeerID] registrations map[registrationKey]*pubRegState @@ -48,7 +48,7 @@ type pubRegState struct { var _ types.Receiver = &triggerPublisher{} var _ services.Service = &triggerPublisher{} -func NewTriggerPublisher(config types.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo types.DON, workflowDONs map[string]types.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { +func NewTriggerPublisher(config types.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[string]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { config.ApplyDefaults() return &triggerPublisher{ config: config, diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index dd107e12e61..71a5174c07f 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -29,12 +29,12 @@ func TestTriggerPublisher_Register(t *testing.T) { require.NoError(t, p1.UnmarshalText([]byte(peerID1))) p2 := p2ptypes.PeerID{} require.NoError(t, p2.UnmarshalText([]byte(peerID2))) - capDonInfo := remotetypes.DON{ + capDonInfo := commoncap.DON{ ID: "capability-don", Members: []p2ptypes.PeerID{p1}, F: 0, } - workflowDonInfo := remotetypes.DON{ + workflowDonInfo := commoncap.DON{ ID: "workflow-don", Members: []p2ptypes.PeerID{p2}, F: 0, @@ -47,7 +47,7 @@ func TestTriggerPublisher_Register(t *testing.T) { MinResponsesToAggregate: 1, MessageExpiryMs: 100_000, } - workflowDONs := map[string]remotetypes.DON{ + workflowDONs := map[string]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } underlying := &testTrigger{ diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index a7cb58c008b..e9704bf1865 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -6,6 +6,7 @@ import ( sync "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -24,9 +25,9 @@ import ( type triggerSubscriber struct { config types.RemoteTriggerConfig capInfo commoncap.CapabilityInfo - capDonInfo types.DON + capDonInfo capabilities.DON capDonMembers map[p2ptypes.PeerID]struct{} - localDonInfo types.DON + localDonInfo capabilities.DON dispatcher types.Dispatcher aggregator types.Aggregator messageCache *messageCache[triggerEventKey, p2ptypes.PeerID] @@ -54,8 +55,7 @@ var _ services.Service = &triggerSubscriber{} // TODO makes this configurable with a default const defaultSendChannelBufferSize = 1000 -func NewTriggerSubscriber(config types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo types.DON, localDonInfo types.DON, - dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { +func NewTriggerSubscriber(config types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo capabilities.DON, localDonInfo capabilities.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { if aggregator == nil { lggr.Warnw("no aggregator provided, using default MODE aggregator", "capabilityId", capInfo.ID) aggregator = NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index df04306e2b0..4d251d49dc8 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -38,12 +38,12 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { require.NoError(t, p1.UnmarshalText([]byte(peerID1))) p2 := p2ptypes.PeerID{} require.NoError(t, p2.UnmarshalText([]byte(peerID2))) - capDonInfo := remotetypes.DON{ + capDonInfo := commoncap.DON{ ID: "capability-don", Members: []p2ptypes.PeerID{p1}, F: 0, } - workflowDonInfo := remotetypes.DON{ + workflowDonInfo := commoncap.DON{ ID: "workflow-don", Members: []p2ptypes.PeerID{p2}, F: 0, diff --git a/core/capabilities/syncer.go b/core/capabilities/syncer.go index dc9126dba36..67d388a8221 100644 --- a/core/capabilities/syncer.go +++ b/core/capabilities/syncer.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/mercury" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" @@ -70,7 +71,7 @@ func (s *registrySyncer) Start(ctx context.Context) error { "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", } allPeers := make(map[ragetypes.PeerID]p2ptypes.StreamConfig) - addPeersToDONInfo := func(peers []string, donInfo *remotetypes.DON) error { + addPeersToDONInfo := func(peers []string, donInfo *capabilities.DON) error { for _, peerID := range peers { var p ragetypes.PeerID err := p.UnmarshalText([]byte(peerID)) @@ -82,11 +83,11 @@ func (s *registrySyncer) Start(ctx context.Context) error { } return nil } - workflowDonInfo := remotetypes.DON{ID: "workflowDon1", F: 1} + workflowDonInfo := capabilities.DON{ID: "workflowDon1", F: 1} if err := addPeersToDONInfo(workflowDONPeers, &workflowDonInfo); err != nil { return err } - triggerCapabilityDonInfo := remotetypes.DON{ID: "capabilityDon1", F: 1} + triggerCapabilityDonInfo := capabilities.DON{ID: "capabilityDon1", F: 1} if err := addPeersToDONInfo(triggerDONPeers, &triggerCapabilityDonInfo); err != nil { return err } @@ -101,6 +102,7 @@ func (s *registrySyncer) Start(ctx context.Context) error { CapabilityType: commoncap.CapabilityTypeTrigger, Description: "Remote Trigger", Version: "0.0.1", + DON: &triggerCapabilityDonInfo, } myId := s.peerWrapper.GetPeer().ID().String() config := remotetypes.RemoteTriggerConfig{ @@ -125,7 +127,7 @@ func (s *registrySyncer) Start(ctx context.Context) error { } if slices.Contains(triggerDONPeers, myId) { s.lggr.Info("member of a capability DON - starting remote publishers") - workflowDONs := map[string]remotetypes.DON{ + workflowDONs := map[string]capabilities.DON{ workflowDonInfo.ID: workflowDonInfo, } underlying := triggers.NewMercuryTriggerService(1000, s.lggr) diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 47f1048211e..3349e05003e 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -63,6 +63,7 @@ func NewEvmWrite(chain legacyevm.Chain, lggr logger.Logger) *EvmWrite { capabilities.CapabilityTypeTarget, "Write target.", "v1.0.0", + nil, ) return &EvmWrite{ diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 255b038037a..548acf3206c 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -130,7 +130,7 @@ func (r *rpcClient) Dial(callerCtx context.Context) error { wsrpc, err := rpc.DialWebsocket(ctx, r.ws.uri.String(), "") if err != nil { promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc() - return pkgerrors.Wrapf(err, "error while dialing websocket: %v", r.ws.uri.Redacted()) + return r.wrapRPCClientError(pkgerrors.Wrapf(err, "error while dialing websocket: %v", r.ws.uri.Redacted())) } r.ws.rpc = wsrpc @@ -159,7 +159,7 @@ func (r *rpcClient) DialHTTP() error { httprpc, err := rpc.DialHTTP(r.http.uri.String()) if err != nil { promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc() - return pkgerrors.Wrapf(err, "error while dialing HTTP: %v", r.http.uri.Redacted()) + return r.wrapRPCClientError(pkgerrors.Wrapf(err, "error while dialing HTTP: %v", r.http.uri.Redacted())) } r.http.rpc = httprpc @@ -295,10 +295,7 @@ func (r *rpcClient) UnsubscribeAllExceptAliveLoop() { // CallContext implementation func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With( "method", method, @@ -307,6 +304,7 @@ func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method lggr.Debug("RPC call: evmclient.Client#CallContext") start := time.Now() + var err error if http != nil { err = r.wrapHTTP(http.rpc.CallContext(ctx, result, method, args...)) } else { @@ -320,15 +318,13 @@ func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method } func (r *rpcClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("nBatchElems", len(b), "batchElems", b) lggr.Trace("RPC call: evmclient.Client#BatchCallContext") start := time.Now() + var err error if http != nil { err = r.wrapHTTP(http.rpc.BatchCallContext(ctx, b)) } else { @@ -342,24 +338,23 @@ func (r *rpcClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) err } func (r *rpcClient) Subscribe(ctx context.Context, channel chan<- *evmtypes.Head, args ...interface{}) (commontypes.Subscription, error) { - ctx, cancel, ws, _, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, _ := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("args", args) lggr.Debug("RPC call: evmclient.Client#EthSubscribe") start := time.Now() + var sub commontypes.Subscription sub, err := ws.rpc.EthSubscribe(ctx, channel, args...) if err == nil { + sub = newSubscriptionErrorWrapper(sub, r.rpcClientErrorPrefix()) r.registerSub(sub) } duration := time.Since(start) r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe") - return sub, err + return sub, r.wrapWS(err) } // GethClient wrappers @@ -370,17 +365,14 @@ func (r *rpcClient) TransactionReceipt(ctx context.Context, txHash common.Hash) return nil, err } if receipt == nil { - err = ethereum.NotFound + err = r.wrapRPCClientError(ethereum.NotFound) return } return } func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("txHash", txHash) @@ -403,10 +395,7 @@ func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Ha return } func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("txHash", txHash) @@ -430,10 +419,7 @@ func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) ( } func (r *rpcClient) HeaderByNumber(ctx context.Context, number *big.Int) (header *types.Header, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("number", number) @@ -454,10 +440,7 @@ func (r *rpcClient) HeaderByNumber(ctx context.Context, number *big.Int) (header } func (r *rpcClient) HeaderByHash(ctx context.Context, hash common.Hash) (header *types.Header, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("hash", hash) @@ -494,7 +477,7 @@ func (r *rpcClient) blockByNumber(ctx context.Context, number string) (head *evm return nil, err } if head == nil { - err = ethereum.NotFound + err = r.wrapRPCClientError(ethereum.NotFound) return } head.EVMChainID = ubig.New(r.chainID) @@ -507,7 +490,7 @@ func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *ev return nil, err } if head == nil { - err = ethereum.NotFound + err = r.wrapRPCClientError(ethereum.NotFound) return } head.EVMChainID = ubig.New(r.chainID) @@ -515,10 +498,7 @@ func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *ev } func (r *rpcClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (block *types.Block, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("hash", hash) @@ -541,10 +521,7 @@ func (r *rpcClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (bloc } func (r *rpcClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (block *types.Block, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("number", number) @@ -567,15 +544,13 @@ func (r *rpcClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (blo } func (r *rpcClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("tx", tx) lggr.Debug("RPC call: evmclient.Client#SendTransaction") start := time.Now() + var err error if http != nil { err = r.wrapHTTP(http.geth.SendTransaction(ctx, tx)) } else { @@ -607,10 +582,7 @@ func (r *rpcClient) SendEmptyTransaction( // PendingSequenceAt returns one higher than the highest nonce from both mempool and mined transactions func (r *rpcClient) PendingSequenceAt(ctx context.Context, account common.Address) (nonce evmtypes.Nonce, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account) @@ -639,10 +611,7 @@ func (r *rpcClient) PendingSequenceAt(ctx context.Context, account common.Addres // mined nonce at the given block number, but it actually returns the total // transaction count which is the highest mined nonce + 1 func (r *rpcClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (nonce evmtypes.Nonce, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) @@ -668,10 +637,7 @@ func (r *rpcClient) SequenceAt(ctx context.Context, account common.Address, bloc } func (r *rpcClient) PendingCodeAt(ctx context.Context, account common.Address) (code []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account) @@ -694,10 +660,7 @@ func (r *rpcClient) PendingCodeAt(ctx context.Context, account common.Address) ( } func (r *rpcClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) (code []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) @@ -720,10 +683,7 @@ func (r *rpcClient) CodeAt(ctx context.Context, account common.Address, blockNum } func (r *rpcClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() call := c.(ethereum.CallMsg) lggr := r.newRqLggr().With("call", call) @@ -747,10 +707,7 @@ func (r *rpcClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, } func (r *rpcClient) SuggestGasPrice(ctx context.Context) (price *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() @@ -773,10 +730,7 @@ func (r *rpcClient) SuggestGasPrice(ctx context.Context) (price *big.Int, err er } func (r *rpcClient) CallContract(ctx context.Context, msg interface{}, blockNumber *big.Int) (val []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("callMsg", msg, "blockNumber", blockNumber) message := msg.(ethereum.CallMsg) @@ -804,10 +758,7 @@ func (r *rpcClient) CallContract(ctx context.Context, msg interface{}, blockNumb } func (r *rpcClient) PendingCallContract(ctx context.Context, msg interface{}) (val []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("callMsg", msg) message := msg.(ethereum.CallMsg) @@ -841,10 +792,7 @@ func (r *rpcClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) { } func (r *rpcClient) BlockNumber(ctx context.Context) (height uint64, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() @@ -867,10 +815,7 @@ func (r *rpcClient) BlockNumber(ctx context.Context) (height uint64, err error) } func (r *rpcClient) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (balance *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account.Hex(), "blockNumber", blockNumber) @@ -907,7 +852,7 @@ func (r *rpcClient) TokenBalance(ctx context.Context, address common.Address, co return numLinkBigInt, err } if _, ok := numLinkBigInt.SetString(result, 0); !ok { - return nil, fmt.Errorf("failed to parse int: %s", result) + return nil, r.wrapRPCClientError(fmt.Errorf("failed to parse int: %s", result)) } return numLinkBigInt, nil } @@ -926,10 +871,7 @@ func (r *rpcClient) FilterEvents(ctx context.Context, q ethereum.FilterQuery) ([ } func (r *rpcClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l []types.Log, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("q", q) @@ -957,10 +899,7 @@ func (r *rpcClient) ClientVersion(ctx context.Context) (version string, err erro } func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (sub ethereum.Subscription, err error) { - ctx, cancel, ws, _, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, _ := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("q", q) @@ -968,6 +907,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu start := time.Now() sub, err = ws.geth.SubscribeFilterLogs(ctx, q, ch) if err == nil { + sub = newSubscriptionErrorWrapper(sub, r.rpcClientErrorPrefix()) r.registerSub(sub) } err = r.wrapWS(err) @@ -979,10 +919,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu } func (r *rpcClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() @@ -1007,7 +944,7 @@ func (r *rpcClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err // Returns the ChainID according to the geth client. This is useful for functions like verify() // the common node. func (r *rpcClient) ChainID(ctx context.Context) (chainID *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() @@ -1026,6 +963,15 @@ func (r *rpcClient) newRqLggr() logger.SugaredLogger { return r.rpcLog.With("requestID", uuid.New()) } +func (r *rpcClient) wrapRPCClientError(err error) error { + // simple add msg to the error without adding new stack trace + return pkgerrors.WithMessage(err, r.rpcClientErrorPrefix()) +} + +func (r *rpcClient) rpcClientErrorPrefix() string { + return fmt.Sprintf("RPCClient returned error (%s)", r.name) +} + func wrapCallError(err error, tp string) error { if err == nil { return nil @@ -1038,11 +984,12 @@ func wrapCallError(err error, tp string) error { func (r *rpcClient) wrapWS(err error) error { err = wrapCallError(err, fmt.Sprintf("%s websocket (%s)", r.tier.String(), r.ws.uri.Redacted())) - return err + return r.wrapRPCClientError(err) } func (r *rpcClient) wrapHTTP(err error) error { err = wrapCallError(err, fmt.Sprintf("%s http (%s)", r.tier.String(), r.http.uri.Redacted())) + err = r.wrapRPCClientError(err) if err != nil { r.rpcLog.Debugw("Call failed", "err", err) } else { @@ -1052,7 +999,7 @@ func (r *rpcClient) wrapHTTP(err error) error { } // makeLiveQueryCtxAndSafeGetClients wraps makeQueryCtx -func (r *rpcClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context) (ctx context.Context, cancel context.CancelFunc, ws rawclient, http *rawclient, err error) { +func (r *rpcClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context) (ctx context.Context, cancel context.CancelFunc, ws rawclient, http *rawclient) { // Need to wrap in mutex because state transition can cancel and replace the // context r.stateMu.RLock() @@ -1072,16 +1019,14 @@ func (r *rpcClient) makeQueryCtx(ctx context.Context) (context.Context, context. } func (r *rpcClient) IsSyncing(ctx context.Context) (bool, error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return false, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() lggr.Debug("RPC call: evmclient.Client#SyncProgress") var syncProgress *ethereum.SyncProgress start := time.Now() + var err error if http != nil { syncProgress, err = http.geth.SyncProgress(ctx) err = r.wrapHTTP(err) diff --git a/core/chains/evm/client/sub_error_wrapper.go b/core/chains/evm/client/sub_error_wrapper.go new file mode 100644 index 00000000000..689991ce70f --- /dev/null +++ b/core/chains/evm/client/sub_error_wrapper.go @@ -0,0 +1,77 @@ +package client + +import ( + "fmt" + + commontypes "github.com/smartcontractkit/chainlink/v2/common/types" +) + +// subErrorWrapper - adds specified prefix to a subscription error +type subErrorWrapper struct { + sub commontypes.Subscription + errorPrefix string + + done chan struct{} + unSub chan struct{} + errorCh chan error +} + +func newSubscriptionErrorWrapper(sub commontypes.Subscription, errorPrefix string) *subErrorWrapper { + s := &subErrorWrapper{ + sub: sub, + errorPrefix: errorPrefix, + done: make(chan struct{}), + unSub: make(chan struct{}), + errorCh: make(chan error), + } + + go func() { + for { + select { + // sub.Err channel is closed by sub.Unsubscribe + case err, ok := <-sub.Err(): + if !ok { + // might only happen if someone terminated wrapped subscription + // in any case - do our best to release resources + // we can't call Unsubscribe on root sub as this might cause panic + close(s.errorCh) + close(s.done) + return + } + + select { + case s.errorCh <- fmt.Errorf("%s: %w", s.errorPrefix, err): + case <-s.unSub: + s.close() + return + } + case <-s.unSub: + s.close() + return + } + } + }() + + return s +} + +func (s *subErrorWrapper) close() { + s.sub.Unsubscribe() + close(s.errorCh) + close(s.done) +} + +func (s *subErrorWrapper) Unsubscribe() { + select { + // already unsubscribed + case <-s.done: + // signal unsubscribe + case s.unSub <- struct{}{}: + // wait for unsubscribe to complete + <-s.done + } +} + +func (s *subErrorWrapper) Err() <-chan error { + return s.errorCh +} diff --git a/core/chains/evm/client/sub_error_wrapper_test.go b/core/chains/evm/client/sub_error_wrapper_test.go new file mode 100644 index 00000000000..457d392a50e --- /dev/null +++ b/core/chains/evm/client/sub_error_wrapper_test.go @@ -0,0 +1,75 @@ +package client + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" +) + +func TestSubscriptionErrorWrapper(t *testing.T) { + t.Parallel() + t.Run("Unsubscribe wrapper releases resources", func(t *testing.T) { + t.Parallel() + + mockedSub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(mockedSub, prefix) + wrapper.Unsubscribe() + + // mock's resources were relased + assert.True(t, mockedSub.unsubscribed) + _, ok := <-mockedSub.Err() + assert.False(t, ok) + // wrapper's channels are closed + _, ok = <-wrapper.Err() + assert.False(t, ok) + // subsequence unsubscribe does not causes panic + wrapper.Unsubscribe() + }) + t.Run("Unsubscribe interrupts error delivery", func(t *testing.T) { + t.Parallel() + sub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(sub, prefix) + sub.Errors <- fmt.Errorf("error") + + wrapper.Unsubscribe() + _, ok := <-wrapper.Err() + assert.False(t, ok) + }) + t.Run("Successfully wraps error", func(t *testing.T) { + t.Parallel() + sub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(sub, prefix) + sub.Errors <- fmt.Errorf("root error") + + err, ok := <-wrapper.Err() + assert.True(t, ok) + assert.Equal(t, "RPC returned error: root error", err.Error()) + + wrapper.Unsubscribe() + _, ok = <-wrapper.Err() + assert.False(t, ok) + }) + t.Run("Unsubscribe on root does not cause panic", func(t *testing.T) { + t.Parallel() + mockedSub := NewMockSubscription() + wrapper := newSubscriptionErrorWrapper(mockedSub, "") + + mockedSub.Unsubscribe() + // mock's resources were released + assert.True(t, mockedSub.unsubscribed) + _, ok := <-mockedSub.Err() + assert.False(t, ok) + // wrapper's channels are eventually closed + tests.AssertEventually(t, func() bool { + _, ok = <-wrapper.Err() + return !ok + }) + + }) +} diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 8b8c626f725..0ae067e45bf 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -721,7 +721,7 @@ func (b *BlockHistoryEstimator) batchFetch(ctx context.Context, reqs []rpc.Batch err := b.ethClient.BatchCallContext(ctx, reqs[i:j]) if pkgerrors.Is(err, context.DeadlineExceeded) { // We ran out of time, return what we have - b.logger.Warnf("Batch fetching timed out; loaded %d/%d results", i, len(reqs)) + b.logger.Warnf("Batch fetching timed out; loaded %d/%d results: %v", i, len(reqs), err) for k := i; k < len(reqs); k++ { if k < j { reqs[k].Error = pkgerrors.Wrap(err, "request failed") diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index 0d725b8594b..13aeb8d2338 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -110,7 +110,7 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, m[r.Chain().ID().String()] = r.Chain() } legacyChains := legacyevm.NewLegacyChains(m, cc.AppConfig().EVMConfigs()) - pipelineHelper := cltest.NewJobPipelineV2(t, globalConfig.WebServer(), globalConfig.JobPipeline(), globalConfig.Database(), legacyChains, db, kst, nil, nil) + pipelineHelper := cltest.NewJobPipelineV2(t, globalConfig.WebServer(), globalConfig.JobPipeline(), legacyChains, db, kst, nil, nil) return &broadcasterHelper{ t: t, @@ -263,7 +263,7 @@ func (helper *broadcasterHelper) newLogListenerWithJob(name string) *simpleLogLi PipelineSpec: &pipeline.Spec{}, ExternalJobID: uuid.New(), } - err := helper.pipelineHelper.Jrm.CreateJob(jb) + err := helper.pipelineHelper.Jrm.CreateJob(testutils.Context(t), jb) require.NoError(t, err) var rec received @@ -288,7 +288,7 @@ func (listener *simpleLogListener) HandleLog(ctx context.Context, lb log.Broadca listener.received.logs = append(listener.received.logs, lb.RawLog()) listener.received.broadcasts = append(listener.received.broadcasts, lb) - consumed := listener.handleLogBroadcast(lb) + consumed := listener.handleLogBroadcast(ctx, lb) if !consumed { listener.received.uniqueLogs = append(listener.received.uniqueLogs, lb.RawLog()) @@ -321,9 +321,8 @@ func (listener *simpleLogListener) requireAllReceived(t *testing.T, expectedStat }, testutils.WaitTimeout(t), time.Second, "len(received.uniqueLogs): %v is not equal len(expectedState.uniqueLogs): %v", len(received.getUniqueLogs()), len(expectedState.getUniqueLogs())) } -func (listener *simpleLogListener) handleLogBroadcast(lb log.Broadcast) bool { +func (listener *simpleLogListener) handleLogBroadcast(ctx context.Context, lb log.Broadcast) bool { t := listener.t - ctx := testutils.Context(t) consumed, err := listener.WasAlreadyConsumed(ctx, lb) if !assert.NoError(t, err) { return false @@ -354,8 +353,8 @@ type mockListener struct { jobID int32 } -func (l *mockListener) JobID() int32 { return l.jobID } -func (l *mockListener) HandleLog(log.Broadcast) {} +func (l *mockListener) JobID() int32 { return l.jobID } +func (l *mockListener) HandleLog(context.Context, log.Broadcast) {} type mockEthClientExpectedCalls struct { SubscribeFilterLogs int diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go index fd6b375d80a..e34533b3cfb 100644 --- a/core/chains/evm/log/integration_test.go +++ b/core/chains/evm/log/integration_test.go @@ -250,7 +250,6 @@ func TestBroadcaster_ReplaysLogs(t *testing.T) { func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { contract1 := newMockContract(t) contract2 := newMockContract(t) - ctx := testutils.Context(t) blocks := cltest.NewBlocks(t, 10) const ( @@ -267,6 +266,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 0, 1, logs, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) listener := helper.newLogListenerWithJob("one") @@ -292,6 +292,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 2, 1, logs, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) contract1.On("ParseLog", log1).Return(flux_aggregator_wrapper.FluxAggregatorNewRound{}, nil) contract2.On("ParseLog", log2).Return(flux_aggregator_wrapper.FluxAggregatorAnswerUpdated{}, nil) @@ -318,6 +319,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 4, 1, logs, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) listener := helper.newLogListenerWithJob("one") @@ -342,6 +344,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 7, 1, logs[1:], func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) listener := helper.newLogListenerWithJob("one") listener2 := helper.newLogListenerWithJob("two") @@ -377,8 +380,9 @@ func (helper *broadcasterHelper) simulateHeads(t *testing.T, listener, listener2 <-headsDone + ctx := testutils.Context(t) require.Eventually(t, func() bool { - blockNum, err := orm.GetPendingMinBlock(testutils.Context(t)) + blockNum, err := orm.GetPendingMinBlock(ctx) if !assert.NoError(t, err) { return false } diff --git a/core/chains/evm/logpoller/disabled.go b/core/chains/evm/logpoller/disabled.go index f3e64378384..6f95b9c55da 100644 --- a/core/chains/evm/logpoller/disabled.go +++ b/core/chains/evm/logpoller/disabled.go @@ -114,3 +114,11 @@ func (d disabled) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, from func (d disabled) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { return nil, ErrDisabled } + +func (d disabled) FindLCA(ctx context.Context) (*LogPollerBlock, error) { + return nil, ErrDisabled +} + +func (d disabled) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { + return ErrDisabled +} diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index de2a182bbce..cd26889627f 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -44,6 +44,8 @@ type LogPoller interface { GetFilters() map[string]Filter LatestBlock(ctx context.Context) (LogPollerBlock, error) GetBlocksRange(ctx context.Context, numbers []uint64) ([]LogPollerBlock, error) + FindLCA(ctx context.Context) (*LogPollerBlock, error) + DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error // General querying Logs(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address) ([]Log, error) @@ -699,8 +701,8 @@ func (lp *logPoller) BackupPollAndSaveLogs(ctx context.Context) { } return } - // If this is our first run, start from block min(lastProcessed.FinalizedBlockNumber-1, lastProcessed.BlockNumber-backupPollerBlockDelay) - backupStartBlock := mathutil.Min(lastProcessed.FinalizedBlockNumber-1, lastProcessed.BlockNumber-lp.backupPollerBlockDelay) + // If this is our first run, start from block min(lastProcessed.FinalizedBlockNumber, lastProcessed.BlockNumber-backupPollerBlockDelay) + backupStartBlock := mathutil.Min(lastProcessed.FinalizedBlockNumber, lastProcessed.BlockNumber-lp.backupPollerBlockDelay) // (or at block 0 if whole blockchain is too short) lp.backupPollerNextBlock = mathutil.Max(backupStartBlock, 0) } @@ -771,11 +773,16 @@ func convertTopics(topics []common.Hash) [][]byte { return topicsForDB } -func (lp *logPoller) blocksFromLogs(ctx context.Context, logs []types.Log) (blocks []LogPollerBlock, err error) { +// blocksFromLogs fetches all of the blocks associated with a given list of logs. It will also unconditionally fetch endBlockNumber, +// whether or not there are any logs in the list from that block +func (lp *logPoller) blocksFromLogs(ctx context.Context, logs []types.Log, endBlockNumber uint64) (blocks []LogPollerBlock, err error) { var numbers []uint64 for _, log := range logs { numbers = append(numbers, log.BlockNumber) } + if numbers[len(numbers)-1] != endBlockNumber { + numbers = append(numbers, endBlockNumber) + } return lp.GetBlocksRange(ctx, numbers) } @@ -789,6 +796,7 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { batchSize := lp.backfillBatchSize for from := start; from <= end; from += batchSize { to := mathutil.Min(from+batchSize-1, end) + gethLogs, err := lp.ec.FilterLogs(ctx, lp.Filter(big.NewInt(from), big.NewInt(to), nil)) if err != nil { var rpcErr client.JsonError @@ -810,13 +818,19 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { if len(gethLogs) == 0 { continue } - blocks, err := lp.blocksFromLogs(ctx, gethLogs) + blocks, err := lp.blocksFromLogs(ctx, gethLogs, uint64(to)) if err != nil { return err } + endblock := blocks[len(blocks)-1] + if gethLogs[len(gethLogs)-1].BlockNumber != uint64(to) { + // Pop endblock if there were no logs for it, so that length of blocks & gethLogs are the same to pass to convertLogs + blocks = blocks[:len(blocks)-1] + } + lp.lggr.Debugw("Backfill found logs", "from", from, "to", to, "logs", len(gethLogs), "blocks", blocks) - err = lp.orm.InsertLogsWithBlock(ctx, convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), blocks[len(blocks)-1]) + err = lp.orm.InsertLogsWithBlock(ctx, convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), endblock) if err != nil { lp.lggr.Warnw("Unable to insert logs, retrying", "err", err, "from", from, "to", to) return err @@ -955,19 +969,18 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int currentBlockNumber = lastSafeBackfillBlock + 1 } - if currentBlockNumber > currentBlock.Number { - // If we successfully backfilled we have logs up to and including lastSafeBackfillBlock, - // now load the first unfinalized block. - currentBlock, err = lp.getCurrentBlockMaybeHandleReorg(ctx, currentBlockNumber, nil) - if err != nil { - // If there's an error handling the reorg, we can't be sure what state the db was left in. - // Resume from the latest block saved. - lp.lggr.Errorw("Unable to get current block", "err", err) - return + for { + if currentBlockNumber > currentBlock.Number { + currentBlock, err = lp.getCurrentBlockMaybeHandleReorg(ctx, currentBlockNumber, nil) + if err != nil { + // If there's an error handling the reorg, we can't be sure what state the db was left in. + // Resume from the latest block saved. + lp.lggr.Errorw("Unable to get current block", "err", err) + return + } + currentBlockNumber = currentBlock.Number } - } - for { h := currentBlock.Hash var logs []types.Log logs, err = lp.ec.FilterLogs(ctx, lp.Filter(nil, nil, &h)) @@ -992,14 +1005,6 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int if currentBlockNumber > latestBlockNumber { break } - currentBlock, err = lp.getCurrentBlockMaybeHandleReorg(ctx, currentBlockNumber, nil) - if err != nil { - // If there's an error handling the reorg, we can't be sure what state the db was left in. - // Resume from the latest block saved. - lp.lggr.Errorw("Unable to get current block", "err", err) - return - } - currentBlockNumber = currentBlock.Number } } @@ -1252,12 +1257,16 @@ func (lp *logPoller) GetBlocksRange(ctx context.Context, numbers []uint64) ([]Lo return blocks, nil } +// fillRemainingBlocksFromRPC sends a batch request for each block in blocksRequested, and converts them from +// geth blocks into LogPollerBlock structs. This is only intended to be used for requesting finalized blocks, +// if any of the blocks coming back are not finalized, an error will be returned func (lp *logPoller) fillRemainingBlocksFromRPC( ctx context.Context, blocksRequested map[uint64]struct{}, blocksFound map[uint64]LogPollerBlock, ) (map[uint64]LogPollerBlock, error) { var remainingBlocks []string + for num := range blocksRequested { if _, ok := blocksFound[num]; !ok { remainingBlocks = append(remainingBlocks, hexutil.EncodeBig(new(big.Int).SetUint64(num))) @@ -1287,54 +1296,126 @@ func (lp *logPoller) fillRemainingBlocksFromRPC( return logPollerBlocks, nil } -func (lp *logPoller) batchFetchBlocks(ctx context.Context, blocksRequested []string, batchSize int64) ([]*evmtypes.Head, error) { - reqs := make([]rpc.BatchElem, 0, len(blocksRequested)) - for _, num := range blocksRequested { - req := rpc.BatchElem{ - Method: "eth_getBlockByNumber", - Args: []interface{}{num, false}, - Result: &evmtypes.Head{}, - } - reqs = append(reqs, req) +// newBlockReq constructs an eth_getBlockByNumber request for particular block number +func newBlockReq(num string) rpc.BatchElem { + return rpc.BatchElem{ + Method: "eth_getBlockByNumber", + Args: []interface{}{num, false}, + Result: &evmtypes.Head{}, } +} - for i := 0; i < len(reqs); i += int(batchSize) { - j := i + int(batchSize) - if j > len(reqs) { - j = len(reqs) - } +type blockValidationType string - err := lp.ec.BatchCallContext(ctx, reqs[i:j]) - if err != nil { - return nil, err +var ( + latestBlock blockValidationType = blockValidationType(rpc.LatestBlockNumber.String()) + finalizedBlock blockValidationType = blockValidationType(rpc.FinalizedBlockNumber.String()) +) + +// fetchBlocks fetches a list of blocks in a single batch. validationReq is the string to use for the +// additional validation request (either the "finalized" or "latest" string defined in rpc module), which +// will be used to validate the finality of the other blocks. +func (lp *logPoller) fetchBlocks(ctx context.Context, blocksRequested []string, validationReq blockValidationType) (blocks []*evmtypes.Head, err error) { + n := len(blocksRequested) + blocks = make([]*evmtypes.Head, 0, n+1) + reqs := make([]rpc.BatchElem, 0, n+1) + + validationBlockIndex := n + for k, num := range blocksRequested { + if num == string(validationReq) { + validationBlockIndex = k } + reqs = append(reqs, newBlockReq(num)) } - var blocks = make([]*evmtypes.Head, 0, len(reqs)) - for _, r := range reqs { - if r.Error != nil { - return nil, r.Error + if validationBlockIndex == n { + // Add validation req if it wasn't in there already + reqs = append(reqs, newBlockReq(string(validationReq))) + } + + err = lp.ec.BatchCallContext(ctx, reqs) + if err != nil { + return nil, err + } + + validationBlock, err := validateBlockResponse(reqs[validationBlockIndex]) + if err != nil { + return nil, err + } + latestFinalizedBlockNumber := validationBlock.Number + if validationReq == latestBlock { + // subtract finalityDepth from "latest" to get finalized, when useFinalityTags = false + latestFinalizedBlockNumber = mathutil.Max(latestFinalizedBlockNumber-lp.finalityDepth, 0) + } + if len(reqs) == n+1 { + reqs = reqs[:n] // ignore last req if we added it explicitly for validation + } + + for k, r := range reqs { + if k == validationBlockIndex { + // Already validated this one, just insert it in proper place + blocks = append(blocks, validationBlock) + continue } - block, is := r.Result.(*evmtypes.Head) - if !is { - return nil, pkgerrors.Errorf("expected result to be a %T, got %T", &evmtypes.Head{}, r.Result) + block, err2 := validateBlockResponse(r) + if err2 != nil { + return nil, err2 } - if block == nil { - return nil, pkgerrors.New("invariant violation: got nil block") + + blockRequested := r.Args[0].(string) + if blockRequested != string(latestBlock) && block.Number > latestFinalizedBlockNumber { + return nil, fmt.Errorf( + "Received unfinalized block %d while expecting finalized block (latestFinalizedBlockNumber = %d)", + block.Number, latestFinalizedBlockNumber) } - if block.Hash == (common.Hash{}) { - return nil, pkgerrors.Errorf("missing block hash for block number: %d", block.Number) + + blocks = append(blocks, block) + } + return blocks, nil +} + +func (lp *logPoller) batchFetchBlocks(ctx context.Context, blocksRequested []string, batchSize int64) ([]*evmtypes.Head, error) { + var blocks = make([]*evmtypes.Head, 0, len(blocksRequested)+1) + + validationReq := finalizedBlock + if !lp.useFinalityTag { + validationReq = latestBlock + } + + for i := 0; i < len(blocksRequested); i += int(batchSize) { + j := i + int(batchSize) + if j > len(blocksRequested) { + j = len(blocksRequested) } - if block.Number < 0 { - return nil, pkgerrors.Errorf("expected block number to be >= to 0, got %d", block.Number) + moreBlocks, err := lp.fetchBlocks(ctx, blocksRequested[i:j], validationReq) + if err != nil { + return nil, err } - blocks = append(blocks, block) + blocks = append(blocks, moreBlocks...) } return blocks, nil } +func validateBlockResponse(r rpc.BatchElem) (*evmtypes.Head, error) { + block, is := r.Result.(*evmtypes.Head) + + if !is { + return nil, pkgerrors.Errorf("expected result to be a %T, got %T", &evmtypes.Head{}, r.Result) + } + if block == nil { + return nil, pkgerrors.New("invariant violation: got nil block") + } + if block.Hash == (common.Hash{}) { + return nil, pkgerrors.Errorf("missing block hash for block number: %d", block.Number) + } + if block.Number < 0 { + return nil, pkgerrors.Errorf("expected block number to be >= to 0, got %d", block.Number) + } + return block, nil +} + // IndexedLogsWithSigsExcluding returns the set difference(A-B) of logs with signature sigA and sigB, matching is done on the topics index // // For example, query to retrieve unfulfilled requests by querying request log events without matching fulfillment log events. @@ -1343,6 +1424,103 @@ func (lp *logPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address c return lp.orm.SelectIndexedLogsWithSigsExcluding(ctx, eventSigA, eventSigB, topicIndex, address, fromBlock, toBlock, confs) } +// DeleteLogsAndBlocksAfter - removes blocks and logs starting from the specified block +func (lp *logPoller) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { + return lp.orm.DeleteLogsAndBlocksAfter(ctx, start) +} + +func (lp *logPoller) FindLCA(ctx context.Context) (*LogPollerBlock, error) { + latest, err := lp.orm.SelectLatestBlock(ctx) + if err != nil { + return nil, fmt.Errorf("failed to select the latest block: %w", err) + } + + oldest, err := lp.orm.SelectOldestBlock(ctx, 0) + if err != nil { + return nil, fmt.Errorf("failed to select the oldest block: %w", err) + } + + if latest == nil || oldest == nil { + return nil, fmt.Errorf("expected at least one block to be present in DB") + } + + lp.lggr.Debugf("Received request to find LCA. Searching in range [%d, %d]", oldest.BlockNumber, latest.BlockNumber) + + // Find the largest block number for which block hash stored in the DB matches one that we get from the RPC. + // `sort.Find` expects slice of following format s = [1, 0, -1] and returns smallest index i for which s[i] = 0. + // To utilise `sort.Find` we represent range of blocks as slice [latestBlock, latestBlock-1, ..., olderBlock+1, oldestBlock] + // and return 1 if DB block was reorged or 0 if it's still present on chain. + lcaI, found := sort.Find(int(latest.BlockNumber-oldest.BlockNumber)+1, func(i int) int { + const notFound = 1 + const found = 0 + // if there is an error - stop the search + if err != nil { + return notFound + } + + // canceled search + if ctx.Err() != nil { + err = fmt.Errorf("aborted, FindLCA request cancelled: %w", ctx.Err()) + return notFound + } + iBlockNumber := latest.BlockNumber - int64(i) + var dbBlock *LogPollerBlock + // Block with specified block number might not exist in the database, to address that we check closest child + // of the iBlockNumber. If the child is present on chain, it's safe to assume that iBlockNumber is present too + dbBlock, err = lp.orm.SelectOldestBlock(ctx, iBlockNumber) + if err != nil { + err = fmt.Errorf("failed to select block %d by number: %w", iBlockNumber, err) + return notFound + } + + if dbBlock == nil { + err = fmt.Errorf("expected block to exist with blockNumber >= %d as observed block with number %d", iBlockNumber, latest.BlockNumber) + return notFound + } + + lp.lggr.Debugf("Looking for matching block on chain blockNumber: %d blockHash: %s", + dbBlock.BlockNumber, dbBlock.BlockHash) + var chainBlock *evmtypes.Head + chainBlock, err = lp.ec.HeadByHash(ctx, dbBlock.BlockHash) + // our block in DB does not exist on chain + if (chainBlock == nil && err == nil) || errors.Is(err, ethereum.NotFound) { + err = nil + return notFound + } + if err != nil { + err = fmt.Errorf("failed to get block %s from RPC: %w", dbBlock.BlockHash, err) + return notFound + } + + if chainBlock.BlockNumber() != dbBlock.BlockNumber { + err = fmt.Errorf("expected block numbers to match (db: %d, chain: %d), if block hashes match "+ + "(db: %s, chain: %s)", dbBlock.BlockNumber, chainBlock.BlockNumber(), dbBlock.BlockHash, chainBlock.Hash) + return notFound + } + + return found + }) + if err != nil { + return nil, fmt.Errorf("failed to find: %w", err) + } + + if !found { + return nil, fmt.Errorf("failed to find LCA, this means that whole database LogPoller state was reorged out of chain or RPC/Core node is misconfigured") + } + + lcaBlockNumber := latest.BlockNumber - int64(lcaI) + lca, err := lp.orm.SelectBlockByNumber(ctx, lcaBlockNumber) + if err != nil { + return nil, fmt.Errorf("failed to select lca from db: %w", err) + } + + if lca == nil { + return nil, fmt.Errorf("expected lca (blockNum: %d) to exist in DB", lcaBlockNumber) + } + + return lca, nil +} + func EvmWord(i uint64) common.Hash { var b = make([]byte, 8) binary.BigEndian.PutUint64(b, i) diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index b6af0f7de5c..4236f0b8ef1 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -2,6 +2,7 @@ package logpoller import ( "context" + "errors" "fmt" "math/big" "reflect" @@ -12,6 +13,7 @@ import ( "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/core/types" "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" @@ -205,13 +207,14 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { chainID := testutils.FixtureChainID db := pgtest.NewSqlxDB(t) orm := NewORM(chainID, db, lggr) + latestBlock := int64(4) - head := evmtypes.Head{Number: 3} + head := evmtypes.Head{Number: latestBlock} events := []common.Hash{EmitterABI.Events["Log1"].ID} log1 := types.Log{ Index: 0, BlockHash: common.Hash{}, - BlockNumber: uint64(3), + BlockNumber: uint64(latestBlock), Topics: events, Address: addr, TxHash: common.HexToHash("0x1234"), @@ -230,20 +233,44 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { BackfillBatchSize: 3, RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, + BackupPollerBlockDelay: 0, } lp := NewLogPoller(orm, ec, lggr, lpOpts) lp.BackupPollAndSaveLogs(ctx) assert.Equal(t, int64(0), lp.backupPollerNextBlock) assert.Equal(t, 1, observedLogs.FilterMessageSnippet("ran before first successful log poller run").Len()) - lp.PollAndSaveLogs(ctx, 3) + lp.PollAndSaveLogs(ctx, latestBlock) lastProcessed, err := lp.orm.SelectLatestBlock(ctx) require.NoError(t, err) - require.Equal(t, int64(3), lastProcessed.BlockNumber) + require.Equal(t, latestBlock, lastProcessed.BlockNumber) lp.BackupPollAndSaveLogs(ctx) - assert.Equal(t, int64(1), lp.backupPollerNextBlock) // Ensure non-negative! + assert.Equal(t, int64(2), lp.backupPollerNextBlock) +} + +func mockBatchCallContext(t *testing.T, ec *evmclimocks.Client) { + ec.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + for _, e := range elems { + var num int64 + block := e.Args[0].(string) + switch block { + case "latest": + num = 8 + case "finalized": + num = 5 + default: + n, err := hexutil.DecodeUint64(block) + require.NoError(t, err) + num = int64(n) + } + result := e.Result.(*evmtypes.Head) + *result = evmtypes.Head{Number: num, Hash: utils.NewHash()} + + } + }) } func TestLogPoller_Replay(t *testing.T) { @@ -269,16 +296,20 @@ func TestLogPoller_Replay(t *testing.T) { } ec := evmclimocks.NewClient(t) - ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(&head, nil) - ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Twice() + ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(context.Context, *big.Int) (*evmtypes.Head, error) { + headCopy := head + return &headCopy, nil + }) + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Once() ec.On("ConfiguredChainID").Return(chainID, nil) + lpOpts := Opts{ - PollPeriod: time.Hour, + PollPeriod: time.Second, FinalityDepth: 3, BackfillBatchSize: 3, RpcBatchSize: 3, KeepFinalizedBlocksDepth: 20, - BackupPollerBlockDelay: 100, + BackupPollerBlockDelay: 0, } lp := NewLogPoller(orm, ec, lggr, lpOpts) @@ -308,6 +339,8 @@ func TestLogPoller_Replay(t *testing.T) { // Replay() should return error code received from replayComplete t.Run("returns error code on replay complete", func(t *testing.T) { + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Once() + mockBatchCallContext(t, ec) anyErr := pkgerrors.New("any error") done := make(chan struct{}) go func() { @@ -345,6 +378,7 @@ func TestLogPoller_Replay(t *testing.T) { var wg sync.WaitGroup defer func() { wg.Wait() }() ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) { + head = evmtypes.Head{Number: 4} wg.Add(1) go func() { defer wg.Done() @@ -371,6 +405,7 @@ func TestLogPoller_Replay(t *testing.T) { ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Maybe() // in case task gets delayed by >= 100ms + head = evmtypes.Head{Number: 5} t.Cleanup(lp.reset) servicetest.Run(t, lp) @@ -395,6 +430,8 @@ func TestLogPoller_Replay(t *testing.T) { ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) { go func() { defer close(done) + + head = evmtypes.Head{Number: 4} // Restore latest block to 4, so this matches the fromBlock requested select { case lp.replayStart <- 4: case <-ctx.Done(): @@ -405,9 +442,10 @@ func TestLogPoller_Replay(t *testing.T) { lp.cancel() close(pass) }) - ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Maybe() // in case task gets delayed by >= 100ms + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) t.Cleanup(lp.reset) + head = evmtypes.Head{Number: 5} // Latest block must be > lastProcessed in order for SaveAndPollLogs() to call FilterLogs() servicetest.Run(t, lp) select { @@ -420,6 +458,9 @@ func TestLogPoller_Replay(t *testing.T) { // ReplayAsync should return as soon as replayStart is received t.Run("ReplayAsync success", func(t *testing.T) { t.Cleanup(lp.reset) + head = evmtypes.Head{Number: 5} + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) + mockBatchCallContext(t, ec) servicetest.Run(t, lp) lp.ReplayAsync(1) @@ -430,6 +471,7 @@ func TestLogPoller_Replay(t *testing.T) { t.Run("ReplayAsync error", func(t *testing.T) { t.Cleanup(lp.reset) servicetest.Run(t, lp) + head = evmtypes.Head{Number: 4} anyErr := pkgerrors.New("async error") observedLogs.TakeAll() @@ -462,6 +504,9 @@ func TestLogPoller_Replay(t *testing.T) { err = lp.orm.InsertBlock(ctx, head.Hash, head.Number, head.Timestamp, head.Number) require.NoError(t, err) + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) + mockBatchCallContext(t, ec) + err = lp.Replay(ctx, 1) require.NoError(t, err) }) @@ -554,6 +599,77 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) { }) } +func Test_FetchBlocks(t *testing.T) { + lggr := logger.Test(t) + chainID := testutils.FixtureChainID + db := pgtest.NewSqlxDB(t) + orm := NewORM(chainID, db, lggr) + ctx := testutils.Context(t) + + lpOpts := Opts{ + PollPeriod: time.Hour, + BackfillBatchSize: 2, + RpcBatchSize: 2, + KeepFinalizedBlocksDepth: 50, + FinalityDepth: 3, + } + + ec := evmclimocks.NewClient(t) + mockBatchCallContext(t, ec) // This will return 5 for "finalized" and 8 for "latest" + + cases := []struct { + name string + blocksRequested []string + expectedErr error + }{{ + "successful validation including finalized and latest", + []string{"0x3", "latest", "0x5", "finalized", "0x1"}, + nil, + }, { + "successful validation with all block numbers", + []string{"0x2", "0x5", "0x3", "0x4"}, + nil, + }, { + "finality violation including finalized and latest", + []string{"0x8", "0x2", "latest", "finalized"}, + errors.New("Received unfinalized block 8 while expecting finalized block (latestFinalizedBlockNumber = 5)"), + }, { + "finality violation with all block numbers", + []string{"0x9", "0x2", "finalized", "latest"}, + errors.New("Received unfinalized block 9 while expecting finalized block (latestFinalizedBlockNumber = 5)"), + }} + + lp := NewLogPoller(orm, ec, lggr, lpOpts) + for _, tc := range cases { + for _, lp.useFinalityTag = range []bool{false, true} { + blockValidationReq := latestBlock + if lp.useFinalityTag { + blockValidationReq = finalizedBlock + } + t.Run(fmt.Sprintf("%s where useFinalityTag=%t", tc.name, lp.useFinalityTag), func(t *testing.T) { + blocks, err := lp.fetchBlocks(ctx, tc.blocksRequested, blockValidationReq) + if tc.expectedErr != nil { + require.Equal(t, err.Error(), tc.expectedErr.Error()) + return // PASS + } + require.NoError(t, err) + for i, blockRequested := range tc.blocksRequested { + switch blockRequested { + case string(latestBlock): + assert.Equal(t, int64(8), blocks[i].Number) + case string(finalizedBlock): + assert.Equal(t, int64(5), blocks[i].Number) + default: + blockNum, err2 := hexutil.DecodeUint64(blockRequested) + require.NoError(t, err2) + assert.Equal(t, int64(blockNum), blocks[i].Number) + } + } + }) + } + } +} + func benchmarkFilter(b *testing.B, nFilters, nAddresses, nEvents int) { lggr := logger.Test(b) lpOpts := Opts{ diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 2096ccf3cf4..cb211043a4c 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -545,8 +545,6 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) BackupPollerBlockDelay: 1, } th := SetupTH(t, lpOpts) - //header, err := th.Client.HeaderByNumber(ctx, nil) - //require.NoError(t, err) // Emit some logs in blocks for i := 1; i <= logsBatch; i++ { @@ -559,7 +557,7 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) // 1 -> 2 -> ... -> firstBatchBlock firstBatchBlock := th.PollAndSaveLogs(ctx, 1) // Mark current tip of the chain as finalized (after emitting 10 logs) - markBlockAsFinalized(t, th, firstBatchBlock) + markBlockAsFinalized(t, th, firstBatchBlock-1) // Emit 2nd batch of block for i := 1; i <= logsBatch; i++ { @@ -571,7 +569,7 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) // 1 -> 2 -> ... -> firstBatchBlock (finalized) -> .. -> firstBatchBlock + emitted logs secondBatchBlock := th.PollAndSaveLogs(ctx, firstBatchBlock) // Mark current tip of the block as finalized (after emitting 20 logs) - markBlockAsFinalized(t, th, secondBatchBlock) + markBlockAsFinalized(t, th, secondBatchBlock-1) // Register filter err := th.LogPoller.RegisterFilter(ctx, logpoller.Filter{ @@ -595,8 +593,8 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) th.EmitterAddress1, ) require.NoError(t, err) - require.Len(t, logs, logsBatch+1) - require.Equal(t, hexutil.MustDecode(`0x0000000000000000000000000000000000000000000000000000000000000009`), logs[0].Data) + require.Len(t, logs, logsBatch) + require.Equal(t, hexutil.MustDecode(`0x000000000000000000000000000000000000000000000000000000000000000a`), logs[0].Data) } func TestLogPoller_BlockTimestamps(t *testing.T) { @@ -676,6 +674,7 @@ func TestLogPoller_BlockTimestamps(t *testing.T) { require.NoError(t, err) // Logs should have correct timestamps + require.NotZero(t, len(lg1)) b, _ := th.Client.BlockByHash(ctx, lg1[0].BlockHash) t.Log(len(lg1), lg1[0].BlockTimestamp) assert.Equal(t, int64(b.Time()), lg1[0].BlockTimestamp.UTC().Unix(), time1) @@ -1181,6 +1180,7 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { // Check that L1_1 has a proper data payload lgs, err := th.ORM.SelectLogsByBlockRange(testutils.Context(t), 2, 2) require.NoError(t, err) + require.NotZero(t, len(lgs)) assert.Equal(t, hexutil.MustDecode(`0x0000000000000000000000000000000000000000000000000000000000000001`), lgs[0].Data) // Single block reorg and log poller not working for a while, mine blocks and progress with finalization @@ -1208,6 +1208,7 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { // Expect L1_2 to be properly updated lgs, err = th.ORM.SelectLogsByBlockRange(testutils.Context(t), 2, 2) require.NoError(t, err) + require.NotZero(t, len(lgs)) assert.Equal(t, hexutil.MustDecode(`0x0000000000000000000000000000000000000000000000000000000000000002`), lgs[0].Data) th.assertHaveCanonical(t, 1, 1) th.assertDontHave(t, 2, 3) // These blocks are backfilled @@ -1301,6 +1302,7 @@ func TestLogPoller_LoadFilters(t *testing.T) { func TestLogPoller_GetBlocks_Range(t *testing.T) { t.Parallel() + lpOpts := logpoller.Opts{ UseFinalityTag: false, FinalityDepth: 2, @@ -1310,7 +1312,15 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { } th := SetupTH(t, lpOpts) - err := th.LogPoller.RegisterFilter(testutils.Context(t), logpoller.Filter{ + _, err := th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(1)}) + require.NoError(t, err) + th.Client.Commit() // Commit block #2 with log in it + + _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(2)}) + require.NoError(t, err) + th.Client.Commit() // Commit block #3 with a different log + + err = th.LogPoller.RegisterFilter(testutils.Context(t), logpoller.Filter{ Name: "GetBlocks Test", EventSigs: []common.Hash{EmitterABI.Events["Log1"].ID, EmitterABI.Events["Log2"].ID}, Addresses: []common.Address{th.EmitterAddress1, th.EmitterAddress2}, @@ -1330,16 +1340,13 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { assert.Equal(t, 1, len(blocks)) assert.Equal(t, 1, int(blocks[0].BlockNumber)) - // LP fails to retrieve block 2 because it's neither in DB nor returned by RPC + // LP fails to return block 2 because it hasn't been finalized yet blockNums = []uint64{2} _, err = th.LogPoller.GetBlocksRange(testutils.Context(t), blockNums) require.Error(t, err) - assert.Equal(t, "blocks were not found in db or RPC call: [2]", err.Error()) + assert.Equal(t, "Received unfinalized block 2 while expecting finalized block (latestFinalizedBlockNumber = 1)", err.Error()) - // Emit a log and mine block #2 - _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(1)}) - require.NoError(t, err) - th.Client.Commit() + th.Client.Commit() // Commit block #4, so that block #2 is finalized // Assert block 2 is not yet in DB _, err = th.ORM.SelectBlockByNumber(testutils.Context(t), 2) @@ -1351,10 +1358,7 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { assert.Equal(t, 1, len(rpcBlocks)) assert.Equal(t, 2, int(rpcBlocks[0].BlockNumber)) - // Emit a log and mine block #3 - _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(2)}) - require.NoError(t, err) - th.Client.Commit() + th.Client.Commit() // commit block #5 so that #3 becomes finalized // Assert block 3 is not yet in DB _, err = th.ORM.SelectBlockByNumber(testutils.Context(t), 3) @@ -1368,12 +1372,9 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { assert.Equal(t, 1, int(rpcBlocks2[0].BlockNumber)) assert.Equal(t, 3, int(rpcBlocks2[1].BlockNumber)) - // after calling PollAndSaveLogs, block 2 & 3 are persisted in DB + // after calling PollAndSaveLogs, block 3 (latest finalized block) is persisted in DB th.LogPoller.PollAndSaveLogs(testutils.Context(t), 1) - block, err := th.ORM.SelectBlockByNumber(testutils.Context(t), 2) - require.NoError(t, err) - assert.Equal(t, 2, int(block.BlockNumber)) - block, err = th.ORM.SelectBlockByNumber(testutils.Context(t), 3) + block, err := th.ORM.SelectBlockByNumber(testutils.Context(t), 3) require.NoError(t, err) assert.Equal(t, 3, int(block.BlockNumber)) @@ -1507,9 +1508,9 @@ func TestLogPoller_DBErrorHandling(t *testing.T) { time.Sleep(100 * time.Millisecond) require.NoError(t, lp.Start(ctx)) - require.Eventually(t, func() bool { + testutils.AssertEventually(t, func() bool { return observedLogs.Len() >= 1 - }, 2*time.Second, 20*time.Millisecond) + }) err = lp.Close() require.NoError(t, err) @@ -1920,3 +1921,119 @@ func markBlockAsFinalizedByHash(t *testing.T, th TestHarness, blockHash common.H require.NoError(t, err) th.Client.Blockchain().SetFinalized(b.Header()) } + +func TestFindLCA(t *testing.T) { + ctx := testutils.Context(t) + ec := evmtest.NewEthClientMockWithDefaultChain(t) + lggr := logger.Test(t) + chainID := testutils.NewRandomEVMChainID() + db := pgtest.NewSqlxDB(t) + + orm := logpoller.NewORM(chainID, db, lggr) + + lpOpts := logpoller.Opts{ + PollPeriod: time.Hour, + FinalityDepth: 2, + BackfillBatchSize: 20, + RpcBatchSize: 10, + KeepFinalizedBlocksDepth: 1000, + } + + lp := logpoller.NewLogPoller(orm, ec, lggr, lpOpts) + t.Run("Fails, if failed to select oldest block", func(t *testing.T) { + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, "failed to select the latest block") + }) + // oldest + require.NoError(t, orm.InsertBlock(ctx, common.HexToHash("0x123"), 10, time.Now(), 0)) + // latest + latestBlockHash := common.HexToHash("0x124") + require.NoError(t, orm.InsertBlock(ctx, latestBlockHash, 16, time.Now(), 0)) + t.Run("Fails, if caller's context canceled", func(t *testing.T) { + lCtx, cancel := context.WithCancel(ctx) + ec.On("HeadByHash", mock.Anything, latestBlockHash).Return(nil, nil).Run(func(_ mock.Arguments) { + cancel() + }).Once() + _, err := lp.FindLCA(lCtx) + require.ErrorContains(t, err, "aborted, FindLCA request cancelled") + + }) + t.Run("Fails, if RPC returns an error", func(t *testing.T) { + expectedError := fmt.Errorf("failed to call RPC") + ec.On("HeadByHash", mock.Anything, latestBlockHash).Return(nil, expectedError).Once() + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, expectedError.Error()) + }) + t.Run("Fails, if block numbers do not match", func(t *testing.T) { + ec.On("HeadByHash", mock.Anything, latestBlockHash).Return(&evmtypes.Head{ + Number: 123, + }, nil).Once() + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, "expected block numbers to match") + }) + t.Run("Fails, if none of the blocks in db matches on chain", func(t *testing.T) { + ec.On("HeadByHash", mock.Anything, mock.Anything).Return(nil, nil).Times(3) + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, "failed to find LCA, this means that whole database LogPoller state was reorged out of chain or RPC/Core node is misconfigured") + }) + + type block struct { + BN int + Exists bool + } + testCases := []struct { + Name string + Blocks []block + ExpectedBlockNumber int + ExpectedError error + }{ + { + Name: "All of the blocks are present on chain - returns the latest", + Blocks: []block{{BN: 1, Exists: true}, {BN: 2, Exists: true}, {BN: 3, Exists: true}, {BN: 4, Exists: true}}, + ExpectedBlockNumber: 4, + }, + { + Name: "None of the blocks exists on chain - returns an erro", + Blocks: []block{{BN: 1, Exists: false}, {BN: 2, Exists: false}, {BN: 3, Exists: false}, {BN: 4, Exists: false}}, + ExpectedBlockNumber: 0, + ExpectedError: fmt.Errorf("failed to find LCA, this means that whole database LogPoller state was reorged out of chain or RPC/Core node is misconfigured"), + }, + { + Name: "Only latest block does not exist", + Blocks: []block{{BN: 1, Exists: true}, {BN: 2, Exists: true}, {BN: 3, Exists: true}, {BN: 4, Exists: false}}, + ExpectedBlockNumber: 3, + }, + { + Name: "Only oldest block exists on chain", + Blocks: []block{{BN: 1, Exists: true}, {BN: 2, Exists: false}, {BN: 3, Exists: false}, {BN: 4, Exists: false}}, + ExpectedBlockNumber: 1, + }, + } + + blockHashI := int64(0) + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + // reset the database + require.NoError(t, orm.DeleteLogsAndBlocksAfter(ctx, 0)) + for _, b := range tc.Blocks { + blockHashI++ + hash := common.BigToHash(big.NewInt(blockHashI)) + require.NoError(t, orm.InsertBlock(ctx, hash, int64(b.BN), time.Now(), 0)) + // Hashes are unique for all test cases + var onChainBlock *evmtypes.Head + if b.Exists { + onChainBlock = &evmtypes.Head{Number: int64(b.BN)} + } + ec.On("HeadByHash", mock.Anything, hash).Return(onChainBlock, nil).Maybe() + } + + result, err := lp.FindLCA(ctx) + if tc.ExpectedError != nil { + require.ErrorContains(t, err, tc.ExpectedError.Error()) + } else { + require.NotNil(t, result) + require.Equal(t, result.BlockNumber, int64(tc.ExpectedBlockNumber), "expected block numbers to match") + } + }) + } +} diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go index 548e9ca3b90..ef3f4dbd428 100644 --- a/core/chains/evm/logpoller/mocks/log_poller.go +++ b/core/chains/evm/logpoller/mocks/log_poller.go @@ -37,6 +37,54 @@ func (_m *LogPoller) Close() error { return r0 } +// DeleteLogsAndBlocksAfter provides a mock function with given fields: ctx, start +func (_m *LogPoller) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { + ret := _m.Called(ctx, start) + + if len(ret) == 0 { + panic("no return value specified for DeleteLogsAndBlocksAfter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, start) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// FindLCA provides a mock function with given fields: ctx +func (_m *LogPoller) FindLCA(ctx context.Context) (*logpoller.LogPollerBlock, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for FindLCA") + } + + var r0 *logpoller.LogPollerBlock + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*logpoller.LogPollerBlock, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *logpoller.LogPollerBlock); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logpoller.LogPollerBlock) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetBlocksRange provides a mock function with given fields: ctx, numbers func (_m *LogPoller) GetBlocksRange(ctx context.Context, numbers []uint64) ([]logpoller.LogPollerBlock, error) { ret := _m.Called(ctx, numbers) diff --git a/core/chains/evm/logpoller/observability.go b/core/chains/evm/logpoller/observability.go index 07a0f58ce78..8f3cdfe185e 100644 --- a/core/chains/evm/logpoller/observability.go +++ b/core/chains/evm/logpoller/observability.go @@ -76,9 +76,9 @@ type ObservedORM struct { // NewObservedORM creates an observed version of log poller's ORM created by NewORM // Please see ObservedLogPoller for more details on how latencies are measured -func NewObservedORM(chainID *big.Int, db sqlutil.DataSource, lggr logger.Logger) *ObservedORM { +func NewObservedORM(chainID *big.Int, ds sqlutil.DataSource, lggr logger.Logger) *ObservedORM { return &ObservedORM{ - ORM: NewORM(chainID, db, lggr), + ORM: NewORM(chainID, ds, lggr), queryDuration: lpQueryDuration, datasetSize: lpQueryDataSets, logsInserted: lpLogsInserted, @@ -151,6 +151,12 @@ func (o *ObservedORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, e }) } +func (o *ObservedORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) { + return withObservedQuery(o, "SelectOldestBlock", func() (*LogPollerBlock, error) { + return o.ORM.SelectOldestBlock(ctx, minAllowedBlockNumber) + }) +} + func (o *ObservedORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { return withObservedQuery(o, "SelectLatestLogByEventSigWithConfs", func() (*Log, error) { return o.ORM.SelectLatestLogByEventSigWithConfs(ctx, eventSig, address, confs) diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index ebba3cffc08..5e0a74a9183 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -38,6 +38,7 @@ type ORM interface { SelectBlockByNumber(ctx context.Context, blockNumber int64) (*LogPollerBlock, error) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) + SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) SelectLogs(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash) ([]Log, error) SelectLogsWithSigs(ctx context.Context, start, end int64, address common.Address, eventSigs []common.Hash) ([]Log, error) @@ -59,32 +60,32 @@ type ORM interface { SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) } -type DbORM struct { +type DSORM struct { chainID *big.Int - db sqlutil.DataSource + ds sqlutil.DataSource lggr logger.Logger } -var _ ORM = &DbORM{} +var _ ORM = &DSORM{} -// NewORM creates an DbORM scoped to chainID. -func NewORM(chainID *big.Int, db sqlutil.DataSource, lggr logger.Logger) *DbORM { - return &DbORM{ +// NewORM creates an DSORM scoped to chainID. +func NewORM(chainID *big.Int, ds sqlutil.DataSource, lggr logger.Logger) *DSORM { + return &DSORM{ chainID: chainID, - db: db, + ds: ds, lggr: lggr, } } -func (o *DbORM) Transaction(ctx context.Context, fn func(*DbORM) error) (err error) { - return sqlutil.Transact(ctx, o.new, o.db, nil, fn) +func (o *DSORM) Transact(ctx context.Context, fn func(*DSORM) error) (err error) { + return sqlutil.Transact(ctx, o.new, o.ds, nil, fn) } -// new returns a NewORM like o, but backed by q. -func (o *DbORM) new(q sqlutil.DataSource) *DbORM { return NewORM(o.chainID, q, o.lggr) } +// new returns a NewORM like o, but backed by ds. +func (o *DSORM) new(ds sqlutil.DataSource) *DSORM { return NewORM(o.chainID, ds, o.lggr) } // InsertBlock is idempotent to support replays. -func (o *DbORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNumber int64, blockTimestamp time.Time, finalizedBlock int64) error { +func (o *DSORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNumber int64, blockTimestamp time.Time, finalizedBlock int64) error { args, err := newQueryArgs(o.chainID). withCustomHashArg("block_hash", blockHash). withCustomArg("block_number", blockNumber). @@ -98,12 +99,7 @@ func (o *DbORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNum (evm_chain_id, block_hash, block_number, block_timestamp, finalized_block_number, created_at) VALUES (:evm_chain_id, :block_hash, :block_number, :block_timestamp, :finalized_block_number, NOW()) ON CONFLICT DO NOTHING` - query, sqlArgs, err := o.db.BindNamed(query, args) - if err != nil { - return err - } - - _, err = o.db.ExecContext(ctx, query, sqlArgs...) + _, err = o.ds.NamedExecContext(ctx, query, args) return err } @@ -111,7 +107,7 @@ func (o *DbORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNum // // Each address/event pair must have a unique job id, so it may be removed when the job is deleted. // If a second job tries to overwrite the same pair, this should fail. -func (o *DbORM) InsertFilter(ctx context.Context, filter Filter) (err error) { +func (o *DSORM) InsertFilter(ctx context.Context, filter Filter) (err error) { topicArrays := []types.HashArray{filter.Topic2, filter.Topic3, filter.Topic4} args, err := newQueryArgs(o.chainID). withCustomArg("name", filter.Name). @@ -148,18 +144,13 @@ func (o *DbORM) InsertFilter(ctx context.Context, filter Filter) (err error) { topicsColumns.String(), topicsSql.String()) - query, sqlArgs, err := o.db.BindNamed(query, args) - if err != nil { - return err - } - - _, err = o.db.ExecContext(ctx, query, sqlArgs...) + _, err = o.ds.NamedExecContext(ctx, query, args) return err } // DeleteFilter removes all events,address pairs associated with the Filter -func (o *DbORM) DeleteFilter(ctx context.Context, name string) error { - _, err := o.db.ExecContext(ctx, +func (o *DSORM) DeleteFilter(ctx context.Context, name string) error { + _, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_filters WHERE name = $1 AND evm_chain_id = $2`, name, ubig.New(o.chainID)) return err @@ -167,7 +158,7 @@ func (o *DbORM) DeleteFilter(ctx context.Context, name string) error { } // LoadFilters returns all filters for this chain -func (o *DbORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { +func (o *DSORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { query := `SELECT name, ARRAY_AGG(DISTINCT address)::BYTEA[] AS addresses, ARRAY_AGG(DISTINCT event)::BYTEA[] AS event_sigs, @@ -180,7 +171,7 @@ func (o *DbORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { FROM evm.log_poller_filters WHERE evm_chain_id = $1 GROUP BY name` var rows []Filter - err := o.db.SelectContext(ctx, &rows, query, ubig.New(o.chainID)) + err := o.ds.SelectContext(ctx, &rows, query, ubig.New(o.chainID)) filters := make(map[string]Filter) for _, filter := range rows { filters[filter.Name] = filter @@ -188,31 +179,39 @@ func (o *DbORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { return filters, err } -func (o *DbORM) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) { +func (o *DSORM) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.db.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, hash.Bytes(), ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, hash.Bytes(), ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil } -func (o *DbORM) SelectBlockByNumber(ctx context.Context, n int64) (*LogPollerBlock, error) { +func (o *DSORM) SelectBlockByNumber(ctx context.Context, n int64) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.db.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil } -func (o *DbORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) { +func (o *DSORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.db.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil } -func (o *DbORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { +func (o *DSORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) { + var b LogPollerBlock + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 AND block_number >= $2 ORDER BY block_number ASC LIMIT 1`, ubig.New(o.chainID), minAllowedBlockNumber); err != nil { + return nil, err + } + return &b, nil +} + +func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withConfs(confs). toArgs() @@ -228,11 +227,11 @@ func (o *DbORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig ORDER BY (block_number, log_index) DESC LIMIT 1`, nestedBlockNumberQuery(confs)) var l Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err = o.db.GetContext(ctx, &l, query, sqlArgs...); err != nil { + if err = o.ds.GetContext(ctx, &l, query, sqlArgs...); err != nil { return nil, err } return &l, nil @@ -240,9 +239,9 @@ func (o *DbORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig // DeleteBlocksBefore delete blocks before and including end. When limit is set, it will delete at most limit blocks. // Otherwise, it will delete all blocks at once. -func (o *DbORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) (int64, error) { +func (o *DSORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) (int64, error) { if limit > 0 { - result, err := o.db.ExecContext(ctx, + result, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE block_number IN ( SELECT block_number FROM evm.log_poller_blocks @@ -257,7 +256,7 @@ func (o *DbORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) } return result.RowsAffected() } - result, err := o.db.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks + result, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE block_number <= $1 AND evm_chain_id = $2`, end, ubig.New(o.chainID)) if err != nil { return 0, err @@ -265,16 +264,16 @@ func (o *DbORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) return result.RowsAffected() } -func (o *DbORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { +func (o *DSORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { // These deletes are bounded by reorg depth, so they are // fast and should not slow down the log readers. - return o.Transaction(ctx, func(orm *DbORM) error { + return o.Transact(ctx, func(orm *DSORM) error { // Applying upper bound filter is critical for Postgres performance (especially for evm.logs table) // because it allows the planner to properly estimate the number of rows to be scanned. // If not applied, these queries can become very slow. After some critical number // of logs, Postgres will try to scan all the logs in the index by block_number. // Latency without upper bound filter can be orders of magnitude higher for large number of logs. - _, err := o.db.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks + _, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= (SELECT MAX(block_number) @@ -286,7 +285,7 @@ func (o *DbORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error return err } - _, err = o.db.ExecContext(ctx, `DELETE FROM evm.logs + _, err = o.ds.ExecContext(ctx, `DELETE FROM evm.logs WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= (SELECT MAX(block_number) FROM evm.logs WHERE evm_chain_id = $1)`, @@ -307,11 +306,11 @@ type Exp struct { ShouldDelete bool } -func (o *DbORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, error) { +func (o *DSORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, error) { var err error var result sql.Result if limit > 0 { - result, err = o.db.ExecContext(ctx, ` + result, err = o.ds.ExecContext(ctx, ` DELETE FROM evm.logs WHERE (evm_chain_id, address, event_sig, block_number) IN ( SELECT l.evm_chain_id, l.address, l.event_sig, l.block_number @@ -327,7 +326,7 @@ func (o *DbORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, erro LIMIT $2 )`, ubig.New(o.chainID), limit) } else { - result, err = o.db.ExecContext(ctx, `WITH r AS + result, err = o.ds.ExecContext(ctx, `WITH r AS ( SELECT address, event, MAX(retention) AS retention FROM evm.log_poller_filters WHERE evm_chain_id=$1 GROUP BY evm_chain_id,address, event HAVING NOT 0 = ANY(ARRAY_AGG(retention)) @@ -344,16 +343,16 @@ func (o *DbORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, erro } // InsertLogs is idempotent to support replays. -func (o *DbORM) InsertLogs(ctx context.Context, logs []Log) error { +func (o *DSORM) InsertLogs(ctx context.Context, logs []Log) error { if err := o.validateLogs(logs); err != nil { return err } - return o.Transaction(ctx, func(orm *DbORM) error { - return orm.insertLogsWithinTx(ctx, logs, orm.db) + return o.Transact(ctx, func(orm *DSORM) error { + return orm.insertLogsWithinTx(ctx, logs, orm.ds) }) } -func (o *DbORM) InsertLogsWithBlock(ctx context.Context, logs []Log, block LogPollerBlock) error { +func (o *DSORM) InsertLogsWithBlock(ctx context.Context, logs []Log, block LogPollerBlock) error { // Optimization, don't open TX when there is only a block to be persisted if len(logs) == 0 { return o.InsertBlock(ctx, block.BlockHash, block.BlockNumber, block.BlockTimestamp, block.FinalizedBlockNumber) @@ -364,16 +363,16 @@ func (o *DbORM) InsertLogsWithBlock(ctx context.Context, logs []Log, block LogPo } // Block and logs goes with the same TX to ensure atomicity - return o.Transaction(ctx, func(orm *DbORM) error { + return o.Transact(ctx, func(orm *DSORM) error { err := orm.InsertBlock(ctx, block.BlockHash, block.BlockNumber, block.BlockTimestamp, block.FinalizedBlockNumber) if err != nil { return err } - return orm.insertLogsWithinTx(ctx, logs, orm.db) + return orm.insertLogsWithinTx(ctx, logs, orm.ds) }) } -func (o *DbORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.DataSource) error { +func (o *DSORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.DataSource) error { batchInsertSize := 4000 for i := 0; i < len(logs); i += batchInsertSize { start, end := i, i+batchInsertSize @@ -387,12 +386,10 @@ func (o *DbORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.D (:evm_chain_id, :log_index, :block_hash, :block_number, :block_timestamp, :address, :event_sig, :topics, :tx_hash, :data, NOW()) ON CONFLICT DO NOTHING` - query, sqlArgs, err := o.db.BindNamed(query, logs[start:end]) + _, err := o.ds.NamedExecContext(ctx, query, logs[start:end]) if err != nil { return err } - - _, err = tx.ExecContext(ctx, query, sqlArgs...) if err != nil { if pkgerrors.Is(err, context.DeadlineExceeded) && batchInsertSize > 500 { // In case of DB timeouts, try to insert again with a smaller batch upto a limit @@ -406,7 +403,7 @@ func (o *DbORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.D return nil } -func (o *DbORM) validateLogs(logs []Log) error { +func (o *DSORM) validateLogs(logs []Log) error { for _, log := range logs { if o.chainID.Cmp(log.EvmChainId.ToInt()) != 0 { return pkgerrors.Errorf("invalid chainID in log got %v want %v", log.EvmChainId.ToInt(), o.chainID) @@ -415,7 +412,7 @@ func (o *DbORM) validateLogs(logs []Log) error { return nil } -func (o *DbORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([]Log, error) { +func (o *DSORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([]Log, error) { args, err := newQueryArgs(o.chainID). withStartBlock(start). withEndBlock(end). @@ -431,12 +428,12 @@ func (o *DbORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([ ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } @@ -444,7 +441,7 @@ func (o *DbORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([ } // SelectLogs finds the logs in a given block range. -func (o *DbORM) SelectLogs(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash) ([]Log, error) { +func (o *DSORM) SelectLogs(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withStartBlock(start). withEndBlock(end). @@ -462,12 +459,12 @@ func (o *DbORM) SelectLogs(ctx context.Context, start, end int64, address common ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } @@ -475,7 +472,7 @@ func (o *DbORM) SelectLogs(ctx context.Context, start, end int64, address common } // SelectLogsCreatedAfter finds logs created after some timestamp. -func (o *DbORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withBlockTimestampAfter(after). withConfs(confs). @@ -494,12 +491,12 @@ func (o *DbORM) SelectLogsCreatedAfter(ctx context.Context, address common.Addre ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err = o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil @@ -507,7 +504,7 @@ func (o *DbORM) SelectLogsCreatedAfter(ctx context.Context, address common.Addre // SelectLogsWithSigs finds the logs in the given block range with the given event signatures // emitted from the given address. -func (o *DbORM) SelectLogsWithSigs(ctx context.Context, start, end int64, address common.Address, eventSigs []common.Hash) (logs []Log, err error) { +func (o *DSORM) SelectLogsWithSigs(ctx context.Context, start, end int64, address common.Address, eventSigs []common.Hash) (logs []Log, err error) { args, err := newQueryArgs(o.chainID). withAddress(address). withEventSigArray(eventSigs). @@ -525,19 +522,19 @@ func (o *DbORM) SelectLogsWithSigs(ctx context.Context, start, end int64, addres AND block_number BETWEEN :start_block AND :end_block ORDER BY (block_number, log_index)` - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if pkgerrors.Is(err, sql.ErrNoRows) { return nil, nil } return logs, err } -func (o *DbORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]LogPollerBlock, error) { +func (o *DSORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]LogPollerBlock, error) { args, err := newQueryArgs(o.chainID). withStartBlock(start). withEndBlock(end). @@ -553,12 +550,12 @@ func (o *DbORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]L ORDER BY block_number ASC` var blocks []LogPollerBlock - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &blocks, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &blocks, query, sqlArgs...) if err != nil { return nil, err } @@ -566,7 +563,7 @@ func (o *DbORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]L } // SelectLatestLogEventSigsAddrsWithConfs finds the latest log by (address, event) combination that matches a list of Addresses and list of events -func (o *DbORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgs(o.chainID). withAddressArray(addresses). withEventSigArray(eventSigs). @@ -590,19 +587,19 @@ func (o *DbORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, from ORDER BY block_number ASC`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err = o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, pkgerrors.Wrap(err, "failed to execute query") } return logs, nil } // SelectLatestBlockByEventSigsAddrsWithConfs finds the latest block number that matches a list of Addresses and list of events. It returns 0 if there is no matching block -func (o *DbORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { +func (o *DSORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { args, err := newQueryArgs(o.chainID). withEventSigArray(eventSigs). withAddressArray(addresses). @@ -621,18 +618,18 @@ func (o *DbORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, AND block_number <= %s`, nestedBlockNumberQuery(confs)) var blockNumber int64 - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return 0, err } - if err = o.db.GetContext(ctx, &blockNumber, query, sqlArgs...); err != nil { + if err = o.ds.GetContext(ctx, &blockNumber, query, sqlArgs...); err != nil { return 0, err } return blockNumber, nil } -func (o *DbORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndex(wordIndex). withWordValueMin(wordValueMin). @@ -653,18 +650,18 @@ func (o *DbORM) SelectLogsDataWordRange(ctx context.Context, address common.Addr ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndex(wordIndex). withWordValueMin(wordValueMin). @@ -684,18 +681,18 @@ func (o *DbORM) SelectLogsDataWordGreaterThan(ctx context.Context, address commo ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndexMin(wordIndexMin). withWordIndexMax(wordIndexMax). @@ -716,18 +713,18 @@ func (o *DbORM) SelectLogsDataWordBetween(ctx context.Context, address common.Ad ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValueMin(topicValueMin). @@ -747,18 +744,18 @@ func (o *DbORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address c ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValueMin(topicValueMin). @@ -780,18 +777,18 @@ func (o *DbORM) SelectIndexedLogsTopicRange(ctx context.Context, address common. ORDER BY (evm.logs.block_number, evm.logs.log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValues(topicValues). @@ -811,19 +808,19 @@ func (o *DbORM) SelectIndexedLogs(ctx context.Context, address common.Address, e ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } // SelectIndexedLogsByBlockRange finds the indexed logs in a given block range. -func (o *DbORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValues(topicValues). @@ -844,19 +841,19 @@ func (o *DbORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end in ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withBlockTimestampAfter(after). withConfs(confs). @@ -878,18 +875,18 @@ func (o *DbORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address commo ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Address, eventSig common.Hash, txHash common.Hash) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Address, eventSig common.Hash, txHash common.Hash) ([]Log, error) { args, err := newQueryArgs(o.chainID). withTxHash(txHash). withAddress(address). @@ -907,12 +904,12 @@ func (o *DbORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Ad ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } @@ -920,7 +917,7 @@ func (o *DbORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Ad } // SelectIndexedLogsWithSigsExcluding query's for logs that have signature A and exclude logs that have a corresponding signature B, matching is done based on the topic index both logs should be inside the block range and have the minimum number of confirmations -func (o *DbORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs Confirmations) ([]Log, error) { args, err := newQueryArgs(o.chainID). withAddress(address). withTopicIndex(topicIndex). @@ -955,12 +952,12 @@ func (o *DbORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, si ORDER BY block_number,log_index ASC`, nestedQuery, nestedQuery) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index 8a45ff2f1c5..2a1be62dd5b 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -1759,3 +1759,33 @@ func Benchmark_DeleteExpiredLogs(b *testing.B) { assert.NoError(b, err1) } } + +func TestSelectOldestBlock(t *testing.T) { + th := SetupTH(t, lpOpts) + o1 := th.ORM + o2 := th.ORM2 + ctx := testutils.Context(t) + t.Run("Selects oldest within given chain", func(t *testing.T) { + // insert blocks + require.NoError(t, o2.InsertBlock(ctx, common.HexToHash("0x1231"), 11, time.Now(), 0)) + require.NoError(t, o2.InsertBlock(ctx, common.HexToHash("0x1232"), 12, time.Now(), 0)) + // insert newer block from different chain + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1233"), 13, time.Now(), 0)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1231"), 14, time.Now(), 0)) + block, err := o1.SelectOldestBlock(ctx, 0) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, block.BlockNumber, int64(13)) + require.Equal(t, block.BlockHash, common.HexToHash("0x1233")) + }) + t.Run("Does not select blocks older than specified limit", func(t *testing.T) { + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1232"), 11, time.Now(), 0)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1233"), 13, time.Now(), 0)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1234"), 15, time.Now(), 0)) + block, err := o1.SelectOldestBlock(ctx, 12) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, block.BlockNumber, int64(13)) + require.Equal(t, block.BlockHash, common.HexToHash("0x1233")) + }) +} diff --git a/core/chains/evm/logpoller/query.go b/core/chains/evm/logpoller/query.go index 6aabe59045d..f9d2c45bce1 100644 --- a/core/chains/evm/logpoller/query.go +++ b/core/chains/evm/logpoller/query.go @@ -24,7 +24,7 @@ func concatBytes[T bytesProducer](byteSlice []T) [][]byte { return output } -// queryArgs is a helper for building the arguments to a postgres query created by DbORM +// queryArgs is a helper for building the arguments to a postgres query created by DSORM // Besides the convenience methods, it also keeps track of arguments validation and sanitization. type queryArgs struct { args map[string]interface{} diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 4e19a2ec7da..20c069a46d6 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -1112,7 +1112,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { } t.Run("with erroring callback bails out", func(t *testing.T) { - require.NoError(t, txStore.InsertTx(ctx, &etx)) + require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) fn := func(ctx context.Context, id uuid.UUID, result interface{}, err error) error { return errors.New("something exploded in the callback") } diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go index f13efb2b258..0671f49bb74 100644 --- a/core/chains/evm/txmgr/builder.go +++ b/core/chains/evm/txmgr/builder.go @@ -4,8 +4,6 @@ import ( "math/big" "time" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/common/txmgr" @@ -21,8 +19,7 @@ import ( // NewTxm constructs the necessary dependencies for the EvmTxm (broadcaster, confirmer, etc) and returns a new EvmTxManager func NewTxm( - sqlxDB *sqlx.DB, - db sqlutil.DataSource, + ds sqlutil.DataSource, chainConfig ChainConfig, fCfg FeeConfig, txConfig config.Transactions, @@ -40,14 +37,14 @@ func NewTxm( var fwdMgr FwdMgr if txConfig.ForwardersEnabled() { - fwdMgr = forwarders.NewFwdMgr(db, client, logPoller, lggr, chainConfig) + fwdMgr = forwarders.NewFwdMgr(ds, client, logPoller, lggr, chainConfig) } else { lggr.Info("EvmForwarderManager: Disabled") } checker := &CheckerFactory{Client: client} // create tx attempt builder txAttemptBuilder := NewEvmTxAttemptBuilder(*client.ConfiguredChainID(), fCfg, keyStore, estimator) - txStore := NewTxStore(sqlxDB, lggr) + txStore := NewTxStore(ds, lggr) txmCfg := NewEvmTxmConfig(chainConfig) // wrap Evm specific config feeCfg := NewEvmTxmFeeConfig(fCfg) // wrap Evm specific config txmClient := NewEvmTxmClient(client, clientErrors) // wrap Evm specific client diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index c8e664e8cfe..dedba07b594 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -115,7 +115,7 @@ func DbReceiptToEvmReceipt(receipt *dbReceipt) *evmtypes.Receipt { // Directly maps to onchain receipt schema. type rawOnchainReceipt = evmtypes.Receipt -func (o *evmTxStore) Transaction(ctx context.Context, readOnly bool, fn func(*evmTxStore) error) (err error) { +func (o *evmTxStore) Transact(ctx context.Context, readOnly bool, fn func(*evmTxStore) error) (err error) { opts := &sqlutil.TxOptions{TxOptions: sql.TxOptions{ReadOnly: readOnly}} return sqlutil.Transact(ctx, o.new, o.q, opts, fn) } @@ -509,7 +509,7 @@ func (o *evmTxStore) FindTxAttemptsByTxIDs(ctx context.Context, ids []int64) ([] func (o *evmTxStore) FindTxByHash(ctx context.Context, hash common.Hash) (*Tx, error) { var dbEtx DbEthTx - err := o.Transaction(ctx, true, func(orm *evmTxStore) error { + err := o.Transact(ctx, true, func(orm *evmTxStore) error { sql := `SELECT evm.txes.* FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM evm.tx_attempts WHERE hash = $1)` if err := orm.q.GetContext(ctx, &dbEtx, sql, hash); err != nil { return pkgerrors.Wrapf(err, "failed to find eth_tx with hash %d", hash) @@ -575,7 +575,7 @@ func (o *evmTxStore) GetFatalTransactions(ctx context.Context) (txes []*Tx, err var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { stmt := `SELECT * FROM evm.txes WHERE state = 'fatal_error'` var dbEtxs []DbEthTx if err = orm.q.SelectContext(ctx, &dbEtxs, stmt); err != nil { @@ -595,7 +595,7 @@ func (o *evmTxStore) GetFatalTransactions(ctx context.Context) (txes []*Tx, err // FindTxWithAttempts finds the Tx with its attempts and receipts preloaded func (o *evmTxStore) FindTxWithAttempts(ctx context.Context, etxID int64) (etx Tx, err error) { - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtx DbEthTx if err = orm.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE id = $1 ORDER BY created_at ASC, id ASC`, etxID); err != nil { return pkgerrors.Wrapf(err, "failed to find evm.tx with id %d", etxID) @@ -614,7 +614,7 @@ func (o *evmTxStore) FindTxWithAttempts(ctx context.Context, etxID int64) (etx T func (o *evmTxStore) FindTxAttemptConfirmedByTxIDs(ctx context.Context, ids []int64) ([]TxAttempt, error) { var txAttempts []TxAttempt - err := o.Transaction(ctx, true, func(orm *evmTxStore) error { + err := o.Transact(ctx, true, func(orm *evmTxStore) error { var dbAttempts []DbEthTxAttempt if err := orm.q.SelectContext(ctx, &dbAttempts, `SELECT eta.* FROM evm.tx_attempts eta @@ -806,7 +806,7 @@ func (o *evmTxStore) FindTxAttemptsRequiringReceiptFetch(ctx context.Context, ch var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbAttempts []DbEthTxAttempt err = orm.q.SelectContext(ctx, &dbAttempts, ` SELECT evm.tx_attempts.* FROM evm.tx_attempts @@ -963,7 +963,7 @@ func (o *evmTxStore) GetInProgressTxAttempts(ctx context.Context, address common var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbAttempts []DbEthTxAttempt err = orm.q.SelectContext(ctx, &dbAttempts, ` SELECT evm.tx_attempts.* FROM evm.tx_attempts @@ -1046,7 +1046,7 @@ func (o *evmTxStore) FindTxWithSequence(ctx context.Context, fromAddress common. ctx, cancel = o.mergeContexts(ctx) defer cancel() etx = new(Tx) - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtx DbEthTx err = orm.q.GetContext(ctx, &dbEtx, ` SELECT * FROM evm.txes WHERE from_address = $1 AND nonce = $2 AND state IN ('confirmed', 'confirmed_missing_receipt', 'unconfirmed') @@ -1094,7 +1094,7 @@ func (o *evmTxStore) UpdateTxForRebroadcast(ctx context.Context, etx Tx, etxAtte var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { if err := deleteEthReceipts(ctx, orm, etx.ID); err != nil { return pkgerrors.Wrapf(err, "deleteEthReceipts failed for etx %v", etx.ID) } @@ -1109,7 +1109,7 @@ func (o *evmTxStore) FindTransactionsConfirmedInBlockRange(ctx context.Context, var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtxs []DbEthTx err = orm.q.SelectContext(ctx, &dbEtxs, ` SELECT DISTINCT evm.txes.* FROM evm.txes @@ -1136,7 +1136,7 @@ func (o *evmTxStore) FindEarliestUnconfirmedBroadcastTime(ctx context.Context, c var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { if err = orm.q.QueryRowxContext(ctx, `SELECT min(initial_broadcast_at) FROM evm.txes WHERE state = 'unconfirmed' AND evm_chain_id = $1`, chainID.String()).Scan(&broadcastAt); err != nil { return fmt.Errorf("failed to query for unconfirmed eth_tx count: %w", err) } @@ -1149,7 +1149,7 @@ func (o *evmTxStore) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context, var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { err = orm.q.QueryRowxContext(ctx, ` SELECT MIN(broadcast_before_block_num) FROM evm.tx_attempts JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id @@ -1184,7 +1184,7 @@ func (o *evmTxStore) IsTxFinalized(ctx context.Context, blockHeight int64, txID func (o *evmTxStore) saveAttemptWithNewState(ctx context.Context, attempt TxAttempt, broadcastAt time.Time) error { var dbAttempt DbEthTxAttempt dbAttempt.FromTxAttempt(&attempt) - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { // In case of null broadcast_at (shouldn't happen) we don't want to // update anyway because it indicates a state where broadcast_at makes // no sense e.g. fatal_error @@ -1230,7 +1230,7 @@ func (o *evmTxStore) SaveConfirmedMissingReceiptAttempt(ctx context.Context, tim var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err := o.Transaction(ctx, false, func(orm *evmTxStore) error { + err := o.Transact(ctx, false, func(orm *evmTxStore) error { if err := orm.saveSentAttempt(ctx, timeout, attempt, broadcastAt); err != nil { return err } @@ -1321,7 +1321,7 @@ func (o *evmTxStore) GetTxByID(ctx context.Context, id int64) (txe *Tx, err erro ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { stmt := `SELECT * FROM evm.txes WHERE id = $1` var dbEtxs []DbEthTx if err = orm.q.SelectContext(ctx, &dbEtxs, stmt, id); err != nil { @@ -1355,7 +1355,7 @@ func (o *evmTxStore) FindTxsRequiringGasBump(ctx context.Context, address common var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { stmt := ` SELECT evm.txes.* FROM evm.txes LEFT JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id AND (broadcast_before_block_num > $4 OR broadcast_before_block_num IS NULL OR evm.tx_attempts.state != 'broadcast') @@ -1382,7 +1382,7 @@ func (o *evmTxStore) FindTxsRequiringResubmissionDueToInsufficientFunds(ctx cont var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtxs []DbEthTx err = orm.q.SelectContext(ctx, &dbEtxs, ` SELECT DISTINCT evm.txes.* FROM evm.txes @@ -1423,7 +1423,7 @@ func (o *evmTxStore) MarkOldTxesMissingReceiptAsErrored(ctx context.Context, blo return nil } // note: if QOpt passes in a sql.Tx this will reuse it - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { type etx struct { ID int64 Nonce int64 @@ -1511,7 +1511,7 @@ func (o *evmTxStore) SaveReplacementInProgressAttempt(ctx context.Context, oldAt if oldAttempt.ID == 0 { return errors.New("expected oldAttempt to have an ID") } - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { if _, err := orm.q.ExecContext(ctx, `DELETE FROM evm.tx_attempts WHERE id=$1`, oldAttempt.ID); err != nil { return pkgerrors.Wrap(err, "saveReplacementInProgressAttempt failed to delete from evm.tx_attempts") } @@ -1557,7 +1557,7 @@ func (o *evmTxStore) UpdateTxFatalError(ctx context.Context, etx *Tx) error { etx.Sequence = nil etx.State = txmgr.TxFatalError - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { if _, err := orm.q.ExecContext(ctx, `DELETE FROM evm.tx_attempts WHERE eth_tx_id = $1`, etx.ID); err != nil { return pkgerrors.Wrapf(err, "saveFatallyErroredTransaction failed to delete eth_tx_attempt with eth_tx.ID %v", etx.ID) } @@ -1591,7 +1591,7 @@ func (o *evmTxStore) UpdateTxAttemptInProgressToBroadcast(ctx context.Context, e } etx.State = txmgr.TxUnconfirmed attempt.State = NewAttemptState - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { var dbEtx DbEthTx dbEtx.FromTx(etx) if err := orm.q.GetContext(ctx, &dbEtx, `UPDATE evm.txes SET state=$1, error=$2, broadcast_at=$3, initial_broadcast_at=$4 WHERE id = $5 RETURNING *`, dbEtx.State, dbEtx.Error, dbEtx.BroadcastAt, dbEtx.InitialBroadcastAt, dbEtx.ID); err != nil { @@ -1622,7 +1622,7 @@ func (o *evmTxStore) UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx, return errors.New("attempt state must be in_progress") } etx.State = txmgr.TxInProgress - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { // If a replay was triggered while unconfirmed transactions were pending, they will be marked as fatal_error => abandoned. // In this case, we must remove the abandoned attempt from evm.tx_attempts before replacing it with a new one. In any other // case, we uphold the constraint, leaving the original tx attempt as-is and returning the constraint violation error. @@ -1688,7 +1688,7 @@ func (o *evmTxStore) GetTxInProgress(ctx context.Context, fromAddress common.Add if err != nil { return etx, pkgerrors.Wrap(err, "getInProgressEthTx failed") } - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtx DbEthTx err = orm.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE from_address = $1 and state = 'in_progress'`, fromAddress) if errors.Is(err, sql.ErrNoRows) { @@ -1776,7 +1776,7 @@ func (o *evmTxStore) CreateTransaction(ctx context.Context, txRequest TxRequest, ctx, cancel = o.mergeContexts(ctx) defer cancel() var dbEtx DbEthTx - err = o.Transaction(ctx, false, func(orm *evmTxStore) error { + err = o.Transact(ctx, false, func(orm *evmTxStore) error { if txRequest.PipelineTaskRunID != nil { err = orm.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE pipeline_task_run_id = $1 AND evm_chain_id = $2`, txRequest.PipelineTaskRunID, chainID.String()) @@ -1810,7 +1810,7 @@ func (o *evmTxStore) PruneUnstartedTxQueue(ctx context.Context, queueSize uint32 var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, false, func(orm *evmTxStore) error { + err = o.Transact(ctx, false, func(orm *evmTxStore) error { err := orm.q.SelectContext(ctx, &ids, ` DELETE FROM evm.txes WHERE state = 'unstarted' AND subject = $1 AND @@ -1945,7 +1945,7 @@ func (o *evmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Co var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtxs []DbEthTx if err = orm.q.SelectContext(ctx, &dbEtxs, `SELECT * FROM evm.txes WHERE id = ANY($1) AND state = ANY($2) AND evm_chain_id = $3`, pq.Array(ids), pq.Array(states), chainID.String()); err != nil { return pkgerrors.Wrapf(err, "failed to find evm.txes") diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index aac9d89c490..85d25d8a70b 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -68,7 +68,6 @@ func makeTestEvmTxm( ) return txmgr.NewTxm( - db, db, ccfg, fcfg, diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 920532518ab..27e0155da52 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -9,8 +9,6 @@ import ( gotoml "github.com/pelletier/go-toml/v2" "go.uber.org/multierr" - "github.com/jmoiron/sqlx" - common "github.com/smartcontractkit/chainlink-common/pkg/chains" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -162,8 +160,7 @@ type ChainOpts struct { MailMon *mailbox.Monitor GasEstimator gas.EvmFeeEstimator - SqlxDB *sqlx.DB // Deprecated: use DB instead - DB sqlutil.DataSource + DS sqlutil.DataSource // TODO BCF-2513 remove test code from the API // Gen-functions are useful for dependency injection by tests @@ -184,11 +181,8 @@ func (o ChainOpts) Validate() error { if o.MailMon == nil { err = errors.Join(err, errors.New("nil MailMon")) } - if o.SqlxDB == nil { - err = errors.Join(err, errors.New("nil SqlxDB")) - } - if o.DB == nil { - err = errors.Join(err, errors.New("nil DB")) + if o.DS == nil { + err = errors.Join(err, errors.New("nil DS")) } if err != nil { err = fmt.Errorf("invalid ChainOpts: %w", err) @@ -229,7 +223,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod if !opts.AppConfig.EVMRPCEnabled() { headTracker = headtracker.NullTracker } else if opts.GenHeadTracker == nil { - orm := headtracker.NewORM(*chainID, opts.DB) + orm := headtracker.NewORM(*chainID, opts.DS) headSaver = headtracker.NewHeadSaver(l, orm, cfg.EVM(), cfg.EVM().HeadTracker()) headTracker = headtracker.NewHeadTracker(l, client, cfg.EVM(), cfg.EVM().HeadTracker(), headBroadcaster, headSaver, opts.MailMon) } else { @@ -251,12 +245,12 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod LogPrunePageSize: int64(cfg.EVM().LogPrunePageSize()), BackupPollerBlockDelay: int64(cfg.EVM().BackupLogPollerBlockDelay()), } - logPoller = logpoller.NewLogPoller(logpoller.NewObservedORM(chainID, opts.DB, l), client, l, lpOpts) + logPoller = logpoller.NewLogPoller(logpoller.NewObservedORM(chainID, opts.DS, l), client, l, lpOpts) } } // note: gas estimator is started as a part of the txm - txm, gasEstimator, err := newEvmTxm(opts.SqlxDB, opts.DB, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts) + txm, gasEstimator, err := newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts) if err != nil { return nil, fmt.Errorf("failed to instantiate EvmTxm for chain with ID %s: %w", chainID.String(), err) } @@ -279,7 +273,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod if !opts.AppConfig.EVMRPCEnabled() { logBroadcaster = &log.NullBroadcaster{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)} } else if opts.GenLogBroadcaster == nil { - logORM := log.NewORM(opts.SqlxDB, *chainID) + logORM := log.NewORM(opts.DS, *chainID) logBroadcaster = log.NewBroadcaster(logORM, client, cfg.EVM(), l, highestSeenHead, opts.MailMon) } else { logBroadcaster = opts.GenLogBroadcaster(chainID) diff --git a/core/chains/legacyevm/chain_test.go b/core/chains/legacyevm/chain_test.go index 5dd7eb1c6ed..c10712d4b6b 100644 --- a/core/chains/legacyevm/chain_test.go +++ b/core/chains/legacyevm/chain_test.go @@ -65,8 +65,7 @@ func TestChainOpts_Validate(t *testing.T) { o := legacyevm.ChainOpts{ AppConfig: tt.fields.AppConfig, MailMon: tt.fields.MailMon, - SqlxDB: tt.fields.DB, - DB: tt.fields.DB, + DS: tt.fields.DB, } if err := o.Validate(); (err != nil) != tt.wantErr { t.Errorf("ChainOpts.Validate() error = %v, wantErr %v", err, tt.wantErr) diff --git a/core/chains/legacyevm/evm_txm.go b/core/chains/legacyevm/evm_txm.go index 6b2d1262ce8..df1f4248ce2 100644 --- a/core/chains/legacyevm/evm_txm.go +++ b/core/chains/legacyevm/evm_txm.go @@ -3,8 +3,6 @@ package legacyevm import ( "fmt" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" @@ -15,8 +13,7 @@ import ( ) func newEvmTxm( - sqlxDB *sqlx.DB, - db sqlutil.DataSource, + ds sqlutil.DataSource, cfg evmconfig.EVM, evmRPCEnabled bool, databaseConfig txmgr.DatabaseConfig, @@ -53,8 +50,7 @@ func newEvmTxm( if opts.GenTxManager == nil { txm, err = txmgr.NewTxm( - sqlxDB, - db, + ds, cfg, txmgr.NewEvmTxmFeeConfig(cfg.GasEstimator()), cfg.Transactions(), diff --git a/core/cmd/blocks_commands.go b/core/cmd/blocks_commands.go index 72b0523e18d..158caf253ab 100644 --- a/core/cmd/blocks_commands.go +++ b/core/cmd/blocks_commands.go @@ -9,6 +9,8 @@ import ( "github.com/pkg/errors" "github.com/urfave/cli" "go.uber.org/multierr" + + "github.com/smartcontractkit/chainlink/v2/core/web" ) func initBlocksSubCmds(s *Shell) []cli.Command { @@ -34,6 +36,18 @@ func initBlocksSubCmds(s *Shell) []cli.Command { }, }, }, + { + Name: "find-lca", + Usage: "Find latest common block stored in DB and on chain", + Action: s.FindLCA, + Flags: []cli.Flag{ + cli.Int64Flag{ + Name: "evm-chain-id", + Usage: "Chain ID of the EVM-based blockchain", + Required: true, + }, + }, + }, } } @@ -75,3 +89,47 @@ func (s *Shell) ReplayFromBlock(c *cli.Context) (err error) { fmt.Println("Replay started") return nil } + +// LCAPresenter implements TableRenderer for an LCAResponse. +type LCAPresenter struct { + web.LCAResponse +} + +// ToRow presents the EVMChainResource as a slice of strings. +func (p *LCAPresenter) ToRow() []string { + return []string{p.EVMChainID.String(), p.Hash, strconv.FormatInt(p.BlockNumber, 10)} +} + +// RenderTable implements TableRenderer +// Just renders a single row +func (p LCAPresenter) RenderTable(rt RendererTable) error { + renderList([]string{"ChainID", "Block Hash", "Block Number"}, [][]string{p.ToRow()}, rt.Writer) + + return nil +} + +// FindLCA finds last common block stored in DB and on chain. +func (s *Shell) FindLCA(c *cli.Context) (err error) { + v := url.Values{} + + if c.IsSet("evm-chain-id") { + v.Add("evmChainID", fmt.Sprintf("%d", c.Int64("evm-chain-id"))) + } + + resp, err := s.HTTP.Get(s.ctx(), + fmt.Sprintf( + "/v2/find_lca?%s", + v.Encode(), + )) + if err != nil { + return s.errorOut(err) + } + + defer func() { + if cerr := resp.Body.Close(); cerr != nil { + err = multierr.Append(err, cerr) + } + }() + + return s.renderAPIResponse(resp, &LCAPresenter{}, "Last Common Ancestor") +} diff --git a/core/cmd/blocks_commands_test.go b/core/cmd/blocks_commands_test.go index 30540748cb1..f7656b94ae1 100644 --- a/core/cmd/blocks_commands_test.go +++ b/core/cmd/blocks_commands_test.go @@ -41,3 +41,28 @@ func Test_ReplayFromBlock(t *testing.T) { c = cli.NewContext(nil, set, nil) require.NoError(t, client.ReplayFromBlock(c)) } + +func Test_FindLCA(t *testing.T) { + t.Parallel() + + //ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil) + app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].ChainID = (*ubig.Big)(big.NewInt(5)) + c.EVM[0].Enabled = ptr(true) + }) + + client, _ := app.NewShellAndRenderer() + + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(client.FindLCA, set, "") + + //Incorrect chain ID + require.NoError(t, set.Set("evm-chain-id", "1")) + c := cli.NewContext(nil, set, nil) + require.ErrorContains(t, client.FindLCA(c), "does not match any local chains") + + //Correct chain ID + require.NoError(t, set.Set("evm-chain-id", "5")) + c = cli.NewContext(nil, set, nil) + require.ErrorContains(t, client.FindLCA(c), "FindLCA is only available if LogPoller is enabled") +} diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go index 2f22cd1d3ae..64835c7f28b 100644 --- a/core/cmd/eth_keys_commands_test.go +++ b/core/cmd/eth_keys_commands_test.go @@ -182,7 +182,7 @@ func TestShell_CreateETHKey(t *testing.T) { withKey(), withMocks(ethClient), ) - db := app.GetSqlxDB() + db := app.GetDB() client, _ := app.NewShellAndRenderer() cltest.AssertCount(t, db, "evm.key_states", 1) // The initial funding key @@ -306,7 +306,7 @@ func TestShell_ImportExportETHKey_NoChains(t *testing.T) { _, err = ethKeyStore.Get(testutils.Context(t), address) require.Error(t, err) - cltest.AssertCount(t, app.GetSqlxDB(), "evm.key_states", 0) + cltest.AssertCount(t, app.GetDB(), "evm.key_states", 0) // Import the key set = flag.NewFlagSet("test", 0) diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index df5d066927a..5375abbacee 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -32,7 +32,7 @@ func TestShell_IndexTransactions(t *testing.T) { _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) attempt := tx.TxAttempts[0] @@ -70,7 +70,7 @@ func TestShell_ShowTransaction(t *testing.T) { app := startNewApplicationV2(t, nil) client, r := app.NewShellAndRenderer() - db := app.GetSqlxDB() + db := app.GetDB() _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) txStore := cltest.NewTestTxStore(t, db) @@ -97,7 +97,7 @@ func TestShell_IndexTxAttempts(t *testing.T) { _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) // page 1 @@ -156,7 +156,7 @@ func TestShell_SendEther_From_Txm(t *testing.T) { withMocks(ethMock, key), ) client, r := app.NewShellAndRenderer() - db := app.GetSqlxDB() + db := app.GetDB() txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) set := flag.NewFlagSet("sendether", 0) flagSetApplyFromAction(client.SendEther, set, "") @@ -221,7 +221,7 @@ func TestShell_SendEther_From_Txm_WEI(t *testing.T) { withMocks(ethMock, key), ) client, r := app.NewShellAndRenderer() - db := app.GetSqlxDB() + db := app.GetDB() txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) set := flag.NewFlagSet("sendether", 0) diff --git a/core/cmd/jobs_commands_test.go b/core/cmd/jobs_commands_test.go index 75e95db84ca..77d2487509a 100644 --- a/core/cmd/jobs_commands_test.go +++ b/core/cmd/jobs_commands_test.go @@ -17,6 +17,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -428,7 +429,8 @@ func TestShell_DeleteJob(t *testing.T) { requireJobsCount(t, app.JobORM(), 1) - jobs, _, err := app.JobORM().FindJobs(0, 1000) + ctx := testutils.Context(t) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) jobID := jobs[0].ID cltest.AwaitJobActive(t, app.JobSpawner(), jobID, 3*time.Second) @@ -451,7 +453,8 @@ func TestShell_DeleteJob(t *testing.T) { } func requireJobsCount(t *testing.T, orm job.ORM, expected int) { - jobs, _, err := orm.FindJobs(0, 1000) + ctx := testutils.Context(t) + jobs, _, err := orm.FindJobs(ctx, 0, 1000) require.NoError(t, err) require.Len(t, jobs, expected) } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index bc58c5cab6d..adbb66ce63f 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -136,7 +136,7 @@ type AppFactory interface { type ChainlinkAppFactory struct{} // NewApplication returns a new instance of the node with the given config. -func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, sqlxDB *sqlx.DB) (app chainlink.Application, err error) { +func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB) (app chainlink.Application, err error) { err = initGlobals(cfg.Prometheus(), cfg.Tracing(), appLggr) if err != nil { appLggr.Errorf("Failed to initialize globals: %v", err) @@ -147,14 +147,14 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G return nil, err } - db := sqlutil.WrapDataSource(sqlxDB, appLggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout), sqlutil.MonitorHook(cfg.Database().LogSQL)) - - err = handleNodeVersioning(ctx, sqlxDB, appLggr, cfg.RootDir(), cfg.Database(), cfg.WebServer().HTTPPort()) + err = handleNodeVersioning(ctx, db, appLggr, cfg.RootDir(), cfg.Database(), cfg.WebServer().HTTPPort()) if err != nil { return nil, err } - keyStore := keystore.New(db, utils.GetScryptParams(cfg), appLggr) + ds := sqlutil.WrapDataSource(db, appLggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout), sqlutil.MonitorHook(cfg.Database().LogSQL)) + + keyStore := keystore.New(ds, utils.GetScryptParams(cfg), appLggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), appLggr.Named("Mailbox")) loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing()) @@ -174,8 +174,9 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } evmFactoryCfg := chainlink.EVMFactoryConfig{ - CSAETHKeystore: keyStore, - ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, SqlxDB: sqlxDB, DB: sqlxDB}, + CSAETHKeystore: keyStore, + ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, DS: ds}, + MercuryTransmitter: cfg.Mercury().Transmitter(), } // evm always enabled for backward compatibility // TODO BCF-2510 this needs to change in order to clear the path for EVM extraction @@ -185,8 +186,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G cosmosCfg := chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: sqlxDB, - QConfig: cfg.Database(), + DS: ds, } initOps = append(initOps, chainlink.InitCosmos(ctx, relayerFactory, cosmosCfg)) } @@ -219,11 +219,10 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G restrictedClient := clhttp.NewRestrictedHTTPClient(cfg.Database(), appLggr) unrestrictedClient := clhttp.NewUnrestrictedHTTPClient() - externalInitiatorManager := webhook.NewExternalInitiatorManager(sqlxDB, unrestrictedClient, appLggr, cfg.Database()) + externalInitiatorManager := webhook.NewExternalInitiatorManager(ds, unrestrictedClient) return chainlink.NewApplication(chainlink.ApplicationOpts{ Config: cfg, - SqlxDB: sqlxDB, - DB: db, + DS: ds, KeyStore: keyStore, RelayerChainInteroperators: relayChainInterops, MailMon: mailMon, @@ -244,7 +243,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G func handleNodeVersioning(ctx context.Context, db *sqlx.DB, appLggr logger.Logger, rootDir string, cfg config.Database, healthReportPort uint16) error { var err error // Set up the versioning Configs - verORM := versioning.NewORM(db, appLggr, cfg.DefaultQueryTimeout()) + verORM := versioning.NewORM(db, appLggr) if static.Version != static.Unset { var appv, dbv *semver.Version @@ -272,7 +271,7 @@ func handleNodeVersioning(ctx context.Context, db *sqlx.DB, appLggr logger.Logge // Migrate the database if cfg.MigrateDatabase() { - if err = migrate.Migrate(ctx, db.DB, appLggr); err != nil { + if err = migrate.Migrate(ctx, db.DB); err != nil { return fmt.Errorf("initializeORM#Migrate: %w", err) } } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index a61390a4886..7c9c025d4be 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -34,6 +34,7 @@ import ( "github.com/jmoiron/sqlx" cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -253,6 +254,23 @@ func initLocalSubCmds(s *Shell, safe bool) []cli.Command { }, }, }, + { + Name: "remove-blocks", + Usage: "Deletes block range and all associated data", + Action: s.RemoveBlocks, + Flags: []cli.Flag{ + cli.IntFlag{ + Name: "start", + Usage: "Beginning of block range to be deleted", + Required: true, + }, + cli.Int64Flag{ + Name: "evm-chain-id", + Usage: "Chain ID of the EVM-based blockchain", + Required: true, + }, + }, + }, } } @@ -580,6 +598,11 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { } } + err = s.Config.Validate() + if err != nil { + return err + } + lggr := logger.Sugared(s.Logger.Named("RebroadcastTransactions")) db, err := pg.OpenUnlockedDB(s.Config.AppID(), s.Config.Database()) if err != nil { @@ -632,7 +655,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { s.Logger.Infof("Rebroadcasting transactions from %v to %v", beginningNonce, endingNonce) - orm := txmgr.NewTxStore(app.GetSqlxDB(), lggr) + orm := txmgr.NewTxStore(app.GetDB(), lggr) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), chain.Config().EVM().GasEstimator(), keyStore.Eth(), nil) cfg := txmgr.NewEvmTxmConfig(chain.Config().EVM()) feeCfg := txmgr.NewEvmTxmFeeConfig(chain.Config().EVM().GasEstimator()) @@ -923,7 +946,7 @@ func (s *Shell) RollbackDatabase(c *cli.Context) error { return fmt.Errorf("failed to initialize orm: %v", err) } - if err := migrate.Rollback(ctx, db.DB, s.Logger, version); err != nil { + if err := migrate.Rollback(ctx, db.DB, version); err != nil { return fmt.Errorf("migrateDB failed: %v", err) } @@ -938,7 +961,7 @@ func (s *Shell) VersionDatabase(_ *cli.Context) error { return fmt.Errorf("failed to initialize orm: %v", err) } - version, err := migrate.Current(ctx, db.DB, s.Logger) + version, err := migrate.Current(ctx, db.DB) if err != nil { return fmt.Errorf("migrateDB failed: %v", err) } @@ -955,7 +978,7 @@ func (s *Shell) StatusDatabase(_ *cli.Context) error { return fmt.Errorf("failed to initialize orm: %v", err) } - if err = migrate.Status(ctx, db.DB, s.Logger); err != nil { + if err = migrate.Status(ctx, db.DB); err != nil { return fmt.Errorf("Status failed: %v", err) } return nil @@ -1099,7 +1122,7 @@ func migrateDB(ctx context.Context, config dbConfig, lggr logger.Logger) error { return fmt.Errorf("failed to initialize orm: %v", err) } - if err = migrate.Migrate(ctx, db.DB, lggr); err != nil { + if err = migrate.Migrate(ctx, db.DB); err != nil { return fmt.Errorf("migrateDB failed: %v", err) } return db.Close() @@ -1110,10 +1133,10 @@ func downAndUpDB(ctx context.Context, cfg dbConfig, lggr logger.Logger, baseVers if err != nil { return fmt.Errorf("failed to initialize orm: %v", err) } - if err = migrate.Rollback(ctx, db.DB, lggr, null.IntFrom(baseVersionID)); err != nil { + if err = migrate.Rollback(ctx, db.DB, null.IntFrom(baseVersionID)); err != nil { return fmt.Errorf("test rollback failed: %v", err) } - if err = migrate.Migrate(ctx, db.DB, lggr); err != nil { + if err = migrate.Migrate(ctx, db.DB); err != nil { return fmt.Errorf("second migrateDB failed: %v", err) } return db.Close() @@ -1175,3 +1198,64 @@ func insertFixtures(dbURL url.URL, pathToFixtures string) (err error) { _, err = db.Exec(string(fixturesSQL)) return err } + +// RemoveBlocks - removes blocks after the specified blocks number +func (s *Shell) RemoveBlocks(c *cli.Context) error { + start := c.Int64("start") + if start <= 0 { + return s.errorOut(errors.New("Must pass a positive value in '--start' parameter")) + } + + chainID := big.NewInt(0) + if c.IsSet("evm-chain-id") { + err := chainID.UnmarshalText([]byte(c.String("evm-chain-id"))) + if err != nil { + return s.errorOut(err) + } + } + + cfg := s.Config + err := cfg.Validate() + if err != nil { + return s.errorOut(fmt.Errorf("error validating configuration: %+v", err)) + } + + lggr := logger.Sugared(s.Logger.Named("RemoveBlocks")) + ldb := pg.NewLockedDB(cfg.AppID(), cfg.Database(), cfg.Database().Lock(), lggr) + ctx, cancel := context.WithCancel(context.Background()) + go shutdown.HandleShutdown(func(sig string) { + cancel() + lggr.Info("received signal to stop - closing the database and releasing lock") + + if cErr := ldb.Close(); cErr != nil { + lggr.Criticalf("Failed to close LockedDB: %v", cErr) + } + + if cErr := s.CloseLogger(); cErr != nil { + log.Printf("Failed to close Logger: %v", cErr) + } + }) + + if err = ldb.Open(ctx); err != nil { + // If not successful, we know neither locks nor connection remains opened + return s.errorOut(errors.Wrap(err, "opening db")) + } + defer lggr.ErrorIfFn(ldb.Close, "Error closing db") + + // From now on, DB locks and DB connection will be released on every return. + // Keep watching on logger.Fatal* calls and os.Exit(), because defer will not be executed. + + app, err := s.AppFactory.NewApplication(ctx, s.Config, s.Logger, ldb.DB()) + if err != nil { + return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) + } + + err = app.DeleteLogPollerDataAfter(ctx, chainID, start) + if err != nil { + return s.errorOut(err) + } + + lggr.Infof("RemoveBlocks: successfully removed blocks") + + return nil +} diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index d608d3931d0..e7322e513ae 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "flag" + "fmt" "math/big" "os" "strconv" @@ -91,8 +92,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -196,8 +196,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -299,7 +298,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { lggr := logger.TestLogger(t) app := mocks.NewApplication(t) - app.On("GetSqlxDB").Return(sqlxDB) + app.On("GetDB").Return(sqlxDB) app.On("GetKeyStore").Return(keyStore) app.On("ID").Maybe().Return(uuid.New()) app.On("GetConfig").Return(config) @@ -381,7 +380,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { lggr := logger.TestLogger(t) app := mocks.NewApplication(t) - app.On("GetSqlxDB").Return(sqlxDB) + app.On("GetDB").Return(sqlxDB) app.On("GetKeyStore").Return(keyStore) app.On("ID").Maybe().Return(uuid.New()) app.On("GetConfig").Return(config) @@ -460,7 +459,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { lggr := logger.TestLogger(t) app := mocks.NewApplication(t) - app.On("GetSqlxDB").Maybe().Return(sqlxDB) + app.On("GetDB").Maybe().Return(sqlxDB) app.On("GetKeyStore").Return(keyStore) app.On("ID").Maybe().Return(uuid.New()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -516,3 +515,58 @@ func TestShell_CleanupChainTables(t *testing.T) { c := cli.NewContext(nil, set, nil) require.NoError(t, client.CleanupChainTables(c)) } + +func TestShell_RemoveBlocks(t *testing.T) { + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + s.Password.Keystore = models.NewSecret("dummy") + c.EVM[0].Nodes[0].Name = ptr("fake") + c.EVM[0].Nodes[0].HTTPURL = commonconfig.MustParseURL("http://fake.com") + c.EVM[0].Nodes[0].WSURL = commonconfig.MustParseURL("WSS://fake.com/ws") + // seems to be needed for config validate + c.Insecure.OCRDevelopmentMode = nil + }) + + lggr := logger.TestLogger(t) + + app := mocks.NewApplication(t) + app.On("GetSqlxDB").Maybe().Return(db) + shell := cmd.Shell{ + Config: cfg, + AppFactory: cltest.InstanceAppFactory{App: app}, + FallbackAPIInitializer: cltest.NewMockAPIInitializer(t), + Runner: cltest.EmptyRunner{}, + Logger: lggr, + } + + t.Run("Returns error, if --start is not positive", func(t *testing.T) { + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(shell.RemoveBlocks, set, "") + require.NoError(t, set.Set("start", "0")) + require.NoError(t, set.Set("evm-chain-id", "12")) + c := cli.NewContext(nil, set, nil) + err := shell.RemoveBlocks(c) + require.ErrorContains(t, err, "Must pass a positive value in '--start' parameter") + }) + t.Run("Returns error, if removal fails", func(t *testing.T) { + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(shell.RemoveBlocks, set, "") + require.NoError(t, set.Set("start", "10000")) + require.NoError(t, set.Set("evm-chain-id", "12")) + expectedError := fmt.Errorf("failed to delete log poller's data") + app.On("DeleteLogPollerDataAfter", mock.Anything, big.NewInt(12), int64(10000)).Return(expectedError).Once() + c := cli.NewContext(nil, set, nil) + err := shell.RemoveBlocks(c) + require.ErrorContains(t, err, expectedError.Error()) + }) + t.Run("Happy path", func(t *testing.T) { + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(shell.RemoveBlocks, set, "") + require.NoError(t, set.Set("start", "10000")) + require.NoError(t, set.Set("evm-chain-id", "12")) + app.On("DeleteLogPollerDataAfter", mock.Anything, big.NewInt(12), int64(10000)).Return(nil).Once() + c := cli.NewContext(nil, set, nil) + err := shell.RemoveBlocks(c) + require.NoError(t, err) + }) +} diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index a8c054cd9be..cdbe12d66b4 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -151,6 +151,7 @@ func TestShell_CreateExternalInitiator(t *testing.T) { for _, tt := range tests { test := tt t.Run(test.name, func(t *testing.T) { + ctx := testutils.Context(t) app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.JobPipeline.ExternalInitiatorsEnabled = ptr(true) }) @@ -165,7 +166,7 @@ func TestShell_CreateExternalInitiator(t *testing.T) { require.NoError(t, err) var exi bridges.ExternalInitiator - err = app.GetSqlxDB().Get(&exi, `SELECT * FROM external_initiators WHERE name = $1`, test.args[0]) + err = app.GetDB().GetContext(ctx, &exi, `SELECT * FROM external_initiators WHERE name = $1`, test.args[0]) require.NoError(t, err) if len(test.args) > 1 { @@ -195,7 +196,7 @@ func TestShell_CreateExternalInitiator_Errors(t *testing.T) { }) client, _ := app.NewShellAndRenderer() - initialExis := len(cltest.AllExternalInitiators(t, app.GetSqlxDB())) + initialExis := len(cltest.AllExternalInitiators(t, app.GetDB())) set := flag.NewFlagSet("create", 0) flagSetApplyFromAction(client.CreateExternalInitiator, set, "") @@ -206,7 +207,7 @@ func TestShell_CreateExternalInitiator_Errors(t *testing.T) { err := client.CreateExternalInitiator(c) assert.Error(t, err) - exis := cltest.AllExternalInitiators(t, app.GetSqlxDB()) + exis := cltest.AllExternalInitiators(t, app.GetDB()) assert.Len(t, exis, initialExis) }) } @@ -580,8 +581,8 @@ func TestShell_RunOCRJob_HappyPath(t *testing.T) { require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) var jb job.Job ocrspec := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{DS1BridgeName: bridge.Name.String(), DS2BridgeName: bridge2.Name.String()}) @@ -669,7 +670,7 @@ func TestShell_AutoLogin(t *testing.T) { require.NoError(t, err) // Expire the session and then try again - pgtest.MustExec(t, app.GetSqlxDB(), "delete from sessions where email = $1", user.Email) + pgtest.MustExec(t, app.GetDB(), "delete from sessions where email = $1", user.Email) err = client.ListJobs(cli.NewContext(nil, fs, nil)) require.NoError(t, err) } diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 605f6ced0bc..92d75430daf 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -622,3 +622,17 @@ LatestReportDeadline = "5s" # Default [Mercury.TLS] # CertFile is the path to a PEM file of trusted root certificate authority certificates CertFile = "/path/to/client/certs.pem" # Example + +# Mercury.Transmitter controls settings for the mercury transmitter +[Mercury.Transmitter] +# TransmitQueueMaxSize controls the size of the transmit queue. This is scoped +# per OCR instance. If the queue is full, the transmitter will start dropping +# the oldest messages in order to make space. +# +# This is useful if mercury server goes offline and the nop needs to buffer +# transmissions. +TransmitQueueMaxSize = 10_000 # Default +# TransmitTimeout controls how long the transmitter will wait for a response +# when sending a message to the mercury server, before aborting and considering +# the transmission to be failed. +TransmitTimeout = "5s" # Default diff --git a/core/config/mercury_config.go b/core/config/mercury_config.go index 1210fd282ef..f16fc4661a5 100644 --- a/core/config/mercury_config.go +++ b/core/config/mercury_config.go @@ -3,6 +3,7 @@ package config import ( "time" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/types" ) @@ -16,8 +17,14 @@ type MercuryTLS interface { CertFile() string } +type MercuryTransmitter interface { + TransmitQueueMaxSize() uint32 + TransmitTimeout() commonconfig.Duration +} + type Mercury interface { Credentials(credName string) *types.MercuryCredentials Cache() MercuryCache TLS() MercuryTLS + Transmitter() MercuryTransmitter } diff --git a/core/config/toml/types.go b/core/config/toml/types.go index ed52c21e34e..ba74528b3b6 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -1312,14 +1312,30 @@ func (m *MercuryTLS) ValidateConfig() (err error) { return } +type MercuryTransmitter struct { + TransmitQueueMaxSize *uint32 + TransmitTimeout *commonconfig.Duration +} + +func (m *MercuryTransmitter) setFrom(f *MercuryTransmitter) { + if v := f.TransmitQueueMaxSize; v != nil { + m.TransmitQueueMaxSize = v + } + if v := f.TransmitTimeout; v != nil { + m.TransmitTimeout = v + } +} + type Mercury struct { - Cache MercuryCache `toml:",omitempty"` - TLS MercuryTLS `toml:",omitempty"` + Cache MercuryCache `toml:",omitempty"` + TLS MercuryTLS `toml:",omitempty"` + Transmitter MercuryTransmitter `toml:",omitempty"` } func (m *Mercury) setFrom(f *Mercury) { m.Cache.setFrom(&f.Cache) m.TLS.setFrom(&f.TLS) + m.Transmitter.setFrom(&f.Transmitter) } func (m *Mercury) ValidateConfig() (err error) { diff --git a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go index 1f6c763d280..6cb4ee30be6 100644 --- a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go +++ b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go @@ -57,8 +57,8 @@ type AutomationRegistrar23TriggerRegistrationStorage struct { } var AutomationRegistrarMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60c06040523480156200001157600080fd5b5060405162003483380380620034838339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612c2f620008546000396000818161027b015281816105a601526106390152600081816104b301528181610a0301528181610a6c0152818161168501526116dc0152612c2f6000f3fe6080604052600436106101295760003560e01c806388b12d55116100a5578063accb832311610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063accb832314610461578063b5ff5b411461048157600080fd5b806388b12d55146103085780638da5cb5b146103d3578063a2b1ff94146103fe578063a4c0ed361461044157600080fd5b80635ab1bd53116100fc5780636bf7d75f116100e15780636bf7d75f1461026957806379ba50971461029d5780637e776f7f146102b257600080fd5b80635ab1bd53146101fd57806366ab87f91461024957600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba578063367b9b4f146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611e6f565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611e9f565b610515565b6040516101849190611f24565b6101cd6101c836600461223b565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f636600461227e565b610710565b005b34801561020957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561025557600080fd5b506101fb610264366004612346565b6107a2565b34801561027557600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156102a957600080fd5b506101fb6108e9565b3480156102be57600080fd5b506102f86102cd36600461241c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561031457600080fd5b5061039a610323366004612439565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103df57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610224565b34801561040a57600080fd5b506101cd61041936600461241c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561044d57600080fd5b506101fb61045c366004612452565b6109eb565b34801561046d57600080fd5b506101fb61047c3660046124db565b610b19565b34801561048d57600080fd5b506101fb61049c366004612526565b610c84565b3480156104ad57600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612439565b610d63565b34801561050157600080fd5b506101fb61051036600461241c565b610f2a565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611eba565b600281111561057657610576611eba565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f3e565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fe0909392919063ffffffff16565b61070a82336110c2565b92915050565b610718611529565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6107aa611529565b80518251146107e5576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b82518110156108ba578181815181106108435761084361256f565b6020026020010151600460008584815181106108615761086161256f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806108b2906125cd565b915050610828565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461096f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a5a576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a688284018461223b565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610af3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610b1181866110c2565b505050505050565b610b21611529565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290610bcd576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001610be091906126b9565b604051602081830303815290604052805190602001209050808314610c31576040517f3f4d605300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260056020526040812090815560010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610c7d610c7785612875565b826115ac565b5050505050565b610c8c611529565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cd957610cd9611eba565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d5690859085908590612881565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610dfd575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e33576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e81576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610efb9273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff1661198f565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f32611529565b610f3b816119ea565b50565b60006bffffffffffffffffffffffff821115610fdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610966565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526110bc9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611adf565b50505050565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611138576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611189576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122191906128ac565b611257576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360405160200161126a91906128c9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112fd576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161137f99989796959493929190612a35565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936114029383911660028111156113c5576113c5611eba565b60028111156113d6576113d6611eba565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611beb565b1561146a57608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561143a83612af0565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061146385836115ac565b9050611521565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610966565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861163c98939792969095939492939092909190600401612b13565b6020604051808303816000875af115801561165b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167f9190612ba1565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168660a0015173ffffffffffffffffffffffffffffffffffffffff16036117a6577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161172f91815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161175c93929190612bba565b6020604051808303816000875af115801561177b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179f91906128ac565b90506118fa565b60a086015160208701516040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526bffffffffffffffffffffffff909216602482015291169063095ea7b3906044016020604051808303816000875af1158015611833573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185791906128ac565b905080156118fa5760208601516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff84169063948108f790604401600060405180830381600087803b1580156118e157600080fd5b505af11580156118f5573d6000803e3d6000fd5b505050505b80611949576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610966565b81857fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8860c0015160405161197e9190611e6f565b60405180910390a350949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119e59084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161103a565b505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610966565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611b41826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611c909092919063ffffffff16565b8051909150156119e55780806020019051810190611b5f91906128ac565b6119e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610966565b60008083516002811115611c0157611c01611eba565b03611c0e5750600061070a565b600183516002811115611c2357611c23611eba565b148015611c56575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611c635750600061070a565b826020015163ffffffff16836040015163ffffffff161015611c875750600161070a565b50600092915050565b60606115218484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611cc49190612c06565b60006040518083038185875af1925050503d8060008114611d01576040519150601f19603f3d011682016040523d82523d6000602084013e611d06565b606091505b5091509150611d1787838387611d22565b979650505050505050565b60608315611db8578251600003611db15773ffffffffffffffffffffffffffffffffffffffff85163b611db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610966565b5081611521565b6115218383815115611dcd5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109669190611e6f565b60005b83811015611e1c578181015183820152602001611e04565b50506000910152565b60008151808452611e3d816020860160208601611e01565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611e826020830184611e25565b9392505050565b803560ff81168114611e9a57600080fd5b919050565b600060208284031215611eb157600080fd5b611e8282611e89565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110611f20577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050611f37828451611ee9565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715611fb057611fb0611f5d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611ffd57611ffd611f5d565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f3b57600080fd5b8035611e9a81612005565b80356bffffffffffffffffffffffff81168114611e9a57600080fd5b803563ffffffff81168114611e9a57600080fd5b600082601f83011261207357600080fd5b813567ffffffffffffffff81111561208d5761208d611f5d565b6120be60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fb6565b8181528460208386010111156120d357600080fd5b816020850160208301376000918101602001919091529392505050565b6000610160828403121561210357600080fd5b61210b611f8c565b905061211682612027565b815261212460208301612032565b602082015261213560408301612027565b60408201526121466060830161204e565b606082015261215760808301611e89565b608082015261216860a08301612027565b60a082015260c082013567ffffffffffffffff8082111561218857600080fd5b61219485838601612062565b60c084015260e08401359150808211156121ad57600080fd5b6121b985838601612062565b60e0840152610100915081840135818111156121d457600080fd5b6121e086828701612062565b8385015250610120915081840135818111156121fb57600080fd5b61220786828701612062565b83850152506101409150818401358181111561222257600080fd5b61222e86828701612062565b8385015250505092915050565b60006020828403121561224d57600080fd5b813567ffffffffffffffff81111561226457600080fd5b611521848285016120f0565b8015158114610f3b57600080fd5b6000806040838503121561229157600080fd5b823561229c81612005565b915060208301356122ac81612270565b809150509250929050565b600067ffffffffffffffff8211156122d1576122d1611f5d565b5060051b60200190565b600082601f8301126122ec57600080fd5b813560206123016122fc836122b7565b611fb6565b82815260059290921b8401810191818101908684111561232057600080fd5b8286015b8481101561233b5780358352918301918301612324565b509695505050505050565b60008060006060848603121561235b57600080fd5b833561236681612005565b925060208481013567ffffffffffffffff8082111561238457600080fd5b818701915087601f83011261239857600080fd5b81356123a66122fc826122b7565b81815260059190911b8301840190848101908a8311156123c557600080fd5b938501935b828510156123ec5784356123dd81612005565b825293850193908501906123ca565b96505050604087013592508083111561240457600080fd5b5050612412868287016122db565b9150509250925092565b60006020828403121561242e57600080fd5b8135611e8281612005565b60006020828403121561244b57600080fd5b5035919050565b6000806000806060858703121561246857600080fd5b843561247381612005565b935060208501359250604085013567ffffffffffffffff8082111561249757600080fd5b818701915087601f8301126124ab57600080fd5b8135818111156124ba57600080fd5b8860208285010111156124cc57600080fd5b95989497505060200194505050565b600080604083850312156124ee57600080fd5b823567ffffffffffffffff81111561250557600080fd5b8301610160818603121561251857600080fd5b946020939093013593505050565b60008060006060848603121561253b57600080fd5b61254484611e89565b925060208401356003811061255857600080fd5b91506125666040850161204e565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036125fe576125fe61259e565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261263a57600080fd5b830160208101925035905067ffffffffffffffff81111561265a57600080fd5b80360382131561266957600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526126e7602082016126cd84612027565b73ffffffffffffffffffffffffffffffffffffffff169052565b60006126f560208401612032565b6bffffffffffffffffffffffff811660408401525061271660408401612027565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061273f6060840161204e565b63ffffffff811660808401525061275860808401611e89565b60ff811660a08401525061276e60a08401612027565b73ffffffffffffffffffffffffffffffffffffffff811660c08401525061279860c0840184612605565b6101608060e08601526127b061018086018385612670565b92506127bf60e0870187612605565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008188870301818901526127f9868685612670565b9550612807818a018a612605565b9550925050610120818887030181890152612823868685612670565b9550612831818a018a612605565b955092505061014081888703018189015261284d868685612670565b955061285b818a018a612605565b955092505080878603018388015250611d17848483612670565b600061070a36836120f0565b60ff84168152606081016128986020830185611ee9565b63ffffffff83166040830152949350505050565b6000602082840312156128be57600080fd5b8151611e8281612270565b602081526128f060208201835173ffffffffffffffffffffffffffffffffffffffff169052565b6000602083015161291160408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612993610180850183611e25565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526129d18584611e25565b9450808801519250506101208187860301818801526129f08584611e25565b945080880151925050610140818786030181880152612a0f8584611e25565b908801518782039092018488015293509050612a2b8382611e25565b9695505050505050565b6000610120808352612a498184018d611e25565b90508281036020840152612a5d818c611e25565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612aa28188611e25565b905082810360c0840152612ab68187611e25565b905082810360e0840152612aca8186611e25565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612b0957612b0961259e565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612b6a81840187611e25565b905082810360c0840152612b7e8186611e25565b905082810360e0840152612b928185611e25565b9b9a5050505050505050505050565b600060208284031215612bb357600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612bfd6060830184611e25565b95945050505050565b60008251612c18818460208701611e01565b919091019291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60c06040523480156200001157600080fd5b5060405162003556380380620035568339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612d02620008546000396000818161029b015281816105a601526106390152600081816104b301528181610b4c01528181610bb50152818161165b01526116b40152612d026000f3fe6080604052600436106101295760003560e01c80637e776f7f116100a5578063a4c0ed3611610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063a4c0ed3614610461578063b5ff5b411461048157600080fd5b80637e776f7f146102d257806388b12d55146103285780638da5cb5b146103f3578063a2b1ff941461041e57600080fd5b8063367b9b4f116100fc57806366ab87f9116100e157806366ab87f9146102695780636bf7d75f1461028957806379ba5097146102bd57600080fd5b8063367b9b4f146101fd5780635ab1bd531461021d57600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba5780633188a2ce146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611f51565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611f81565b610515565b6040516101849190612006565b6101cd6101c836600461231d565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f6366004612352565b610710565b005b34801561020957600080fd5b506101fb61021836600461239c565b610859565b34801561022957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561027557600080fd5b506101fb610284366004612464565b6108eb565b34801561029557600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c957600080fd5b506101fb610a32565b3480156102de57600080fd5b506103186102ed36600461253a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561033457600080fd5b506103ba610343366004612557565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103ff57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610244565b34801561042a57600080fd5b506101cd61043936600461253a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561046d57600080fd5b506101fb61047c366004612570565b610b34565b34801561048d57600080fd5b506101fb61049c3660046125f9565b610c62565b3480156104ad57600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612557565b610d41565b34801561050157600080fd5b506101fb61051036600461253a565b610f08565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611f9c565b600281111561057657610576611f9c565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f1c565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fbe909392919063ffffffff16565b61070a823361109a565b92915050565b610718611501565b60008160405160200161072b91906126f6565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181528282528051602091820120600081815260058352839020606085018452805473ffffffffffffffffffffffffffffffffffffffff808216808852740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169487019490945260019091015490921692840192909252909250610807576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040812090815560010180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561085361084d846128b2565b83611584565b50505050565b610861611501565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6108f3611501565b805182511461092e576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b8251811015610a035781818151811061098c5761098c6128be565b6020026020010151600460008584815181106109aa576109aa6128be565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806109fb9061291c565b915050610971565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ab8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610ba3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610bb18284018461231d565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610c3c576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610c5a818661109a565b505050505050565b610c6a611501565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cb757610cb7611f9c565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d3490859085908590612954565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610ddb575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e11576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e5f576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610ed99273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff166118ef565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f10611501565b610f198161194a565b50565b60006bffffffffffffffffffffffff821115610fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610aaf565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526108539085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a3f565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611110576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611161576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f9919061297f565b61122f576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001611242919061299c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112d5576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161135799989796959493929190612b08565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936113da93839116600281111561139d5761139d611f9c565b60028111156113ae576113ae611f9c565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611b4b565b1561144257608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561141283612bc3565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061143b8583611584565b90506114f9565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610aaf565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861161498939792969095939492939092909190600401612be6565b6020604051808303816000875af1158015611633573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116579190612c74565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16036117ce5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161170791815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161173493929190612c8d565b6020604051808303816000875af1158015611753573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611777919061297f565b9050806117c8576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610aaf565b506118aa565b61180f8286602001516bffffffffffffffffffffffff168760a0015173ffffffffffffffffffffffffffffffffffffffff16611bf09092919063ffffffff16565b60208501516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff83169063948108f790604401600060405180830381600087803b15801561189157600080fd5b505af11580156118a5573d6000803e3d6000fd5b505050505b80847fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8760c001516040516118df9190611f51565b60405180910390a3949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119459084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611018565b505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036119c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610aaf565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611aa1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d729092919063ffffffff16565b8051909150156119455780806020019051810190611abf919061297f565b611945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610aaf565b60008083516002811115611b6157611b61611f9c565b03611b6e5750600061070a565b600183516002811115611b8357611b83611f9c565b148015611bb6575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611bc35750600061070a565b826020015163ffffffff16836040015163ffffffff161015611be75750600161070a565b50600092915050565b801580611c9057506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8e9190612c74565b155b611d1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610aaf565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119459084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611018565b60606114f98484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611da69190612cd9565b60006040518083038185875af1925050503d8060008114611de3576040519150601f19603f3d011682016040523d82523d6000602084013e611de8565b606091505b5091509150611df987838387611e04565b979650505050505050565b60608315611e9a578251600003611e935773ffffffffffffffffffffffffffffffffffffffff85163b611e93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aaf565b50816114f9565b6114f98383815115611eaf5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aaf9190611f51565b60005b83811015611efe578181015183820152602001611ee6565b50506000910152565b60008151808452611f1f816020860160208601611ee3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f646020830184611f07565b9392505050565b803560ff81168114611f7c57600080fd5b919050565b600060208284031215611f9357600080fd5b611f6482611f6b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110612002577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050612019828451611fcb565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156120925761209261203f565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156120df576120df61203f565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1957600080fd5b8035611f7c816120e7565b80356bffffffffffffffffffffffff81168114611f7c57600080fd5b803563ffffffff81168114611f7c57600080fd5b600082601f83011261215557600080fd5b813567ffffffffffffffff81111561216f5761216f61203f565b6121a060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612098565b8181528460208386010111156121b557600080fd5b816020850160208301376000918101602001919091529392505050565b600061016082840312156121e557600080fd5b6121ed61206e565b90506121f882612109565b815261220660208301612114565b602082015261221760408301612109565b604082015261222860608301612130565b606082015261223960808301611f6b565b608082015261224a60a08301612109565b60a082015260c082013567ffffffffffffffff8082111561226a57600080fd5b61227685838601612144565b60c084015260e084013591508082111561228f57600080fd5b61229b85838601612144565b60e0840152610100915081840135818111156122b657600080fd5b6122c286828701612144565b8385015250610120915081840135818111156122dd57600080fd5b6122e986828701612144565b83850152506101409150818401358181111561230457600080fd5b61231086828701612144565b8385015250505092915050565b60006020828403121561232f57600080fd5b813567ffffffffffffffff81111561234657600080fd5b6114f9848285016121d2565b60006020828403121561236457600080fd5b813567ffffffffffffffff81111561237b57600080fd5b82016101608185031215611f6457600080fd5b8015158114610f1957600080fd5b600080604083850312156123af57600080fd5b82356123ba816120e7565b915060208301356123ca8161238e565b809150509250929050565b600067ffffffffffffffff8211156123ef576123ef61203f565b5060051b60200190565b600082601f83011261240a57600080fd5b8135602061241f61241a836123d5565b612098565b82815260059290921b8401810191818101908684111561243e57600080fd5b8286015b848110156124595780358352918301918301612442565b509695505050505050565b60008060006060848603121561247957600080fd5b8335612484816120e7565b925060208481013567ffffffffffffffff808211156124a257600080fd5b818701915087601f8301126124b657600080fd5b81356124c461241a826123d5565b81815260059190911b8301840190848101908a8311156124e357600080fd5b938501935b8285101561250a5784356124fb816120e7565b825293850193908501906124e8565b96505050604087013592508083111561252257600080fd5b5050612530868287016123f9565b9150509250925092565b60006020828403121561254c57600080fd5b8135611f64816120e7565b60006020828403121561256957600080fd5b5035919050565b6000806000806060858703121561258657600080fd5b8435612591816120e7565b935060208501359250604085013567ffffffffffffffff808211156125b557600080fd5b818701915087601f8301126125c957600080fd5b8135818111156125d857600080fd5b8860208285010111156125ea57600080fd5b95989497505060200194505050565b60008060006060848603121561260e57600080fd5b61261784611f6b565b925060208401356003811061262b57600080fd5b915061263960408501612130565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261267757600080fd5b830160208101925035905067ffffffffffffffff81111561269757600080fd5b8036038213156126a657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526127246020820161270a84612109565b73ffffffffffffffffffffffffffffffffffffffff169052565b600061273260208401612114565b6bffffffffffffffffffffffff811660408401525061275360408401612109565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061277c60608401612130565b63ffffffff811660808401525061279560808401611f6b565b60ff811660a0840152506127ab60a08401612109565b73ffffffffffffffffffffffffffffffffffffffff811660c0840152506127d560c0840184612642565b6101608060e08601526127ed610180860183856126ad565b92506127fc60e0870187612642565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008188870301818901526128368686856126ad565b9550612844818a018a612642565b95509250506101208188870301818901526128608686856126ad565b955061286e818a018a612642565b955092505061014081888703018189015261288a8686856126ad565b9550612898818a018a612642565b955092505080878603018388015250611df98484836126ad565b600061070a36836121d2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361294d5761294d6128ed565b5060010190565b60ff841681526060810161296b6020830185611fcb565b63ffffffff83166040830152949350505050565b60006020828403121561299157600080fd5b8151611f648161238e565b602081526129c360208201835173ffffffffffffffffffffffffffffffffffffffff169052565b600060208301516129e460408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612a66610180850183611f07565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610100818786030181880152612aa48584611f07565b945080880151925050610120818786030181880152612ac38584611f07565b945080880151925050610140818786030181880152612ae28584611f07565b908801518782039092018488015293509050612afe8382611f07565b9695505050505050565b6000610120808352612b1c8184018d611f07565b90508281036020840152612b30818c611f07565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612b758188611f07565b905082810360c0840152612b898187611f07565b905082810360e0840152612b9d8186611f07565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612bdc57612bdc6128ed565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612c3d81840187611f07565b905082810360c0840152612c518186611f07565b905082810360e0840152612c658185611f07565b9b9a5050505050505050505050565b600060208284031215612c8657600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612cd06060830184611f07565b95945050505050565b60008251612ceb818460208701611ee3565b919091019291505056fea164736f6c6343000813000a", } var AutomationRegistrarABI = AutomationRegistrarMetaData.ABI @@ -408,16 +408,16 @@ func (_AutomationRegistrar *AutomationRegistrarTransactorSession) AcceptOwnershi return _AutomationRegistrar.Contract.AcceptOwnership(&_AutomationRegistrar.TransactOpts) } -func (_AutomationRegistrar *AutomationRegistrarTransactor) Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) { - return _AutomationRegistrar.contract.Transact(opts, "approve", requestParams, hash) +func (_AutomationRegistrar *AutomationRegistrarTransactor) Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) { + return _AutomationRegistrar.contract.Transact(opts, "approve", requestParams) } -func (_AutomationRegistrar *AutomationRegistrarSession) Approve(requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) { - return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams, hash) +func (_AutomationRegistrar *AutomationRegistrarSession) Approve(requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) { + return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams) } -func (_AutomationRegistrar *AutomationRegistrarTransactorSession) Approve(requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) { - return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams, hash) +func (_AutomationRegistrar *AutomationRegistrarTransactorSession) Approve(requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) { + return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams) } func (_AutomationRegistrar *AutomationRegistrarTransactor) Cancel(opts *bind.TransactOpts, hash [32]byte) (*types.Transaction, error) { @@ -1633,7 +1633,7 @@ type AutomationRegistrarInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) + Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) Cancel(opts *bind.TransactOpts, hash [32]byte) (*types.Transaction, error) diff --git a/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go index 891415c7d3a..d08825fa1f4 100644 --- a/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go @@ -46,7 +46,7 @@ type AutomationRegistryBase23BillingOverrides struct { var AutomationRegistryLogicAMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicB2_3\",\"name\":\"logicB\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b506040516200477c3803806200477c83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e0516101005161012051610140516101605161406862000714600039600081816088015260de01526000505060005050600081816111bd01526114d60152600050506000505060005050600050506140686000f3fe608060405260043610620000865760003560e01c80638e86139b11620000555780638e86139b1462000192578063c62cf68414620001b7578063c804802214620001eb578063f2fde38b14620002105762000086565b8063349e8cca14620000ce57806379ba5097146200012857806385c1b0ba14620001405780638da5cb5b1462000165575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015620000c7573d6000f35b3d6000fd5b005b348015620000db57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200013557600080fd5b50620000cc62000235565b3480156200014d57600080fd5b50620000cc6200015f36600462002cac565b62000338565b3480156200017257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16620000fe565b3480156200019f57600080fd5b50620000cc620001b136600462002d85565b62001080565b348015620001c457600080fd5b50620001dc620001d636600462002f43565b62001408565b6040519081526020016200011f565b348015620001f857600080fd5b50620000cc6200020a36600462003038565b620017b5565b3480156200021d57600080fd5b50620000cc6200022f36600462003052565b62001c8d565b60015473ffffffffffffffffffffffffffffffffffffffff163314620002bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600173ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff16600381111562000377576200037762003079565b14158015620003c35750600373ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff166003811115620003c057620003c062003079565b14155b15620003fb576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60165473ffffffffffffffffffffffffffffffffffffffff166200044b576040517fd12d7d8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082900362000487576040517f2c2fc94100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290528190819060008667ffffffffffffffff811115620004f157620004f162002df0565b6040519080825280602002602001820160405280156200051b578160200160208202803683370190505b50905060008767ffffffffffffffff8111156200053c576200053c62002df0565b604051908082528060200260200182016040528015620005d357816020015b604080516101208101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816200055b5790505b50905060008867ffffffffffffffff811115620005f457620005f462002df0565b6040519080825280602002602001820160405280156200062957816020015b6060815260200190600190039081620006135790505b50905060008967ffffffffffffffff8111156200064a576200064a62002df0565b6040519080825280602002602001820160405280156200067f57816020015b6060815260200190600190039081620006695790505b50905060008a67ffffffffffffffff811115620006a057620006a062002df0565b604051908082528060200260200182016040528015620006d557816020015b6060815260200190600190039081620006bf5790505b50905060005b8b81101562000def578c8c82818110620006f957620006f9620030a8565b602090810292909201356000818152600484526040808220815161012081018352815460ff8082161515835261010080830490911615159883019890985263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911694810194909452909a5091985050819003620008305786610100015199508660c001516bffffffffffffffffffffffff1698505b8973ffffffffffffffffffffffffffffffffffffffff1687610100015173ffffffffffffffffffffffffffffffffffffffff1614620008f55773ffffffffffffffffffffffffffffffffffffffff8a166000908152602160205260409020546200089c908a9062003106565b73ffffffffffffffffffffffffffffffffffffffff8b16600081815260216020526040902091909155620008d2908c8b62001ca5565b86610100015199508660c001516bffffffffffffffffffffffff1698506200091e565b80156200091e5760c08701516200091b906bffffffffffffffffffffffff168a6200311c565b98505b620009298862001d39565b60808701516040517f1a5da6c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d8116600483015290911690631a5da6c890602401600060405180830381600087803b1580156200099957600080fd5b505af1158015620009ae573d6000803e3d6000fd5b5050505086858281518110620009c857620009c8620030a8565b60200260200101819052506005600089815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686828151811062000a1c5762000a1c620030a8565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526000898152600790915260409020805462000a5b9062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000a899062003132565b801562000ada5780601f1062000aae5761010080835404028352916020019162000ada565b820191906000526020600020905b81548152906001019060200180831162000abc57829003601f168201915b505050505084828151811062000af45762000af4620030a8565b6020026020010181905250601d6000898152602001908152602001600020805462000b1f9062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000b4d9062003132565b801562000b9e5780601f1062000b725761010080835404028352916020019162000b9e565b820191906000526020600020905b81548152906001019060200180831162000b8057829003601f168201915b505050505083828151811062000bb85762000bb8620030a8565b6020026020010181905250601e6000898152602001908152602001600020805462000be39062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000c119062003132565b801562000c625780601f1062000c365761010080835404028352916020019162000c62565b820191906000526020600020905b81548152906001019060200180831162000c4457829003601f168201915b505050505082828151811062000c7c5762000c7c620030a8565b602090810291909101810191909152600089815260048252604080822080547fffff0000000000000000000000000000000000000000000000000000000000001681556001810183905560020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600790925290812062000d029162002c0f565b6000888152601d6020526040812062000d1b9162002c0f565b6000888152601e6020526040812062000d349162002c0f565b600088815260066020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905562000d7560028962001df0565b5060c0870151604080516bffffffffffffffffffffffff909216825273ffffffffffffffffffffffffffffffffffffffff8d16602083015289917fb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff910160405180910390a28062000de68162003187565b915050620006db565b5073ffffffffffffffffffffffffffffffffffffffff891660009081526021602052604090205462000e2390899062003106565b73ffffffffffffffffffffffffffffffffffffffff8a1660008181526021602052604090209190915562000e59908b8a62001ca5565b60008c8c868167ffffffffffffffff81111562000e7a5762000e7a62002df0565b60405190808252806020026020018201604052801562000ea4578160200160208202803683370190505b508988888860405160200162000ec2989796959493929190620033b9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282526016547faab9edd6000000000000000000000000000000000000000000000000000000008452915190935073ffffffffffffffffffffffffffffffffffffffff808f1693638e86139b939091169163c71249ab91600491869163aab9edd6918482019160209190819003860181865afa15801562000f72573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f98919062003498565b866040518463ffffffff1660e01b815260040162000fb993929190620034bd565b600060405180830381865afa15801562000fd7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200101f9190810190620034e4565b6040518263ffffffff1660e01b81526004016200103d91906200355b565b600060405180830381600087803b1580156200105857600080fd5b505af11580156200106d573d6000803e3d6000fd5b5050505050505050505050505050505050565b6002336000908152601c602052604090205460ff166003811115620010a957620010a962003079565b14158015620010df57506003336000908152601c602052604090205460ff166003811115620010dc57620010dc62003079565b14155b1562001117576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080808080806200112d888a018a62003882565b965096509650965096509650965060005b8751811015620013fc57600073ffffffffffffffffffffffffffffffffffffffff16878281518110620011755762001175620030a8565b60200260200101516080015173ffffffffffffffffffffffffffffffffffffffff16036200128957858181518110620011b257620011b2620030a8565b6020026020010151307f0000000000000000000000000000000000000000000000000000000000000000604051620011ea9062002c4e565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001234573d6000803e3d6000fd5b508782815181106200124a576200124a620030a8565b60200260200101516080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b62001341888281518110620012a257620012a2620030a8565b6020026020010151888381518110620012bf57620012bf620030a8565b6020026020010151878481518110620012dc57620012dc620030a8565b6020026020010151878581518110620012f957620012f9620030a8565b6020026020010151878681518110620013165762001316620030a8565b6020026020010151878781518110620013335762001333620030a8565b602002602001015162001e07565b878181518110620013565762001356620030a8565b60200260200101517f74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a71888381518110620013945762001394620030a8565b602002602001015160c0015133604051620013df9291906bffffffffffffffffffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a280620013f38162003187565b9150506200113e565b50505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff1633148015906200143c57506200143a60093362002324565b155b1562001474576040517fd48b678b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a163b620014c3576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014ce8762002354565b905060008a307f0000000000000000000000000000000000000000000000000000000000000000604051620015039062002c4e565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f0801580156200154d573d6000803e3d6000fd5b5090506200163e826040518061012001604052806000151581526020016000151581526020018d63ffffffff16815260200163ffffffff801681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152602001600063ffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152508b89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915062001e079050565b601680547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690601c6200167683620039b3565b91906101000a81548163ffffffff021916908363ffffffff16021790555050817fbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d0128b8b604051620016ef92919063ffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a2817fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d87876040516200172b929190620039d9565b60405180910390a2817f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664856040516200176591906200355b565b60405180910390a2817f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850846040516200179f91906200355b565b60405180910390a2509998505050505050505050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915290620018d960005473ffffffffffffffffffffffffffffffffffffffff1690565b61010083015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602090815260408083206002015460155482517f57e871e70000000000000000000000000000000000000000000000000000000081529251968616331497506bffffffffffffffffffffffff90911695939416926357e871e7926004808401939192918290030181865afa1580156200197b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019a1919062003a26565b9050836060015163ffffffff16600003620019e8576040517ffbc0357800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606084015163ffffffff9081161462001a2d576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215801562001a60575060008581526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b1562001a98576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8262001aae5762001aab6032826200311c565b90505b6000858152600460205260409020805463ffffffff8084166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff9092169190911790915562001b0b90600290879062001df016565b506000826bffffffffffffffffffffffff168560a001516fffffffffffffffffffffffffffffffff16101562001b7e5760a085015162001b4c908462003a40565b90508460c001516bffffffffffffffffffffffff16816bffffffffffffffffffffffff16111562001b7e575060c08401515b808560c0015162001b90919062003a40565b600087815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010089015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205462001c229183169062003106565b61010086015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604080822092909255905167ffffffffffffffff84169188917f91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f7911819190a3505050505050565b62001c97620025f3565b62001ca28162002678565b50565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905262001d349084906200276f565b505050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331462001d97576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff9081161462001ca2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062001dfe838362002882565b90505b92915050565b601454760100000000000000000000000000000000000000000000900460ff161562001e5f576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175483517c010000000000000000000000000000000000000000000000000000000090910463ffffffff16101562001ec4576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc856040015163ffffffff16108062001f0a5750601654604086015163ffffffff780100000000000000000000000000000000000000000000000090920482169116115b1562001f42576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff161562001fad576040517f6e3b930b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010085015173ffffffffffffffffffffffffffffffffffffffff9081166000908152602260205260409020546701000000000000009004166200201d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846004600088815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050836005600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260076000888152602001908152602001600020908162002262919062003aba565b5060c085015161010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902054620022ad916bffffffffffffffffffffffff16906200311c565b61010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020908152604080832093909355888252601d905220620022f2838262003aba565b506000868152601e602052604090206200230d828262003aba565b506200231b6002876200298d565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151562001dfe565b601554604080517f57e871e70000000000000000000000000000000000000000000000000000000081529051600092839273ffffffffffffffffffffffffffffffffffffffff90911691839183916385df51fd9160019184916357e871e79160048083019260209291908290030181865afa158015620023d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620023fe919062003a26565b6200240a919062003106565b6040518263ffffffff1660e01b81526004016200242991815260200190565b602060405180830381865afa15801562002447573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200246d919062003a26565b60165460408051602081019390935230908301527c0100000000000000000000000000000000000000000000000000000000900463ffffffff166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060045b600f8110156200258157838282815181106200253d576200253d620030a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620025788162003187565b9150506200251d565b5084600181111562002597576200259762003079565b60f81b81600f81518110620025b057620025b0620030a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620025ea8162003be1565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462002676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401620002b3565b565b3373ffffffffffffffffffffffffffffffffffffffff821603620026f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620002b3565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000620027d3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200299b9092919063ffffffff16565b80519091501562001d345780806020019051810190620027f4919062003c24565b62001d34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620002b3565b600081815260018301602052604081205480156200297b576000620028a960018362003106565b8554909150600090620028bf9060019062003106565b90508181146200292b576000866000018281548110620028e357620028e3620030a8565b9060005260206000200154905080876000018481548110620029095762002909620030a8565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200293f576200293f62003c44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062001e01565b600091505062001e01565b5092915050565b600062001dfe8383620029b4565b6060620029ac848460008562002a06565b949350505050565b6000818152600183016020526040812054620029fd5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562001e01565b50600062001e01565b60608247101562002a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401620002b3565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162002ac5919062003c73565b60006040518083038185875af1925050503d806000811462002b04576040519150601f19603f3d011682016040523d82523d6000602084013e62002b09565b606091505b509150915062002b1c8783838762002b27565b979650505050505050565b6060831562002bc257825160000362002bba5773ffffffffffffffffffffffffffffffffffffffff85163b62002bba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620002b3565b5081620029ac565b620029ac838381511562002bd95781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b391906200355b565b50805462002c1d9062003132565b6000825580601f1062002c2e575050565b601f01602090049060005260206000209081019062001ca2919062002c5c565b6103ca8062003c9283390190565b5b8082111562002c73576000815560010162002c5d565b5090565b73ffffffffffffffffffffffffffffffffffffffff8116811462001ca257600080fd5b803562002ca78162002c77565b919050565b60008060006040848603121562002cc257600080fd5b833567ffffffffffffffff8082111562002cdb57600080fd5b818601915086601f83011262002cf057600080fd5b81358181111562002d0057600080fd5b8760208260051b850101111562002d1657600080fd5b6020928301955093505084013562002d2e8162002c77565b809150509250925092565b60008083601f84011262002d4c57600080fd5b50813567ffffffffffffffff81111562002d6557600080fd5b60208301915083602082850101111562002d7e57600080fd5b9250929050565b6000806020838503121562002d9957600080fd5b823567ffffffffffffffff81111562002db157600080fd5b62002dbf8582860162002d39565b90969095509350505050565b803563ffffffff8116811462002ca757600080fd5b80356002811062002ca757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171562002e465762002e4662002df0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562002e965762002e9662002df0565b604052919050565b600067ffffffffffffffff82111562002ebb5762002ebb62002df0565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002ef957600080fd5b813562002f1062002f0a8262002e9e565b62002e4c565b81815284602083860101111562002f2657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c03121562002f6357600080fd5b62002f6e8a62002c9a565b985062002f7e60208b0162002dcb565b975062002f8e60408b0162002c9a565b965062002f9e60608b0162002de0565b955062002fae60808b0162002c9a565b945060a08a013567ffffffffffffffff8082111562002fcc57600080fd5b62002fda8d838e0162002d39565b909650945060c08c013591508082111562002ff457600080fd5b620030028d838e0162002ee7565b935060e08c01359150808211156200301957600080fd5b50620030288c828d0162002ee7565b9150509295985092959850929598565b6000602082840312156200304b57600080fd5b5035919050565b6000602082840312156200306557600080fd5b8135620030728162002c77565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111562001e015762001e01620030d7565b8082018082111562001e015762001e01620030d7565b600181811c908216806200314757607f821691505b60208210810362003181577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620031bb57620031bb620030d7565b5060010190565b600081518084526020808501945080840160005b838110156200329b5781518051151588528381015115158489015260408082015163ffffffff908116918a01919091526060808301518216908a015260808083015173ffffffffffffffffffffffffffffffffffffffff908116918b019190915260a0808401516fffffffffffffffffffffffffffffffff16908b015260c0808401516bffffffffffffffffffffffff16908b015260e080840151909216918a01919091526101009182015116908801526101209096019590820190600101620031d6565b509495945050505050565b600081518084526020808501945080840160005b838110156200329b57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101620032ba565b60005b838110156200330b578181015183820152602001620032f1565b50506000910152565b600081518084526200332e816020860160208601620032ee565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015620033ac5782840389526200339984835162003314565b988501989350908401906001016200337e565b5091979650505050505050565b60e081528760e082015260006101007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a1115620033f657600080fd5b8960051b808c838601378301838103820160208501526200341a8282018b620031c2565b9150508281036040840152620034318189620032a6565b90508281036060840152620034478188620032a6565b905082810360808401526200345d818762003360565b905082810360a084015262003473818662003360565b905082810360c084015262003489818562003360565b9b9a5050505050505050505050565b600060208284031215620034ab57600080fd5b815160ff811681146200307257600080fd5b60ff8416815260ff83166020820152606060408201526000620025ea606083018462003314565b600060208284031215620034f757600080fd5b815167ffffffffffffffff8111156200350f57600080fd5b8201601f810184136200352157600080fd5b80516200353262002f0a8262002e9e565b8181528560208385010111156200354857600080fd5b620025ea826020830160208601620032ee565b60208152600062001dfe602083018462003314565b600067ffffffffffffffff8211156200358d576200358d62002df0565b5060051b60200190565b600082601f830112620035a957600080fd5b81356020620035bc62002f0a8362003570565b82815260059290921b84018101918181019086841115620035dc57600080fd5b8286015b84811015620035f95780358352918301918301620035e0565b509695505050505050565b801515811462001ca257600080fd5b803562002ca78162003604565b80356fffffffffffffffffffffffffffffffff8116811462002ca757600080fd5b80356bffffffffffffffffffffffff8116811462002ca757600080fd5b600082601f8301126200367057600080fd5b813560206200368362002f0a8362003570565b8281526101209283028501820192828201919087851115620036a457600080fd5b8387015b858110156200377e5781818a031215620036c25760008081fd5b620036cc62002e1f565b620036d78262003613565b8152620036e686830162003613565b868201526040620036f981840162002dcb565b9082015260606200370c83820162002dcb565b9082015260806200371f83820162002c9a565b9082015260a06200373283820162003620565b9082015260c06200374583820162003641565b9082015260e06200375883820162002dcb565b908201526101006200376c83820162002c9a565b908201528452928401928101620036a8565b5090979650505050505050565b600082601f8301126200379d57600080fd5b81356020620037b062002f0a8362003570565b82815260059290921b84018101918181019086841115620037d057600080fd5b8286015b84811015620035f9578035620037ea8162002c77565b8352918301918301620037d4565b600082601f8301126200380a57600080fd5b813560206200381d62002f0a8362003570565b82815260059290921b840181019181810190868411156200383d57600080fd5b8286015b84811015620035f957803567ffffffffffffffff811115620038635760008081fd5b620038738986838b010162002ee7565b84525091830191830162003841565b600080600080600080600060e0888a0312156200389e57600080fd5b873567ffffffffffffffff80821115620038b757600080fd5b620038c58b838c0162003597565b985060208a0135915080821115620038dc57600080fd5b620038ea8b838c016200365e565b975060408a01359150808211156200390157600080fd5b6200390f8b838c016200378b565b965060608a01359150808211156200392657600080fd5b620039348b838c016200378b565b955060808a01359150808211156200394b57600080fd5b620039598b838c01620037f8565b945060a08a01359150808211156200397057600080fd5b6200397e8b838c01620037f8565b935060c08a01359150808211156200399557600080fd5b50620039a48a828b01620037f8565b91505092959891949750929550565b600063ffffffff808316818103620039cf57620039cf620030d7565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60006020828403121562003a3957600080fd5b5051919050565b6bffffffffffffffffffffffff828116828216039080821115620029865762002986620030d7565b601f82111562001d3457600081815260208120601f850160051c8101602086101562003a915750805b601f850160051c820191505b8181101562003ab25782815560010162003a9d565b505050505050565b815167ffffffffffffffff81111562003ad75762003ad762002df0565b62003aef8162003ae8845462003132565b8462003a68565b602080601f83116001811462003b45576000841562003b0e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855562003ab2565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101562003b945788860151825594840194600190910190840162003b73565b508582101562003bd157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8051602080830151919081101562003181577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b60006020828403121562003c3757600080fd5b8151620030728162003604565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825162003c87818460208701620032ee565b919091019291505056fe60c060405234801561001057600080fd5b506040516103ca3803806103ca83398101604081905261002f91610076565b600080546001600160a01b0319166001600160a01b039384161790559181166080521660a0526100b9565b80516001600160a01b038116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005a565b92506100a26020850161005a565b91506100b06040850161005a565b90509250925092565b60805160a0516102e76100e36000396000603801526000818160c4015261011701526102e76000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806379188d161461007b578063f00e6a2a146100aa575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610076573d6000f35b3d6000fd5b61008e6100893660046101c1565b6100ee565b6040805192151583526020830191909152015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100a1565b60008054819073ffffffffffffffffffffffffffffffffffffffff16331461011557600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005a91505a61138881101561014957600080fd5b61138881039050856040820482031161016157600080fd5b50803b61016d57600080fd5b6000808551602087016000858af192505a610188908361029a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156101d457600080fd5b82359150602083013567ffffffffffffffff808211156101f357600080fd5b818501915085601f83011261020757600080fd5b81358181111561021957610219610192565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561025f5761025f610192565b8160405282815288602084870101111561027857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b818103818111156102d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000aa164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b50604051620047913803806200479183398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e0516101005161012051610140516101605161407d62000714600039600081816088015260de01526000505060005050600081816111d201526114eb01526000505060005050600050506000505061407d6000f3fe608060405260043610620000865760003560e01c80638e86139b11620000555780638e86139b1462000192578063c62cf68414620001b7578063c804802214620001eb578063f2fde38b14620002105762000086565b8063349e8cca14620000ce57806379ba5097146200012857806385c1b0ba14620001405780638da5cb5b1462000165575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015620000c7573d6000f35b3d6000fd5b005b348015620000db57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200013557600080fd5b50620000cc62000235565b3480156200014d57600080fd5b50620000cc6200015f36600462002cc1565b62000338565b3480156200017257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16620000fe565b3480156200019f57600080fd5b50620000cc620001b136600462002d9a565b62001095565b348015620001c457600080fd5b50620001dc620001d636600462002f58565b6200141d565b6040519081526020016200011f565b348015620001f857600080fd5b50620000cc6200020a3660046200304d565b620017ca565b3480156200021d57600080fd5b50620000cc6200022f36600462003067565b62001ca2565b60015473ffffffffffffffffffffffffffffffffffffffff163314620002bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600173ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff1660038111156200037757620003776200308e565b14158015620003c35750600373ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff166003811115620003c057620003c06200308e565b14155b15620003fb576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60165473ffffffffffffffffffffffffffffffffffffffff166200044b576040517fd12d7d8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082900362000487576040517f2c2fc94100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290528190819060008667ffffffffffffffff811115620004f157620004f162002e05565b6040519080825280602002602001820160405280156200051b578160200160208202803683370190505b50905060008767ffffffffffffffff8111156200053c576200053c62002e05565b604051908082528060200260200182016040528015620005d357816020015b604080516101208101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816200055b5790505b50905060008867ffffffffffffffff811115620005f457620005f462002e05565b6040519080825280602002602001820160405280156200062957816020015b6060815260200190600190039081620006135790505b50905060008967ffffffffffffffff8111156200064a576200064a62002e05565b6040519080825280602002602001820160405280156200067f57816020015b6060815260200190600190039081620006695790505b50905060008a67ffffffffffffffff811115620006a057620006a062002e05565b604051908082528060200260200182016040528015620006d557816020015b6060815260200190600190039081620006bf5790505b50905060005b8b81101562000e04578c8c82818110620006f957620006f9620030bd565b602090810292909201356000818152600484526040808220815161012081018352815460ff8082161515835261010080830490911615159883019890985263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911694810194909452909a5091985050819003620008305786610100015199508660c001516bffffffffffffffffffffffff1698505b8973ffffffffffffffffffffffffffffffffffffffff1687610100015173ffffffffffffffffffffffffffffffffffffffff1614620008f55773ffffffffffffffffffffffffffffffffffffffff8a166000908152602160205260409020546200089c908a906200311b565b73ffffffffffffffffffffffffffffffffffffffff8b16600081815260216020526040902091909155620008d2908c8b62001cba565b86610100015199508660c001516bffffffffffffffffffffffff1698506200091e565b80156200091e5760c08701516200091b906bffffffffffffffffffffffff168a62003131565b98505b620009298862001d4e565b60808701516040517f1a5da6c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d8116600483015290911690631a5da6c890602401600060405180830381600087803b1580156200099957600080fd5b505af1158015620009ae573d6000803e3d6000fd5b5050505086858281518110620009c857620009c8620030bd565b60200260200101819052506005600089815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686828151811062000a1c5762000a1c620030bd565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526000898152600790915260409020805462000a5b9062003147565b80601f016020809104026020016040519081016040528092919081815260200182805462000a899062003147565b801562000ada5780601f1062000aae5761010080835404028352916020019162000ada565b820191906000526020600020905b81548152906001019060200180831162000abc57829003601f168201915b505050505084828151811062000af45762000af4620030bd565b6020026020010181905250601d6000898152602001908152602001600020805462000b1f9062003147565b80601f016020809104026020016040519081016040528092919081815260200182805462000b4d9062003147565b801562000b9e5780601f1062000b725761010080835404028352916020019162000b9e565b820191906000526020600020905b81548152906001019060200180831162000b8057829003601f168201915b505050505083828151811062000bb85762000bb8620030bd565b6020026020010181905250601e6000898152602001908152602001600020805462000be39062003147565b80601f016020809104026020016040519081016040528092919081815260200182805462000c119062003147565b801562000c625780601f1062000c365761010080835404028352916020019162000c62565b820191906000526020600020905b81548152906001019060200180831162000c4457829003601f168201915b505050505082828151811062000c7c5762000c7c620030bd565b602090810291909101810191909152600089815260048252604080822080547fffff0000000000000000000000000000000000000000000000000000000000001681556001810183905560020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600790925290812062000d029162002c24565b6000888152601d6020526040812062000d1b9162002c24565b6000888152601e6020526040812062000d349162002c24565b600088815260066020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811690915560059092529091208054909116905562000d8a60028962001e05565b5060c0870151604080516bffffffffffffffffffffffff909216825273ffffffffffffffffffffffffffffffffffffffff8d16602083015289917fb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff910160405180910390a28062000dfb816200319c565b915050620006db565b5073ffffffffffffffffffffffffffffffffffffffff891660009081526021602052604090205462000e389089906200311b565b73ffffffffffffffffffffffffffffffffffffffff8a1660008181526021602052604090209190915562000e6e908b8a62001cba565b60008c8c868167ffffffffffffffff81111562000e8f5762000e8f62002e05565b60405190808252806020026020018201604052801562000eb9578160200160208202803683370190505b508988888860405160200162000ed7989796959493929190620033ce565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282526016547faab9edd6000000000000000000000000000000000000000000000000000000008452915190935073ffffffffffffffffffffffffffffffffffffffff808f1693638e86139b939091169163c71249ab91600491869163aab9edd6918482019160209190819003860181865afa15801562000f87573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000fad9190620034ad565b866040518463ffffffff1660e01b815260040162000fce93929190620034d2565b600060405180830381865afa15801562000fec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052620010349190810190620034f9565b6040518263ffffffff1660e01b815260040162001052919062003570565b600060405180830381600087803b1580156200106d57600080fd5b505af115801562001082573d6000803e3d6000fd5b5050505050505050505050505050505050565b6002336000908152601c602052604090205460ff166003811115620010be57620010be6200308e565b14158015620010f457506003336000908152601c602052604090205460ff166003811115620010f157620010f16200308e565b14155b156200112c576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080808080808062001142888a018a62003897565b965096509650965096509650965060005b87518110156200141157600073ffffffffffffffffffffffffffffffffffffffff168782815181106200118a576200118a620030bd565b60200260200101516080015173ffffffffffffffffffffffffffffffffffffffff16036200129e57858181518110620011c757620011c7620030bd565b6020026020010151307f0000000000000000000000000000000000000000000000000000000000000000604051620011ff9062002c63565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001249573d6000803e3d6000fd5b508782815181106200125f576200125f620030bd565b60200260200101516080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b62001356888281518110620012b757620012b7620030bd565b6020026020010151888381518110620012d457620012d4620030bd565b6020026020010151878481518110620012f157620012f1620030bd565b60200260200101518785815181106200130e576200130e620030bd565b60200260200101518786815181106200132b576200132b620030bd565b6020026020010151878781518110620013485762001348620030bd565b602002602001015162001e1c565b8781815181106200136b576200136b620030bd565b60200260200101517f74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a71888381518110620013a957620013a9620030bd565b602002602001015160c0015133604051620013f49291906bffffffffffffffffffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a28062001408816200319c565b91505062001153565b50505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff1633148015906200145157506200144f60093362002339565b155b1562001489576040517fd48b678b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a163b620014d8576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014e38762002369565b905060008a307f0000000000000000000000000000000000000000000000000000000000000000604051620015189062002c63565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001562573d6000803e3d6000fd5b50905062001653826040518061012001604052806000151581526020016000151581526020018d63ffffffff16815260200163ffffffff801681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152602001600063ffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152508b89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915062001e1c9050565b601680547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690601c6200168b83620039c8565b91906101000a81548163ffffffff021916908363ffffffff16021790555050817fbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d0128b8b6040516200170492919063ffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a2817fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d878760405162001740929190620039ee565b60405180910390a2817f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664856040516200177a919062003570565b60405180910390a2817f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf485084604051620017b4919062003570565b60405180910390a2509998505050505050505050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915290620018ee60005473ffffffffffffffffffffffffffffffffffffffff1690565b61010083015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602090815260408083206002015460155482517f57e871e70000000000000000000000000000000000000000000000000000000081529251968616331497506bffffffffffffffffffffffff90911695939416926357e871e7926004808401939192918290030181865afa15801562001990573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b6919062003a3b565b9050836060015163ffffffff16600003620019fd576040517ffbc0357800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606084015163ffffffff9081161462001a42576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215801562001a75575060008581526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b1562001aad576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8262001ac35762001ac060328262003131565b90505b6000858152600460205260409020805463ffffffff8084166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff9092169190911790915562001b2090600290879062001e0516565b506000826bffffffffffffffffffffffff168560a001516fffffffffffffffffffffffffffffffff16101562001b935760a085015162001b61908462003a55565b90508460c001516bffffffffffffffffffffffff16816bffffffffffffffffffffffff16111562001b93575060c08401515b808560c0015162001ba5919062003a55565b600087815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010089015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205462001c37918316906200311b565b61010086015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604080822092909255905167ffffffffffffffff84169188917f91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f7911819190a3505050505050565b62001cac62002608565b62001cb7816200268d565b50565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905262001d4990849062002784565b505050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331462001dac576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff9081161462001cb7576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062001e13838362002897565b90505b92915050565b601454760100000000000000000000000000000000000000000000900460ff161562001e74576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175483517c010000000000000000000000000000000000000000000000000000000090910463ffffffff16101562001ed9576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc856040015163ffffffff16108062001f1f5750601654604086015163ffffffff780100000000000000000000000000000000000000000000000090920482169116115b1562001f57576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff161562001fc2576040517f6e3b930b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010085015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602052604090205467010000000000000090041662002032576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846004600088815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050836005600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260076000888152602001908152602001600020908162002277919062003acf565b5060c085015161010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902054620022c2916bffffffffffffffffffffffff169062003131565b61010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020908152604080832093909355888252601d90522062002307838262003acf565b506000868152601e6020526040902062002322828262003acf565b5062002330600287620029a2565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151562001e13565b601554604080517f57e871e70000000000000000000000000000000000000000000000000000000081529051600092839273ffffffffffffffffffffffffffffffffffffffff90911691839183916385df51fd9160019184916357e871e79160048083019260209291908290030181865afa158015620023ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002413919062003a3b565b6200241f91906200311b565b6040518263ffffffff1660e01b81526004016200243e91815260200190565b602060405180830381865afa1580156200245c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002482919062003a3b565b60165460408051602081019390935230908301527c0100000000000000000000000000000000000000000000000000000000900463ffffffff166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060045b600f811015620025965783828281518110620025525762002552620030bd565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806200258d816200319c565b91505062002532565b50846001811115620025ac57620025ac6200308e565b60f81b81600f81518110620025c557620025c5620030bd565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620025ff8162003bf6565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146200268b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401620002b3565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036200270e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620002b3565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000620027e8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620029b09092919063ffffffff16565b80519091501562001d49578080602001905181019062002809919062003c39565b62001d49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620002b3565b6000818152600183016020526040812054801562002990576000620028be6001836200311b565b8554909150600090620028d4906001906200311b565b905081811462002940576000866000018281548110620028f857620028f8620030bd565b90600052602060002001549050808760000184815481106200291e576200291e620030bd565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062002954576200295462003c59565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062001e16565b600091505062001e16565b5092915050565b600062001e138383620029c9565b6060620029c1848460008562002a1b565b949350505050565b600081815260018301602052604081205462002a125750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562001e16565b50600062001e16565b60608247101562002aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401620002b3565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162002ada919062003c88565b60006040518083038185875af1925050503d806000811462002b19576040519150601f19603f3d011682016040523d82523d6000602084013e62002b1e565b606091505b509150915062002b318783838762002b3c565b979650505050505050565b6060831562002bd757825160000362002bcf5773ffffffffffffffffffffffffffffffffffffffff85163b62002bcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620002b3565b5081620029c1565b620029c1838381511562002bee5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b3919062003570565b50805462002c329062003147565b6000825580601f1062002c43575050565b601f01602090049060005260206000209081019062001cb7919062002c71565b6103ca8062003ca783390190565b5b8082111562002c88576000815560010162002c72565b5090565b73ffffffffffffffffffffffffffffffffffffffff8116811462001cb757600080fd5b803562002cbc8162002c8c565b919050565b60008060006040848603121562002cd757600080fd5b833567ffffffffffffffff8082111562002cf057600080fd5b818601915086601f83011262002d0557600080fd5b81358181111562002d1557600080fd5b8760208260051b850101111562002d2b57600080fd5b6020928301955093505084013562002d438162002c8c565b809150509250925092565b60008083601f84011262002d6157600080fd5b50813567ffffffffffffffff81111562002d7a57600080fd5b60208301915083602082850101111562002d9357600080fd5b9250929050565b6000806020838503121562002dae57600080fd5b823567ffffffffffffffff81111562002dc657600080fd5b62002dd48582860162002d4e565b90969095509350505050565b803563ffffffff8116811462002cbc57600080fd5b80356002811062002cbc57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171562002e5b5762002e5b62002e05565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562002eab5762002eab62002e05565b604052919050565b600067ffffffffffffffff82111562002ed05762002ed062002e05565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002f0e57600080fd5b813562002f2562002f1f8262002eb3565b62002e61565b81815284602083860101111562002f3b57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c03121562002f7857600080fd5b62002f838a62002caf565b985062002f9360208b0162002de0565b975062002fa360408b0162002caf565b965062002fb360608b0162002df5565b955062002fc360808b0162002caf565b945060a08a013567ffffffffffffffff8082111562002fe157600080fd5b62002fef8d838e0162002d4e565b909650945060c08c01359150808211156200300957600080fd5b620030178d838e0162002efc565b935060e08c01359150808211156200302e57600080fd5b506200303d8c828d0162002efc565b9150509295985092959850929598565b6000602082840312156200306057600080fd5b5035919050565b6000602082840312156200307a57600080fd5b8135620030878162002c8c565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111562001e165762001e16620030ec565b8082018082111562001e165762001e16620030ec565b600181811c908216806200315c57607f821691505b60208210810362003196577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620031d057620031d0620030ec565b5060010190565b600081518084526020808501945080840160005b83811015620032b05781518051151588528381015115158489015260408082015163ffffffff908116918a01919091526060808301518216908a015260808083015173ffffffffffffffffffffffffffffffffffffffff908116918b019190915260a0808401516fffffffffffffffffffffffffffffffff16908b015260c0808401516bffffffffffffffffffffffff16908b015260e080840151909216918a01919091526101009182015116908801526101209096019590820190600101620031eb565b509495945050505050565b600081518084526020808501945080840160005b83811015620032b057815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101620032cf565b60005b838110156200332057818101518382015260200162003306565b50506000910152565b600081518084526200334381602086016020860162003303565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015620033c1578284038952620033ae84835162003329565b9885019893509084019060010162003393565b5091979650505050505050565b60e081528760e082015260006101007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a11156200340b57600080fd5b8960051b808c838601378301838103820160208501526200342f8282018b620031d7565b9150508281036040840152620034468189620032bb565b905082810360608401526200345c8188620032bb565b9050828103608084015262003472818762003375565b905082810360a084015262003488818662003375565b905082810360c08401526200349e818562003375565b9b9a5050505050505050505050565b600060208284031215620034c057600080fd5b815160ff811681146200308757600080fd5b60ff8416815260ff83166020820152606060408201526000620025ff606083018462003329565b6000602082840312156200350c57600080fd5b815167ffffffffffffffff8111156200352457600080fd5b8201601f810184136200353657600080fd5b80516200354762002f1f8262002eb3565b8181528560208385010111156200355d57600080fd5b620025ff82602083016020860162003303565b60208152600062001e13602083018462003329565b600067ffffffffffffffff821115620035a257620035a262002e05565b5060051b60200190565b600082601f830112620035be57600080fd5b81356020620035d162002f1f8362003585565b82815260059290921b84018101918181019086841115620035f157600080fd5b8286015b848110156200360e5780358352918301918301620035f5565b509695505050505050565b801515811462001cb757600080fd5b803562002cbc8162003619565b80356fffffffffffffffffffffffffffffffff8116811462002cbc57600080fd5b80356bffffffffffffffffffffffff8116811462002cbc57600080fd5b600082601f8301126200368557600080fd5b813560206200369862002f1f8362003585565b8281526101209283028501820192828201919087851115620036b957600080fd5b8387015b85811015620037935781818a031215620036d75760008081fd5b620036e162002e34565b620036ec8262003628565b8152620036fb86830162003628565b8682015260406200370e81840162002de0565b9082015260606200372183820162002de0565b9082015260806200373483820162002caf565b9082015260a06200374783820162003635565b9082015260c06200375a83820162003656565b9082015260e06200376d83820162002de0565b908201526101006200378183820162002caf565b908201528452928401928101620036bd565b5090979650505050505050565b600082601f830112620037b257600080fd5b81356020620037c562002f1f8362003585565b82815260059290921b84018101918181019086841115620037e557600080fd5b8286015b848110156200360e578035620037ff8162002c8c565b8352918301918301620037e9565b600082601f8301126200381f57600080fd5b813560206200383262002f1f8362003585565b82815260059290921b840181019181810190868411156200385257600080fd5b8286015b848110156200360e57803567ffffffffffffffff811115620038785760008081fd5b620038888986838b010162002efc565b84525091830191830162003856565b600080600080600080600060e0888a031215620038b357600080fd5b873567ffffffffffffffff80821115620038cc57600080fd5b620038da8b838c01620035ac565b985060208a0135915080821115620038f157600080fd5b620038ff8b838c0162003673565b975060408a01359150808211156200391657600080fd5b620039248b838c01620037a0565b965060608a01359150808211156200393b57600080fd5b620039498b838c01620037a0565b955060808a01359150808211156200396057600080fd5b6200396e8b838c016200380d565b945060a08a01359150808211156200398557600080fd5b620039938b838c016200380d565b935060c08a0135915080821115620039aa57600080fd5b50620039b98a828b016200380d565b91505092959891949750929550565b600063ffffffff808316818103620039e457620039e4620030ec565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60006020828403121562003a4e57600080fd5b5051919050565b6bffffffffffffffffffffffff8281168282160390808211156200299b576200299b620030ec565b601f82111562001d4957600081815260208120601f850160051c8101602086101562003aa65750805b601f850160051c820191505b8181101562003ac75782815560010162003ab2565b505050505050565b815167ffffffffffffffff81111562003aec5762003aec62002e05565b62003b048162003afd845462003147565b8462003a7d565b602080601f83116001811462003b5a576000841562003b235750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855562003ac7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101562003ba95788860151825594840194600190910190840162003b88565b508582101562003be657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8051602080830151919081101562003196577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b60006020828403121562003c4c57600080fd5b8151620030878162003619565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825162003c9c81846020870162003303565b919091019291505056fe60c060405234801561001057600080fd5b506040516103ca3803806103ca83398101604081905261002f91610076565b600080546001600160a01b0319166001600160a01b039384161790559181166080521660a0526100b9565b80516001600160a01b038116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005a565b92506100a26020850161005a565b91506100b06040850161005a565b90509250925092565b60805160a0516102e76100e36000396000603801526000818160c4015261011701526102e76000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806379188d161461007b578063f00e6a2a146100aa575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610076573d6000f35b3d6000fd5b61008e6100893660046101c1565b6100ee565b6040805192151583526020830191909152015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100a1565b60008054819073ffffffffffffffffffffffffffffffffffffffff16331461011557600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005a91505a61138881101561014957600080fd5b61138881039050856040820482031161016157600080fd5b50803b61016d57600080fd5b6000808551602087016000858af192505a610188908361029a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156101d457600080fd5b82359150602083013567ffffffffffffffff808211156101f357600080fd5b818501915085601f83011261020757600080fd5b81358181111561021957610219610192565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561025f5761025f610192565b8160405282815288602084870101111561027857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b818103818111156102d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000aa164736f6c6343000813000a", } var AutomationRegistryLogicAABI = AutomationRegistryLogicAMetaData.ABI diff --git a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go index 1edcb07dc6f..29bfe3155f5 100644 --- a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go @@ -65,7 +65,7 @@ type AutomationRegistryBase23OnchainConfig struct { var AutomationRegistryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicA2_3\",\"name\":\"logicA\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b506040516200668a3803806200668a83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615f56620007346000396000818160be01526101910152600050506000505060005050600050506000613b1701526000505060008181610de701528181610ef5015281816110200152818161106a015281816116ec01526131400152615f566000f3fe6080604052600436106100bc5760003560e01c80638da5cb5b11610074578063b1dc65a41161004e578063b1dc65a4146102f6578063e3d0e71214610316578063f2fde38b14610336576100bc565b80638da5cb5b14610265578063a4c0ed3614610290578063afcb95d7146102b0576100bc565b8063349e8cca116100a5578063349e8cca1461018257806379ba5097146101d657806381ff7048146101eb576100bc565b80630870d3a114610103578063181f5a7714610123575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100fc573d6000f35b3d6000fd5b005b34801561010f57600080fd5b5061010161011e366004614c9d565b610356565b34801561012f57600080fd5b5061016c6040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b6040516101799190614e19565b60405180910390f35b34801561018e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610179565b3480156101e257600080fd5b50610101610ccd565b3480156101f757600080fd5b5061024260175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610179565b34801561027157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101b1565b34801561029c57600080fd5b506101016102ab366004614e75565b610dcf565b3480156102bc57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610179565b34801561030257600080fd5b50610101610311366004614f16565b6110eb565b34801561032257600080fd5b50610101610331366004614fcd565b6113cc565b34801561034257600080fd5b5061010161035136600461509a565b611406565b61035e61141a565b601f8851111561039a576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103d7576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103f657506103ee8660036150e6565b60ff16885111155b1561042d576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051825114610468576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610472828261149d565b61047c8888611ad5565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050604051806101600160405280866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866000015163ffffffff168152602001866020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200186610100015173ffffffffffffffffffffffffffffffffffffffff168152602001601660010160149054906101000a900463ffffffff1663ffffffff168152602001601660010160189054906101000a900463ffffffff1663ffffffff168152602001866040015163ffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018660c0015163ffffffff1681526020018660e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050846101600151601981905550846101800151601a81905550846101a00151601b819055506000601660010160189054906101000a900463ffffffff169050856101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa69190615102565b601780547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601491610b1d9185917401000000000000000000000000000000000000000090041661511b565b92506101000a81548163ffffffff021916908363ffffffff160217905550600086604051602001610b4e9190615189565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610bb3904690309074010000000000000000000000000000000000000000900463ffffffff168d8d8d878d8d612196565b6013556000610bc26009612240565b90505b8015610bff57610bec610be4610bdc60018461530f565b600990612250565b600990612263565b5080610bf781615322565b915050610bc5565b5060005b876101c0015151811015610c5657610c43886101c001518281518110610c2b57610c2b615357565b6020026020010151600961228590919063ffffffff16565b5080610c4e81615386565b915050610c03565b506013546017546040517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0592610cb99286927401000000000000000000000000000000000000000090910463ffffffff16908f908f908f9089908f908f906153be565b60405180910390a150505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e3e576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610e78576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e8682840184615454565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610ee1576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610f65576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610fa490859070010000000000000000000000000000000090046bffffffffffffffffffffffff1661546d565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168252602190522054611053908590615492565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015291925061124f576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16611298576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a35146112d4576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101516112e49060016154a5565b60ff16861415806112f55750858414155b1561132c576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61133c8a8a8a8a8a8a8a8a6122a7565b60006113488a8a612510565b905060208b0135600881901c63ffffffff166113658484876125c9565b836020015163ffffffff168163ffffffff1611156113bd57601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b6000806000858060200190518101906113e5919061568f565b9250925092506113fb8989898689898888610356565b505050505050505050565b61140e61141a565b611417816131b6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461149b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d4a565b565b60005b60245481101561155b5760226000602483815481106114c1576114c1615357565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690558061155381615386565b9150506114a0565b50611568602460006146f1565b60255460ff1660005b8351811015611acf57600084828151811061158e5761158e615357565b6020026020010151905060008483815181106115ac576115ac615357565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611601573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611625919061583a565b60ff16816060015160ff161415806116b35750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611687573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ab919061583a565b60ff16600814155b156116ea576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156117565750600184600181111561175457611754615857565b145b1561178d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821615806117c85750604081015173ffffffffffffffffffffffffffffffffffffffff16155b156117ff576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82811660009081526022602052604090205467010000000000000090041615611869576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611ab2908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a250508080611ac790615386565b915050611571565b50505050565b60005b600e54811015611b4c57611b39600e8281548110611af857611af8615357565b600091825260209091200154601454600e5473ffffffffffffffffffffffffffffffffffffffff909216916bffffffffffffffffffffffff909116906132ab565b5080611b4481615386565b915050611ad8565b5060255460009060ff16815b600e54811015611cbd57600e8181548110611b7557611b75615357565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611bb257611bb2615357565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611c5457611c54615857565b148015611c99575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611cab57611ca9600f84612285565b505b80611cb581615386565b915050611b58565b50611cca600d60006146f1565b611cd6600e60006146f1565b6040805160808101825260008082526020820181905291810182905260608101829052905b855181101561216657600c6000878381518110611d1a57611d1a615357565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611d85576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16868281518110611daf57611daf615357565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611e04576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c6000888481518110611e3557611e35615357565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558451859082908110611edd57611edd615357565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611f4d576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250612008576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169490941717919091169290921791909117905583600181111561214257612142615857565b0361215457612152600f85612263565b505b8061215e81615386565b915050611cfb565b50845161217a90600d90602088019061470f565b50835161218e90600e90602087019061470f565b505050505050565b6000808a8a8a8a8a8a8a8a8a6040516020016121ba99989796959493929190615886565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b600061224a825490565b92915050565b600061225c83836134b3565b9392505050565b600061225c8373ffffffffffffffffffffffffffffffffffffffff84166134dd565b600061225c8373ffffffffffffffffffffffffffffffffffffffff84166135d7565b600087876040516122b992919061591b565b6040519081900381206122d0918b9060200161592b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b888110156124a75760018587836020811061233c5761233c615357565b61234991901a601b6154a5565b8c8c8581811061235b5761235b615357565b905060200201358b8b8681811061237457612374615357565b90506020020135604051600081526020016040526040516123b1949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156123d3573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612481576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061249f90615386565b91505061231f565b50827e01010101010101010101010101010101010101010101010101010101010101841614612502576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6125496040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b600061255783850185615a1c565b604081015151606082015151919250908114158061257a57508082608001515114155b8061258a5750808260a001515114155b156125c1576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff8111156125e9576125e96147a6565b6040519080825280602002602001820160405280156126b557816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816126075790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127779190615102565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ef9190615102565b905060005b866040015151811015612c7f57600460008860400151838151811061281b5761281b615357565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911691810191909152855186908390811061293e5761293e615357565b6020026020010151600001819052506129738760400151828151811061296657612966615357565b6020026020010151613626565b85828151811061298557612985615357565b60200260200101516060019060018111156129a2576129a2615857565b908160018111156129b5576129b5615857565b81525050612a19876040015182815181106129d2576129d2615357565b602002602001015184896080015184815181106129f1576129f1615357565b6020026020010151888581518110612a0b57612a0b615357565b60200260200101518c6136d1565b868381518110612a2b57612a2b615357565b6020026020010151602001878481518110612a4857612a48615357565b602002602001015160c0018281525082151515158152505050848181518110612a7357612a73615357565b60200260200101516020015115612aa357600184600001818151612a979190615b09565b61ffff16905250612aa8565b612c6d565b612b0e858281518110612abd57612abd615357565b6020026020010151600001516080015188606001518381518110612ae357612ae3615357565b60200260200101518960a001518481518110612b0157612b01615357565b60200260200101516137f0565b868381518110612b2057612b20615357565b6020026020010151604001878481518110612b3d57612b3d615357565b6020026020010151608001828152508215151515815250505087608001516001612b6791906154a5565b612b759060ff166040615b24565b6103a48860a001518381518110612b8e57612b8e615357565b602002602001015151612ba19190615492565b612bab9190615492565b858281518110612bbd57612bbd615357565b602002602001015160a0018181525050848181518110612bdf57612bdf615357565b602002602001015160a0015184606001818151612bfc9190615492565b9052508451859082908110612c1357612c13615357565b60200260200101516080015186612c2a919061530f565b9550612c6d87604001518281518110612c4557612c45615357565b602002602001015184878481518110612c6057612c60615357565b6020026020010151613a0b565b80612c7781615386565b9150506127f4565b50825161ffff16600003612c965750505050505050565b61c800612ca4366010615b24565b5a612caf908861530f565b612cb99190615492565b612cc39190615492565b83519095506123f090612cda9061ffff1687615b6a565b612ce49190615492565b6040805160808101825260008082526020820181905291810182905260608101829052919650612d1389613b10565b905060005b88604001515181101561304f57868181518110612d3757612d37615357565b6020026020010151602001511561303d57801580612dcf575086612d5c60018361530f565b81518110612d6c57612d6c615357565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612da557612da5615357565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612e0357612e008a888381518110612dea57612dea615357565b6020026020010151600001516101000151613bfa565b92505b6000612f218b6040518061012001604052808b8681518110612e2757612e27615357565b60200260200101516080015181526020018c81526020018a606001518c8781518110612e5557612e55615357565b602002602001015160a001518a612e6c9190615b24565b612e769190615b6a565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612ea757612ea7615357565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612ef657612ef6615357565b60200260200101518b8681518110612f1057612f10615357565b602002602001015160000151613d76565b9050806060015187604001818151612f39919061546d565b6bffffffffffffffffffffffff169052506040810151602088018051612f6090839061546d565b6bffffffffffffffffffffffff169052508751889083908110612f8557612f85615357565b60200260200101516040015115158a604001518381518110612fa957612fa9615357565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83606001518460400151612fe6919061546d565b8b8681518110612ff857612ff8615357565b6020026020010151608001518d8f60800151888151811061301b5761301b615357565b60200260200101516040516130339493929190615b7e565b60405180910390a3505b8061304781615386565b915050612d18565b505050602083810151336000908152600b9092526040909120805460029061308c9084906201000090046bffffffffffffffffffffffff1661546d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff166130ea919061546d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151836020015161312c919061546d565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131a89190615492565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d4a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134a75760008160600151856133439190615bbb565b905060006133518583615be0565b90508083604001818151613365919061546d565b6bffffffffffffffffffffffff169052506133808582615c0b565b83606001818151613391919061546d565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60008260000182815481106134ca576134ca615357565b9060005260206000200154905092915050565b600081815260018301602052604081205480156135c657600061350160018361530f565b85549091506000906135159060019061530f565b905081811461357a57600086600001828154811061353557613535615357565b906000526020600020015490508087600001848154811061355857613558615357565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061358b5761358b615c3b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061224a565b600091505061224a565b5092915050565b600081815260018301602052604081205461361e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561224a565b50600061224a565b6000818160045b600f8110156136b3577fff00000000000000000000000000000000000000000000000000000000000000821683826020811061366b5761366b615357565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146136a157506000949350505050565b806136ab81615386565b91505061362d565b5081600f1a60018111156136c9576136c9615857565b949350505050565b6000808080856060015160018111156136ec576136ec615857565b03613712576136fe8888888888614072565b61370d576000925090506137e6565b61378a565b60018560600151600181111561372a5761372a615857565b0361375857600061373d898989886141fc565b925090508061375257506000925090506137e6565b5061378a565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff1687106137df57877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516137cc9190614e19565b60405180910390a26000925090506137e6565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff161561384d576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b00000000000000000000000000000000000000000000000000000000906138c2908590602401614e19565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906139959087908790600401615c6a565b60408051808303816000875af11580156139b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139d79190615c83565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b600081606001516001811115613a2357613a23615857565b03613a8757600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b600181606001516001811115613a9f57613a9f615857565b03613b0b5760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613b80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba49190615ccb565b50935050925050600082131580613bba57508042105b80613bea57506000846040015162ffffff16118015613bea5750613bde814261530f565b846040015162ffffff16105b156135d0575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d0b9190615ccb565b50935050925050600082131580613d2157508042105b80613d5157506000866040015162ffffff16118015613d515750613d45814261530f565b866040015162ffffff16105b15613d655760018301546060850152613d6d565b606084018290525b50505092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613def5760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613dfb8686614409565b60c0840151602082015182519293509091600091613e189161546d565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613e9d57819050613e7e87608001518860e0015160600151846bffffffffffffffffffffffff16613e6f9190615b24565b613e799190615b6a565b61464f565b6bffffffffffffffffffffffff16604084015260006060840152613f29565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613f2957819050613f1583604001516bffffffffffffffffffffffff1688608001518960e0015160600151856bffffffffffffffffffffffff16613f019190615b24565b613f0b9190615b6a565b613e79919061530f565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613f6f90849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615bbb565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613fca9084906fffffffffffffffffffffffffffffffff16615d1b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806bffffffffffffffffffffffff16602160008960c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254614061919061530f565b909155509298975050505050505050565b600080848060200190518101906140899190615d44565b845160e00151815191925063ffffffff908116911610156140e657867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8866040516140d49190614e19565b60405180910390a260009150506141f3565b8260e0015180156141a657506020810151158015906141a65750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa15801561417f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a39190615102565b14155b806141b85750805163ffffffff168611155b156141ed57867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301866040516140d49190614e19565b60019150505b95945050505050565b6000806000848060200190518101906142159190615d9c565b905060008782600001518360200151846040015160405160200161427794939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e00151801561435257506080820151158015906143525750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa15801561432b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061434f9190615102565b14155b80614367575086826060015163ffffffff1610155b156143b157877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018760405161439c9190614e19565b60405180910390a26000935091506144009050565b60008181526008602052604090205460ff16156143f857877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88760405161439c9190614e19565b600193509150505b94509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516144579190615b24565b9050836101000151801561446a5750803a105b1561447257503a5b600060128311614483576001614499565b61448e60128461530f565b61449990600a615f3d565b90506000601284106144ac5760016144c2565b6144b784601261530f565b6144c290600a615f3d565b905060008660a001518760400151886020015189600001516144e49190615492565b6144ee9087615b24565b6144f89190615492565b6145029190615b24565b9050614525828860e001516060015161451b9190615b24565b613e6f8584615b24565b6bffffffffffffffffffffffff168652608087015161454890613e799083615b6a565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906145819062ffffff16683635c9adc5dea00000615b24565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b6145b49190615b24565b6145be9190615492565b6145c89190615b24565b6145d29190615b24565b6145dc9190615b6a565b6145e69190615492565b9050614609848a60e00151606001516145ff9190615b24565b613e6f8784615b24565b6bffffffffffffffffffffffff166020890152608089015161462f90613e799083615b6a565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b60006bffffffffffffffffffffffff8211156146ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610d4a565b5090565b50805460008255906000526020600020908101906114179190614791565b828054828255906000526020600020908101928215614789579160200282015b8281111561478957825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061472f565b506146ed9291505b5b808211156146ed5760008155600101614792565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff811182821017156147f9576147f96147a6565b60405290565b60405160c0810167ffffffffffffffff811182821017156147f9576147f96147a6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614869576148696147a6565b604052919050565b600067ffffffffffffffff82111561488b5761488b6147a6565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461141757600080fd5b80356148c281614895565b919050565b600082601f8301126148d857600080fd5b813560206148ed6148e883614871565b614822565b82815260059290921b8401810191818101908684111561490c57600080fd5b8286015b8481101561493057803561492381614895565b8352918301918301614910565b509695505050505050565b60ff8116811461141757600080fd5b80356148c28161493b565b63ffffffff8116811461141757600080fd5b80356148c281614955565b801515811461141757600080fd5b80356148c281614972565b62ffffff8116811461141757600080fd5b80356148c28161498b565b61ffff8116811461141757600080fd5b80356148c2816149a7565b600061020082840312156149d557600080fd5b6149dd6147d5565b90506149e882614967565b81526149f660208301614967565b6020820152614a0760408301614967565b6040820152614a18606083016148b7565b6060820152614a2960808301614980565b6080820152614a3a60a0830161499c565b60a0820152614a4b60c08301614967565b60c0820152614a5c60e08301614967565b60e0820152610100614a6f8184016148b7565b90820152610120614a818382016149b7565b90820152610140614a938382016148b7565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff811115614ad457600080fd5b614ae0858286016148c7565b8284015250506101e0614af48184016148b7565b9082015292915050565b803567ffffffffffffffff811681146148c257600080fd5b600082601f830112614b2757600080fd5b813567ffffffffffffffff811115614b4157614b416147a6565b614b7260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614822565b818152846020838601011115614b8757600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461141757600080fd5b600082601f830112614bcf57600080fd5b81356020614bdf6148e883614871565b82815260c09283028501820192828201919087851115614bfe57600080fd5b8387015b85811015614c905781818a031215614c1a5760008081fd5b614c226147ff565b8135614c2d81614955565b815281860135614c3c8161498b565b81870152604082810135614c4f81614895565b90820152606082810135614c628161493b565b908201526080828101359082015260a080830135614c7f81614ba4565b908201528452928401928101614c02565b5090979650505050505050565b600080600080600080600080610100898b031215614cba57600080fd5b883567ffffffffffffffff80821115614cd257600080fd5b614cde8c838d016148c7565b995060208b0135915080821115614cf457600080fd5b614d008c838d016148c7565b9850614d0e60408c0161494a565b975060608b0135915080821115614d2457600080fd5b614d308c838d016149c2565b9650614d3e60808c01614afe565b955060a08b0135915080821115614d5457600080fd5b614d608c838d01614b16565b945060c08b0135915080821115614d7657600080fd5b614d828c838d016148c7565b935060e08b0135915080821115614d9857600080fd5b50614da58b828c01614bbe565b9150509295985092959890939650565b6000815180845260005b81811015614ddb57602081850181015186830182015201614dbf565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061225c6020830184614db5565b60008083601f840112614e3e57600080fd5b50813567ffffffffffffffff811115614e5657600080fd5b602083019150836020828501011115614e6e57600080fd5b9250929050565b60008060008060608587031215614e8b57600080fd5b8435614e9681614895565b935060208501359250604085013567ffffffffffffffff811115614eb957600080fd5b614ec587828801614e2c565b95989497509550505050565b60008083601f840112614ee357600080fd5b50813567ffffffffffffffff811115614efb57600080fd5b6020830191508360208260051b8501011115614e6e57600080fd5b60008060008060008060008060e0898b031215614f3257600080fd5b606089018a811115614f4357600080fd5b8998503567ffffffffffffffff80821115614f5d57600080fd5b614f698c838d01614e2c565b909950975060808b0135915080821115614f8257600080fd5b614f8e8c838d01614ed1565b909750955060a08b0135915080821115614fa757600080fd5b50614fb48b828c01614ed1565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614fe657600080fd5b863567ffffffffffffffff80821115614ffe57600080fd5b61500a8a838b016148c7565b9750602089013591508082111561502057600080fd5b61502c8a838b016148c7565b965061503a60408a0161494a565b9550606089013591508082111561505057600080fd5b61505c8a838b01614b16565b945061506a60808a01614afe565b935060a089013591508082111561508057600080fd5b5061508d89828a01614b16565b9150509295509295509295565b6000602082840312156150ac57600080fd5b813561225c81614895565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff81811683821602908116908181146135d0576135d06150b7565b60006020828403121561511457600080fd5b5051919050565b63ffffffff8181168382160190808211156135d0576135d06150b7565b600081518084526020808501945080840160005b8381101561517e57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161514c565b509495945050505050565b602081526151a060208201835163ffffffff169052565b600060208301516151b9604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006152388185018363ffffffff169052565b84015190506101206152618482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406152788482018361ffff169052565b84015190506101606152a18482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e0808601829052919250906152e9610220860184615138565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b8181038181111561224a5761224a6150b7565b600081615331576153316150b7565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036153b7576153b76150b7565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153ee8184018a615138565b905082810360808401526154028189615138565b905060ff871660a084015282810360c084015261541f8187614db5565b905067ffffffffffffffff851660e08401528281036101008401526154448185614db5565b9c9b505050505050505050505050565b60006020828403121561546657600080fd5b5035919050565b6bffffffffffffffffffffffff8181168382160190808211156135d0576135d06150b7565b8082018082111561224a5761224a6150b7565b60ff818116838216019081111561224a5761224a6150b7565b80516148c281614955565b80516148c281614895565b80516148c281614972565b80516148c28161498b565b80516148c2816149a7565b600082601f83011261550657600080fd5b815160206155166148e883614871565b82815260059290921b8401810191818101908684111561553557600080fd5b8286015b8481101561493057805161554c81614895565b8352918301918301615539565b600082601f83011261556a57600080fd5b8151602061557a6148e883614871565b82815260059290921b8401810191818101908684111561559957600080fd5b8286015b848110156149305780516155b081614895565b835291830191830161559d565b600082601f8301126155ce57600080fd5b815160206155de6148e883614871565b82815260c092830285018201928282019190878511156155fd57600080fd5b8387015b85811015614c905781818a0312156156195760008081fd5b6156216147ff565b815161562c81614955565b81528186015161563b8161498b565b8187015260408281015161564e81614895565b908201526060828101516156618161493b565b908201526080828101519082015260a08083015161567e81614ba4565b908201528452928401928101615601565b6000806000606084860312156156a457600080fd5b835167ffffffffffffffff808211156156bc57600080fd5b9085019061020082880312156156d157600080fd5b6156d96147d5565b6156e2836154be565b81526156f0602084016154be565b6020820152615701604084016154be565b6040820152615712606084016154c9565b6060820152615723608084016154d4565b608082015261573460a084016154df565b60a082015261574560c084016154be565b60c082015261575660e084016154be565b60e08201526101006157698185016154c9565b9082015261012061577b8482016154ea565b9082015261014061578d8482016154c9565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c080840151838111156157c657600080fd5b6157d28a8287016154f5565b8284015250506101e06157e68185016154c9565b90820152602087015190955091508082111561580157600080fd5b61580d87838801615559565b9350604086015191508082111561582357600080fd5b50615830868287016155bd565b9150509250925092565b60006020828403121561584c57600080fd5b815161225c8161493b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526158cd8285018b615138565b915083820360808501526158e1828a615138565b915060ff881660a085015283820360c08501526158fe8288614db5565b90861660e085015283810361010085015290506154448185614db5565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261595257600080fd5b813560206159626148e883614871565b82815260059290921b8401810191818101908684111561598157600080fd5b8286015b848110156149305780358352918301918301615985565b600082601f8301126159ad57600080fd5b813560206159bd6148e883614871565b82815260059290921b840181019181810190868411156159dc57600080fd5b8286015b8481101561493057803567ffffffffffffffff811115615a005760008081fd5b615a0e8986838b0101614b16565b8452509183019183016159e0565b600060208284031215615a2e57600080fd5b813567ffffffffffffffff80821115615a4657600080fd5b9083019060c08286031215615a5a57600080fd5b615a626147ff565b8235815260208301356020820152604083013582811115615a8257600080fd5b615a8e87828601615941565b604083015250606083013582811115615aa657600080fd5b615ab287828601615941565b606083015250608083013582811115615aca57600080fd5b615ad68782860161599c565b60808301525060a083013582811115615aee57600080fd5b615afa8782860161599c565b60a08301525095945050505050565b61ffff8181168382160190808211156135d0576135d06150b7565b808202811582820484141761224a5761224a6150b7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615b7957615b79615b3b565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000615bb16080830184614db5565b9695505050505050565b6bffffffffffffffffffffffff8281168282160390808211156135d0576135d06150b7565b60006bffffffffffffffffffffffff80841680615bff57615bff615b3b565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615c3357615c336150b7565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8281526040602082015260006136c96040830184614db5565b60008060408385031215615c9657600080fd5b8251615ca181614972565b6020939093015192949293505050565b805169ffffffffffffffffffff811681146148c257600080fd5b600080600080600060a08688031215615ce357600080fd5b615cec86615cb1565b9450602086015193506040860151925060608601519150615d0f60808701615cb1565b90509295509295909350565b6fffffffffffffffffffffffffffffffff8181168382160190808211156135d0576135d06150b7565b600060408284031215615d5657600080fd5b6040516040810181811067ffffffffffffffff82111715615d7957615d796147a6565b6040528251615d8781614955565b81526020928301519281019290925250919050565b600060a08284031215615dae57600080fd5b60405160a0810181811067ffffffffffffffff82111715615dd157615dd16147a6565b806040525082518152602083015160208201526040830151615df281614955565b60408201526060830151615e0581614955565b60608201526080928301519281019290925250919050565b600181815b80851115615e7657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615e5c57615e5c6150b7565b80851615615e6957918102915b93841c9390800290615e22565b509250929050565b600082615e8d5750600161224a565b81615e9a5750600061224a565b8160018114615eb05760028114615eba57615ed6565b600191505061224a565b60ff841115615ecb57615ecb6150b7565b50506001821b61224a565b5060208310610133831016604e8410600b8410161715615ef9575081810a61224a565b615f038383615e1d565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615f3557615f356150b7565b029392505050565b600061225c8383615e7e56fea164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b50604051620065f5380380620065f583398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615ec1620007346000396000818160be01526101910152600050506000505060005050600050506000613a8201526000505060008181610d5401528181610e6201528181610f8d01528181610fd70152818161165901526130ab0152615ec16000f3fe6080604052600436106100bc5760003560e01c80638da5cb5b11610074578063b1dc65a41161004e578063b1dc65a4146102f6578063e3d0e71214610316578063f2fde38b14610336576100bc565b80638da5cb5b14610265578063a4c0ed3614610290578063afcb95d7146102b0576100bc565b8063349e8cca116100a5578063349e8cca1461018257806379ba5097146101d657806381ff7048146101eb576100bc565b80630870d3a114610103578063181f5a7714610123575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100fc573d6000f35b3d6000fd5b005b34801561010f57600080fd5b5061010161011e366004614c08565b610356565b34801561012f57600080fd5b5061016c6040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b6040516101799190614d84565b60405180910390f35b34801561018e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610179565b3480156101e257600080fd5b50610101610c3a565b3480156101f757600080fd5b5061024260175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610179565b34801561027157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101b1565b34801561029c57600080fd5b506101016102ab366004614de0565b610d3c565b3480156102bc57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610179565b34801561030257600080fd5b50610101610311366004614e81565b611058565b34801561032257600080fd5b50610101610331366004614f38565b611339565b34801561034257600080fd5b50610101610351366004615005565b611373565b61035e611387565b601f8851111561039a576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103d7576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103f657506103ee866003615051565b60ff16885111155b1561042d576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051825114610468576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610472828261140a565b61047c8888611a42565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506000601660010160189054906101000a900463ffffffff1690506000866101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561072c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610750919061506d565b6017549091506000906107829074010000000000000000000000000000000000000000900463ffffffff166001615086565b9050604051806101600160405280896060015173ffffffffffffffffffffffffffffffffffffffff168152602001896000015163ffffffff168152602001896020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200189610100015173ffffffffffffffffffffffffffffffffffffffff1681526020018263ffffffff1681526020018363ffffffff168152602001896040015163ffffffff16815260200189610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018960c0015163ffffffff1681526020018960e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050876101600151601981905550876101800151601a81905550876101a00151601b81905550600088604051602001610ac591906150f4565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610b2a904690309074010000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f612101565b6013556000610b3960096121ab565b90505b8015610b7657610b63610b5b610b5360018461527a565b6009906121bb565b6009906121ce565b5080610b6e8161528d565b915050610b3c565b5060005b896101c0015151811015610bcd57610bba8a6101c001518281518110610ba257610ba26152c2565b602002602001015160096121f090919063ffffffff16565b5080610bc5816152f1565b915050610b7a565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0584601354601660010160149054906101000a900463ffffffff168f8f8f878f8f604051610c2499989796959493929190615329565b60405180910390a1505050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610dab576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610de5576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3828401846153bf565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610e4e576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610ed2576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610f1190859070010000000000000000000000000000000090046bffffffffffffffffffffffff166153d8565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168252602190522054610fc09085906153fd565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff166101008201529192506111bc576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16611205576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a3514611241576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151611251906001615410565b60ff16861415806112625750858414155b15611299576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112a98a8a8a8a8a8a8a8a612212565b60006112b58a8a61247b565b905060208b0135600881901c63ffffffff166112d2848487612534565b836020015163ffffffff168163ffffffff16111561132a57601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b60008060008580602001905181019061135291906155fa565b9250925092506113688989898689898888610356565b505050505050505050565b61137b611387565b61138481613121565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611408576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610cb7565b565b60005b6024548110156114c857602260006024838154811061142e5761142e6152c2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169055806114c0816152f1565b91505061140d565b506114d56024600061465c565b60255460ff1660005b8351811015611a3c5760008482815181106114fb576114fb6152c2565b602002602001015190506000848381518110611519576115196152c2565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159291906157a5565b60ff16816060015160ff161415806116205750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161891906157a5565b60ff16600814155b15611657576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156116c3575060018460018111156116c1576116c16157c2565b145b156116fa576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821615806117355750604081015173ffffffffffffffffffffffffffffffffffffffff16155b1561176c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156117d6576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611a1f908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a250508080611a34906152f1565b9150506114de565b50505050565b600e546014546bffffffffffffffffffffffff1660005b600e54811015611ab557611aa2600e8281548110611a7957611a796152c2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168385613216565b5080611aad816152f1565b915050611a59565b5060255460009060ff16815b600e54811015611c2657600e8181548110611ade57611ade6152c2565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611b1b57611b1b6152c2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611bbd57611bbd6157c2565b148015611c02575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611c1457611c12600f846121f0565b505b80611c1e816152f1565b915050611ac1565b50611c33600d600061465c565b611c3f600e600061465c565b6040805160808101825260008082526020820181905291810182905260608101829052905b87518110156120cf57600c6000898381518110611c8357611c836152c2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611cee576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16888281518110611d1857611d186152c2565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611d6d576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008a8481518110611d9e57611d9e6152c2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558651879082908110611e4657611e466152c2565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611eb6576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611f71576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909516949094171791909116929092179190911790558360018111156120ab576120ab6157c2565b036120bd576120bb600f856121ce565b505b806120c7816152f1565b915050611c64565b5086516120e390600d9060208a019061467a565b5085516120f790600e90602089019061467a565b5050505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001612125999897969594939291906157f1565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b60006121b5825490565b92915050565b60006121c7838361341e565b9392505050565b60006121c78373ffffffffffffffffffffffffffffffffffffffff8416613448565b60006121c78373ffffffffffffffffffffffffffffffffffffffff8416613542565b60008787604051612224929190615886565b60405190819003812061223b918b90602001615896565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b88811015612412576001858783602081106122a7576122a76152c2565b6122b491901a601b615410565b8c8c858181106122c6576122c66152c2565b905060200201358b8b868181106122df576122df6152c2565b905060200201356040516000815260200160405260405161231c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561233e573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff80821615158085526101009092041693830193909352909550935090506123ec576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061240a906152f1565b91505061228a565b50827e0101010101010101010101010101010101010101010101010101010101010184161461246d576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6124b46040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006124c283850185615987565b60408101515160608201515191925090811415806124e557508082608001515114155b806124f55750808260a001515114155b1561252c576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561255457612554614711565b60405190808252806020026020018201604052801561262057816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816125725790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e2919061506d565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612736573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275a919061506d565b905060005b866040015151811015612bea576004600088604001518381518110612786576127866152c2565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106128a9576128a96152c2565b6020026020010151600001819052506128de876040015182815181106128d1576128d16152c2565b6020026020010151613591565b8582815181106128f0576128f06152c2565b602002602001015160600190600181111561290d5761290d6157c2565b90816001811115612920576129206157c2565b815250506129848760400151828151811061293d5761293d6152c2565b6020026020010151848960800151848151811061295c5761295c6152c2565b6020026020010151888581518110612976576129766152c2565b60200260200101518c61363c565b868381518110612996576129966152c2565b60200260200101516020018784815181106129b3576129b36152c2565b602002602001015160c00182815250821515151581525050508481815181106129de576129de6152c2565b60200260200101516020015115612a0e57600184600001818151612a029190615a74565b61ffff16905250612a13565b612bd8565b612a79858281518110612a2857612a286152c2565b6020026020010151600001516080015188606001518381518110612a4e57612a4e6152c2565b60200260200101518960a001518481518110612a6c57612a6c6152c2565b602002602001015161375b565b868381518110612a8b57612a8b6152c2565b6020026020010151604001878481518110612aa857612aa86152c2565b6020026020010151608001828152508215151515815250505087608001516001612ad29190615410565b612ae09060ff166040615a8f565b6103a48860a001518381518110612af957612af96152c2565b602002602001015151612b0c91906153fd565b612b1691906153fd565b858281518110612b2857612b286152c2565b602002602001015160a0018181525050848181518110612b4a57612b4a6152c2565b602002602001015160a0015184606001818151612b6791906153fd565b9052508451859082908110612b7e57612b7e6152c2565b60200260200101516080015186612b95919061527a565b9550612bd887604001518281518110612bb057612bb06152c2565b602002602001015184878481518110612bcb57612bcb6152c2565b6020026020010151613976565b80612be2816152f1565b91505061275f565b50825161ffff16600003612c015750505050505050565b61c800612c0f366010615a8f565b5a612c1a908861527a565b612c2491906153fd565b612c2e91906153fd565b83519095506123f090612c459061ffff1687615ad5565b612c4f91906153fd565b6040805160808101825260008082526020820181905291810182905260608101829052919650612c7e89613a7b565b905060005b886040015151811015612fba57868181518110612ca257612ca26152c2565b60200260200101516020015115612fa857801580612d3a575086612cc760018361527a565b81518110612cd757612cd76152c2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612d1057612d106152c2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612d6e57612d6b8a888381518110612d5557612d556152c2565b6020026020010151600001516101000151613b65565b92505b6000612e8c8b6040518061012001604052808b8681518110612d9257612d926152c2565b60200260200101516080015181526020018c81526020018a606001518c8781518110612dc057612dc06152c2565b602002602001015160a001518a612dd79190615a8f565b612de19190615ad5565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612e1257612e126152c2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612e6157612e616152c2565b60200260200101518b8681518110612e7b57612e7b6152c2565b602002602001015160000151613ce1565b9050806060015187604001818151612ea491906153d8565b6bffffffffffffffffffffffff169052506040810151602088018051612ecb9083906153d8565b6bffffffffffffffffffffffff169052508751889083908110612ef057612ef06152c2565b60200260200101516040015115158a604001518381518110612f1457612f146152c2565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83606001518460400151612f5191906153d8565b8b8681518110612f6357612f636152c2565b6020026020010151608001518d8f608001518881518110612f8657612f866152c2565b6020026020010151604051612f9e9493929190615ae9565b60405180910390a3505b80612fb2816152f1565b915050612c83565b505050602083810151336000908152600b90925260409091208054600290612ff79084906201000090046bffffffffffffffffffffffff166153d8565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff1661305591906153d8565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151836020015161309791906153d8565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461311391906153fd565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036131a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610cb7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134125760008160600151856132ae9190615b26565b905060006132bc8583615b4b565b905080836040018181516132d091906153d8565b6bffffffffffffffffffffffff169052506132eb8582615b76565b836060018181516132fc91906153d8565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b6000826000018281548110613435576134356152c2565b9060005260206000200154905092915050565b6000818152600183016020526040812054801561353157600061346c60018361527a565b85549091506000906134809060019061527a565b90508181146134e55760008660000182815481106134a0576134a06152c2565b90600052602060002001549050808760000184815481106134c3576134c36152c2565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806134f6576134f6615ba6565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506121b5565b60009150506121b5565b5092915050565b6000818152600183016020526040812054613589575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556121b5565b5060006121b5565b6000818160045b600f81101561361e577fff0000000000000000000000000000000000000000000000000000000000000082168382602081106135d6576135d66152c2565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461360c57506000949350505050565b80613616816152f1565b915050613598565b5081600f1a6001811115613634576136346157c2565b949350505050565b600080808085606001516001811115613657576136576157c2565b0361367d576136698888888888613fdd565b61367857600092509050613751565b6136f5565b600185606001516001811115613695576136956157c2565b036136c35760006136a889898988614167565b92509050806136bd5750600092509050613751565b506136f5565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061374a57877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516137379190614d84565b60405180910390a2600092509050613751565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137b8576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061382d908590602401614d84565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906139009087908790600401615bd5565b60408051808303816000875af115801561391e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139429190615bee565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60008160600151600181111561398e5761398e6157c2565b036139f257600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b600181606001516001811115613a0a57613a0a6157c2565b03613a765760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0f9190615c36565b50935050925050600082131580613b2557508042105b80613b5557506000846040015162ffffff16118015613b555750613b49814261527a565b846040015162ffffff16105b1561353b575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c769190615c36565b50935050925050600082131580613c8c57508042105b80613cbc57506000866040015162ffffff16118015613cbc5750613cb0814261527a565b866040015162ffffff16105b15613cd05760018301546060850152613cd8565b606084018290525b50505092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613d5a5760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613d668686614374565b60c0840151602082015182519293509091600091613d83916153d8565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613e0857819050613de987608001518860e0015160600151846bffffffffffffffffffffffff16613dda9190615a8f565b613de49190615ad5565b6145ba565b6bffffffffffffffffffffffff16604084015260006060840152613e94565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613e9457819050613e8083604001516bffffffffffffffffffffffff1688608001518960e0015160600151856bffffffffffffffffffffffff16613e6c9190615a8f565b613e769190615ad5565b613de4919061527a565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613eda90849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615b26565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613f359084906fffffffffffffffffffffffffffffffff16615c86565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806bffffffffffffffffffffffff16602160008960c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613fcc919061527a565b909155509298975050505050505050565b60008084806020019051810190613ff49190615caf565b845160e00151815191925063ffffffff9081169116101561405157867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88660405161403f9190614d84565b60405180910390a2600091505061415e565b8260e00151801561411157506020810151158015906141115750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa1580156140ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410e919061506d565b14155b806141235750805163ffffffff168611155b1561415857867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018660405161403f9190614d84565b60019150505b95945050505050565b6000806000848060200190518101906141809190615d07565b90506000878260000151836020015184604001516040516020016141e294939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e0015180156142bd57506080820151158015906142bd5750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015614296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ba919061506d565b14155b806142d2575086826060015163ffffffff1610155b1561431c57877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516143079190614d84565b60405180910390a260009350915061436b9050565b60008181526008602052604090205460ff161561436357877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516143079190614d84565b600193509150505b94509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516143c29190615a8f565b905083610100015180156143d55750803a105b156143dd57503a5b6000601283116143ee576001614404565b6143f960128461527a565b61440490600a615ea8565b905060006012841061441757600161442d565b61442284601261527a565b61442d90600a615ea8565b905060008660a0015187604001518860200151896000015161444f91906153fd565b6144599087615a8f565b61446391906153fd565b61446d9190615a8f565b9050614490828860e00151606001516144869190615a8f565b613dda8584615a8f565b6bffffffffffffffffffffffff16865260808701516144b390613de49083615ad5565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906144ec9062ffffff16683635c9adc5dea00000615a8f565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61451f9190615a8f565b61452991906153fd565b6145339190615a8f565b61453d9190615a8f565b6145479190615ad5565b61455191906153fd565b9050614574848a60e001516060015161456a9190615a8f565b613dda8784615a8f565b6bffffffffffffffffffffffff166020890152608089015161459a90613de49083615ad5565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b60006bffffffffffffffffffffffff821115614658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610cb7565b5090565b508054600082559060005260206000209081019061138491906146fc565b8280548282559060005260206000209081019282156146f4579160200282015b828111156146f457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061469a565b506146589291505b5b8082111561465857600081556001016146fd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561476457614764614711565b60405290565b60405160c0810167ffffffffffffffff8111828210171561476457614764614711565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156147d4576147d4614711565b604052919050565b600067ffffffffffffffff8211156147f6576147f6614711565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461138457600080fd5b803561482d81614800565b919050565b600082601f83011261484357600080fd5b81356020614858614853836147dc565b61478d565b82815260059290921b8401810191818101908684111561487757600080fd5b8286015b8481101561489b57803561488e81614800565b835291830191830161487b565b509695505050505050565b60ff8116811461138457600080fd5b803561482d816148a6565b63ffffffff8116811461138457600080fd5b803561482d816148c0565b801515811461138457600080fd5b803561482d816148dd565b62ffffff8116811461138457600080fd5b803561482d816148f6565b61ffff8116811461138457600080fd5b803561482d81614912565b6000610200828403121561494057600080fd5b614948614740565b9050614953826148d2565b8152614961602083016148d2565b6020820152614972604083016148d2565b604082015261498360608301614822565b6060820152614994608083016148eb565b60808201526149a560a08301614907565b60a08201526149b660c083016148d2565b60c08201526149c760e083016148d2565b60e08201526101006149da818401614822565b908201526101206149ec838201614922565b908201526101406149fe838201614822565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff811115614a3f57600080fd5b614a4b85828601614832565b8284015250506101e0614a5f818401614822565b9082015292915050565b803567ffffffffffffffff8116811461482d57600080fd5b600082601f830112614a9257600080fd5b813567ffffffffffffffff811115614aac57614aac614711565b614add60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161478d565b818152846020838601011115614af257600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461138457600080fd5b600082601f830112614b3a57600080fd5b81356020614b4a614853836147dc565b82815260c09283028501820192828201919087851115614b6957600080fd5b8387015b85811015614bfb5781818a031215614b855760008081fd5b614b8d61476a565b8135614b98816148c0565b815281860135614ba7816148f6565b81870152604082810135614bba81614800565b90820152606082810135614bcd816148a6565b908201526080828101359082015260a080830135614bea81614b0f565b908201528452928401928101614b6d565b5090979650505050505050565b600080600080600080600080610100898b031215614c2557600080fd5b883567ffffffffffffffff80821115614c3d57600080fd5b614c498c838d01614832565b995060208b0135915080821115614c5f57600080fd5b614c6b8c838d01614832565b9850614c7960408c016148b5565b975060608b0135915080821115614c8f57600080fd5b614c9b8c838d0161492d565b9650614ca960808c01614a69565b955060a08b0135915080821115614cbf57600080fd5b614ccb8c838d01614a81565b945060c08b0135915080821115614ce157600080fd5b614ced8c838d01614832565b935060e08b0135915080821115614d0357600080fd5b50614d108b828c01614b29565b9150509295985092959890939650565b6000815180845260005b81811015614d4657602081850181015186830182015201614d2a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006121c76020830184614d20565b60008083601f840112614da957600080fd5b50813567ffffffffffffffff811115614dc157600080fd5b602083019150836020828501011115614dd957600080fd5b9250929050565b60008060008060608587031215614df657600080fd5b8435614e0181614800565b935060208501359250604085013567ffffffffffffffff811115614e2457600080fd5b614e3087828801614d97565b95989497509550505050565b60008083601f840112614e4e57600080fd5b50813567ffffffffffffffff811115614e6657600080fd5b6020830191508360208260051b8501011115614dd957600080fd5b60008060008060008060008060e0898b031215614e9d57600080fd5b606089018a811115614eae57600080fd5b8998503567ffffffffffffffff80821115614ec857600080fd5b614ed48c838d01614d97565b909950975060808b0135915080821115614eed57600080fd5b614ef98c838d01614e3c565b909750955060a08b0135915080821115614f1257600080fd5b50614f1f8b828c01614e3c565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614f5157600080fd5b863567ffffffffffffffff80821115614f6957600080fd5b614f758a838b01614832565b97506020890135915080821115614f8b57600080fd5b614f978a838b01614832565b9650614fa560408a016148b5565b95506060890135915080821115614fbb57600080fd5b614fc78a838b01614a81565b9450614fd560808a01614a69565b935060a0890135915080821115614feb57600080fd5b50614ff889828a01614a81565b9150509295509295509295565b60006020828403121561501757600080fd5b81356121c781614800565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216029081169081811461353b5761353b615022565b60006020828403121561507f57600080fd5b5051919050565b63ffffffff81811683821601908082111561353b5761353b615022565b600081518084526020808501945080840160005b838110156150e957815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016150b7565b509495945050505050565b6020815261510b60208201835163ffffffff169052565b60006020830151615124604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006151a38185018363ffffffff169052565b84015190506101206151cc8482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406151e38482018361ffff169052565b840151905061016061520c8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e0808601829052919250906152546102208601846150a3565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b818103818111156121b5576121b5615022565b60008161529c5761529c615022565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361532257615322615022565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153598184018a6150a3565b9050828103608084015261536d81896150a3565b905060ff871660a084015282810360c084015261538a8187614d20565b905067ffffffffffffffff851660e08401528281036101008401526153af8185614d20565b9c9b505050505050505050505050565b6000602082840312156153d157600080fd5b5035919050565b6bffffffffffffffffffffffff81811683821601908082111561353b5761353b615022565b808201808211156121b5576121b5615022565b60ff81811683821601908111156121b5576121b5615022565b805161482d816148c0565b805161482d81614800565b805161482d816148dd565b805161482d816148f6565b805161482d81614912565b600082601f83011261547157600080fd5b81516020615481614853836147dc565b82815260059290921b840181019181810190868411156154a057600080fd5b8286015b8481101561489b5780516154b781614800565b83529183019183016154a4565b600082601f8301126154d557600080fd5b815160206154e5614853836147dc565b82815260059290921b8401810191818101908684111561550457600080fd5b8286015b8481101561489b57805161551b81614800565b8352918301918301615508565b600082601f83011261553957600080fd5b81516020615549614853836147dc565b82815260c0928302850182019282820191908785111561556857600080fd5b8387015b85811015614bfb5781818a0312156155845760008081fd5b61558c61476a565b8151615597816148c0565b8152818601516155a6816148f6565b818701526040828101516155b981614800565b908201526060828101516155cc816148a6565b908201526080828101519082015260a0808301516155e981614b0f565b90820152845292840192810161556c565b60008060006060848603121561560f57600080fd5b835167ffffffffffffffff8082111561562757600080fd5b90850190610200828803121561563c57600080fd5b615644614740565b61564d83615429565b815261565b60208401615429565b602082015261566c60408401615429565b604082015261567d60608401615434565b606082015261568e6080840161543f565b608082015261569f60a0840161544a565b60a08201526156b060c08401615429565b60c08201526156c160e08401615429565b60e08201526101006156d4818501615434565b908201526101206156e6848201615455565b908201526101406156f8848201615434565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c0808401518381111561573157600080fd5b61573d8a828701615460565b8284015250506101e0615751818501615434565b90820152602087015190955091508082111561576c57600080fd5b615778878388016154c4565b9350604086015191508082111561578e57600080fd5b5061579b86828701615528565b9150509250925092565b6000602082840312156157b757600080fd5b81516121c7816148a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526158388285018b6150a3565b9150838203608085015261584c828a6150a3565b915060ff881660a085015283820360c08501526158698288614d20565b90861660e085015283810361010085015290506153af8185614d20565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f8301126158bd57600080fd5b813560206158cd614853836147dc565b82815260059290921b840181019181810190868411156158ec57600080fd5b8286015b8481101561489b57803583529183019183016158f0565b600082601f83011261591857600080fd5b81356020615928614853836147dc565b82815260059290921b8401810191818101908684111561594757600080fd5b8286015b8481101561489b57803567ffffffffffffffff81111561596b5760008081fd5b6159798986838b0101614a81565b84525091830191830161594b565b60006020828403121561599957600080fd5b813567ffffffffffffffff808211156159b157600080fd5b9083019060c082860312156159c557600080fd5b6159cd61476a565b82358152602083013560208201526040830135828111156159ed57600080fd5b6159f9878286016158ac565b604083015250606083013582811115615a1157600080fd5b615a1d878286016158ac565b606083015250608083013582811115615a3557600080fd5b615a4187828601615907565b60808301525060a083013582811115615a5957600080fd5b615a6587828601615907565b60a08301525095945050505050565b61ffff81811683821601908082111561353b5761353b615022565b80820281158282048414176121b5576121b5615022565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ae457615ae4615aa6565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000615b1c6080830184614d20565b9695505050505050565b6bffffffffffffffffffffffff82811682821603908082111561353b5761353b615022565b60006bffffffffffffffffffffffff80841680615b6a57615b6a615aa6565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615b9e57615b9e615022565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8281526040602082015260006136346040830184614d20565b60008060408385031215615c0157600080fd5b8251615c0c816148dd565b6020939093015192949293505050565b805169ffffffffffffffffffff8116811461482d57600080fd5b600080600080600060a08688031215615c4e57600080fd5b615c5786615c1c565b9450602086015193506040860151925060608601519150615c7a60808701615c1c565b90509295509295909350565b6fffffffffffffffffffffffffffffffff81811683821601908082111561353b5761353b615022565b600060408284031215615cc157600080fd5b6040516040810181811067ffffffffffffffff82111715615ce457615ce4614711565b6040528251615cf2816148c0565b81526020928301519281019290925250919050565b600060a08284031215615d1957600080fd5b60405160a0810181811067ffffffffffffffff82111715615d3c57615d3c614711565b806040525082518152602083015160208201526040830151615d5d816148c0565b60408201526060830151615d70816148c0565b60608201526080928301519281019290925250919050565b600181815b80851115615de157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615dc757615dc7615022565b80851615615dd457918102915b93841c9390800290615d8d565b509250929050565b600082615df8575060016121b5565b81615e05575060006121b5565b8160018114615e1b5760028114615e2557615e41565b60019150506121b5565b60ff841115615e3657615e36615022565b50506001821b6121b5565b5060208310610133831016604e8410600b8410161715615e64575081810a6121b5565b615e6e8383615d88565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615ea057615ea0615022565b029392505050565b60006121c78383615de956fea164736f6c6343000813000a", } var AutomationRegistryABI = AutomationRegistryMetaData.ABI diff --git a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go index a72ff506c90..cdbb52883ff 100644 --- a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go +++ b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go @@ -89,6 +89,11 @@ type AutomationRegistryBase23Storage struct { MaxRevertDataSize uint32 } +type AutomationRegistryBase23TransmitterPayeeInfo struct { + TransmitterAddress common.Address + PayeeAddress common.Address +} + type IAutomationV21PlusCommonOnchainConfigLegacy struct { PaymentPremiumPPB uint32 FlatFeeMicroLink uint32 @@ -134,7 +139,7 @@ type IAutomationV21PlusCommonUpkeepInfoLegacy struct { } var IAutomationRegistryMaster23MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var IAutomationRegistryMaster23ABI = IAutomationRegistryMaster23MetaData.ABI @@ -489,6 +494,50 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) Ge return _IAutomationRegistryMaster23.Contract.GetBalance(&_IAutomationRegistryMaster23.CallOpts, id) } +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingConfig", billingToken) + + if err != nil { + return *new(AutomationRegistryBase23BillingConfig), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23BillingConfig)).(*AutomationRegistryBase23BillingConfig) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetBillingConfig(billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingConfig(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetBillingConfig(billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingConfig(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingOverrides(opts *bind.CallOpts, upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingOverrides", upkeepID) + + if err != nil { + return *new(AutomationRegistryBase23BillingOverrides), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23BillingOverrides)).(*AutomationRegistryBase23BillingOverrides) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetBillingOverrides(upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingOverrides(&_IAutomationRegistryMaster23.CallOpts, upkeepID) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetBillingOverrides(upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingOverrides(&_IAutomationRegistryMaster23.CallOpts, upkeepID) +} + func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) { var out []interface{} err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingToken", upkeepID) @@ -1201,6 +1250,28 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) Ge return _IAutomationRegistryMaster23.Contract.GetTransmitterInfo(&_IAutomationRegistryMaster23.CallOpts, query) } +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetTransmittersWithPayees(opts *bind.CallOpts) ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getTransmittersWithPayees") + + if err != nil { + return *new([]AutomationRegistryBase23TransmitterPayeeInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]AutomationRegistryBase23TransmitterPayeeInfo)).(*[]AutomationRegistryBase23TransmitterPayeeInfo) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetTransmittersWithPayees() ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + return _IAutomationRegistryMaster23.Contract.GetTransmittersWithPayees(&_IAutomationRegistryMaster23.CallOpts) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetTransmittersWithPayees() ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + return _IAutomationRegistryMaster23.Contract.GetTransmittersWithPayees(&_IAutomationRegistryMaster23.CallOpts) +} + func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetTriggerType(opts *bind.CallOpts, upkeepId *big.Int) (uint8, error) { var out []interface{} err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getTriggerType", upkeepId) @@ -7239,6 +7310,10 @@ type IAutomationRegistryMaster23Interface interface { GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) + GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) + + GetBillingOverrides(opts *bind.CallOpts, upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) + GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) GetBillingTokenConfig(opts *bind.CallOpts, token common.Address) (AutomationRegistryBase23BillingConfig, error) @@ -7307,6 +7382,8 @@ type IAutomationRegistryMaster23Interface interface { error) + GetTransmittersWithPayees(opts *bind.CallOpts) ([]AutomationRegistryBase23TransmitterPayeeInfo, error) + GetTriggerType(opts *bind.CallOpts, upkeepId *big.Int) (uint8, error) GetUpkeep(opts *bind.CallOpts, id *big.Int) (IAutomationV21PlusCommonUpkeepInfoLegacy, error) diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 6af70fd8f03..d5a931321ab 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -8,13 +8,13 @@ automation_compatible_utils: ../../contracts/solc/v0.8.19/AutomationCompatibleUt automation_consumer_benchmark: ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.bin f52c76f1aaed4be541d82d97189d70f5aa027fc9838037dd7a7d21910c8c488e automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin 15ae0c367297955fdab4b552dbb10e1f2be80a8fde0efec4a4d398693e9d72b5 automation_registrar_wrapper2_1: ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.bin eb06d853aab39d3196c593b03e555851cbe8386e0fe54a74c2479f62d14b3c42 -automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin b42de91c15c7453d8262124e20594819d64a3f23bef8e6db66fa5180d18a8454 +automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin 05dfc1601a6e8a43d98c982b5cb1ad1060b49948dc0c8ccd829ca2c9f6d9430e automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 -automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 1163ecd34c575cb17ffbc2f88fa175816f36982e91992d940ed435d306b3418c +automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin e8ae5a25765092049f79eb8344db8e572bacb43c6c6e284b3d00f82667c248f7 automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin 2d0f45d2087f6f3c8bfa0a16b26a1c8c1d5c64b89859478c609201535c96eeed automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62 -automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin 68acf720890c89512a43c3468712f5da6c1c9613bc7c462b51599293f0cce9f4 +automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin fa9159b9dd36e37209d9805d0fde82f1cba7d0e2674ecc5a7595d48eb40203c4 automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 815b17b63f15d26a0274b962eefad98cdee4ec897ead58688bbb8e2470e585f5 automation_utils_2_2: ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.abi ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.bin 8743f6231aaefa3f2a0b2d484258070d506e2d0860690e66890dccc3949edb2e automation_utils_2_3: ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.abi ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.bin 11e2b481dc9a4d936e3443345d45d2cc571164459d214917b42a8054b295393b @@ -31,7 +31,7 @@ dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723 gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8 i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b -i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin fbfa3f5d78a357ecb7a1bc597c629ff30d42fedc48ba7f57e1622a6302d36523 +i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin 19f51996d05341f1229f21be26b5d72ff58e321f0b6da69c260f768e4622ae8e i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781 diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 45ae103ac56..7e3ca7027eb 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -30,14 +30,21 @@ var ( _ = abi.ConvertType ) -type Capability struct { - CapabilityType [32]byte - Version [32]byte +type CapabilityRegistryCapability struct { + CapabilityType [32]byte + Version [32]byte + ResponseType uint8 + ConfigurationContract common.Address +} + +type CapabilityRegistryNodeOperator struct { + Admin common.Address + Name string } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6105e5806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806379ba50971161005b57806379ba5097146101275780638da5cb5b1461012f5780639cb7c5f414610157578063f2fde38b146101be57600080fd5b8063181f5a7714610082578063229111f5146100ca5780636e5f286914610112575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516100c191906104dc565b60405180910390f35b6101046100d8366004610548565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6040519081526020016100c1565b61012561012036600461056a565b6101d1565b005b61012561024e565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c1565b6101a3610165366004610582565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252016100c1565b6101256101cc36600461059b565b610350565b6101d9610364565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610358610364565b610361816103e7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102cb565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102cb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208083528351808285015260005b81811015610509578581018301518582016040015282016104ed565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561055b57600080fd5b50508035926020909101359150565b60006040828403121561057c57600080fd5b50919050565b60006020828403121561059457600080fd5b5035919050565b6000602082840312156105ad57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146105d157600080fd5b939250505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112cb806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806365c14dc7116100765780638da5cb5b1161005b5780638da5cb5b1461018f5780639cb7c5f4146101b7578063f2fde38b146101d757600080fd5b806365c14dc71461016757806379ba50971461018757600080fd5b80631cdf6343116100a75780631cdf634314610120578063229111f514610133578063398f37731461015457600080fd5b8063117392ce146100c3578063181f5a77146100d8575b600080fd5b6100d66100d1366004610b88565b6101ea565b005b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101179190610c04565b60405180910390f35b6100d661012e366004610c63565b610420565b610146610141366004610ca5565b6104e3565b604051908152602001610117565b6100d6610162366004610c63565b610512565b61017a610175366004610cc7565b6106ab565b6040516101179190610ce0565b6100d6610791565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b6101ca6101c5366004610cc7565b61088e565b6040516101179190610d52565b6100d66101e5366004610df0565b610938565b6101f261094c565b6000610203823560208401356104e3565b90506102106003826109cf565b15610247576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006102596080840160608501610df0565b73ffffffffffffffffffffffffffffffffffffffff16146103c9576102846080830160608401610df0565b73ffffffffffffffffffffffffffffffffffffffff163b158061036457506102b26080830160608401610df0565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561033e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103629190610e0d565b155b156103c9576103796080830160608401610df0565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024015b60405180910390fd5b6103d46003826109ea565b50600081815260026020526040902082906103ef8282610e2f565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b61042861094c565b60005b818110156104de57600083838381811061044757610447610eb1565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506104986001830182610b3a565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a1506104d781610ee0565b905061042b565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b61051a61094c565b60005b818110156104de57600083838381811061053957610539610eb1565b905060200281019061054b9190610f3f565b61055490611024565b805190915073ffffffffffffffffffffffffffffffffffffffff166105a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610628908261118b565b5090505060066000815461063b90610ee0565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610690918591906112a5565b60405180910390a25050806106a490610ee0565b905061051d565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610708906110f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610734906110f0565b80156107815780601f1061075657610100808354040283529160200191610781565b820191906000526020600020905b81548152906001019060200180831161076457829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016103c0565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff16908111156108f7576108f7610d23565b600181111561090857610908610d23565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b61094061094c565b610949816109f6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103c0565b565b600081815260018301602052604081205415155b9392505050565b60006109e38383610aeb565b3373ffffffffffffffffffffffffffffffffffffffff821603610a75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103c0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610b325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561050c565b50600061050c565b508054610b46906110f0565b6000825580601f10610b56575050565b601f01602090049060005260206000209081019061094991905b80821115610b845760008155600101610b70565b5090565b600060808284031215610b9a57600080fd5b50919050565b6000815180845260005b81811015610bc657602081850181015186830182015201610baa565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006109e36020830184610ba0565b60008083601f840112610c2957600080fd5b50813567ffffffffffffffff811115610c4157600080fd5b6020830191508360208260051b8501011115610c5c57600080fd5b9250929050565b60008060208385031215610c7657600080fd5b823567ffffffffffffffff811115610c8d57600080fd5b610c9985828601610c17565b90969095509350505050565b60008060408385031215610cb857600080fd5b50508035926020909101359150565b600060208284031215610cd957600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152610d1b6060840182610ba0565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602080830151908201526040820151608082019060028110610da1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060408401525073ffffffffffffffffffffffffffffffffffffffff606084015116606083015292915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461094957600080fd5b600060208284031215610e0257600080fd5b81356109e381610dce565b600060208284031215610e1f57600080fd5b815180151581146109e357600080fd5b813581556020820135600182015560028101604083013560028110610e5357600080fd5b81546060850135610e6381610dce565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f38577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610f7357600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610fcf57610fcf610f7d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561101c5761101c610f7d565b604052919050565b60006040823603121561103657600080fd5b61103e610fac565b823561104981610dce565b815260208381013567ffffffffffffffff8082111561106757600080fd5b9085019036601f83011261107a57600080fd5b81358181111561108c5761108c610f7d565b6110bc847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610fd5565b915080825236848285010111156110d257600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061110457607f821691505b602082108103610b9a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156104de57600081815260208120601f850160051c810160208610156111645750805b601f850160051c820191505b8181101561118357828155600101611170565b505050505050565b815167ffffffffffffffff8111156111a5576111a5610f7d565b6111b9816111b384546110f0565b8461113d565b602080601f83116001811461120c57600084156111d65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611183565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156112595788860151825594840194600190910190840161123a565b508582101561129557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000610d1b6040830184610ba056fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -176,25 +183,25 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transact(opts *bind. return _CapabilityRegistry.Contract.contract.Transact(opts, method, params...) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", capabilityID) if err != nil { - return *new(Capability), err + return *new(CapabilityRegistryCapability), err } - out0 := *abi.ConvertType(out[0], new(Capability)).(*Capability) + out0 := *abi.ConvertType(out[0], new(CapabilityRegistryCapability)).(*CapabilityRegistryCapability) return out0, err } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) } @@ -220,6 +227,28 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityID(capa return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) } +func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) + + if err != nil { + return *new(CapabilityRegistryNodeOperator), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilityRegistryNodeOperator)).(*CapabilityRegistryNodeOperator) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) GetNodeOperator(nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperator(nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) +} + func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "owner") @@ -276,18 +305,42 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AcceptOwnership( return _CapabilityRegistry.Contract.AcceptOwnership(&_CapabilityRegistry.TransactOpts) } -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapability(opts *bind.TransactOpts, capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "addCapability", capability) } -func (_CapabilityRegistry *CapabilityRegistrySession) AddCapability(capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) AddCapability(capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) } -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapability(capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapability(capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "addNodeOperators", nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "removeNodeOperators", nodeOperatorIds) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) RemoveNodeOperators(nodeOperatorIds []*big.Int) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.RemoveNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) RemoveNodeOperators(nodeOperatorIds []*big.Int) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.RemoveNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds) +} + func (_CapabilityRegistry *CapabilityRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "transferOwnership", to) } @@ -427,6 +480,252 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityAdded(log return event, nil } +type CapabilityRegistryNodeOperatorAddedIterator struct { + Event *CapabilityRegistryNodeOperatorAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeOperatorAdded struct { + NodeOperatorId *big.Int + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorAdded", adminRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeOperatorAddedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorAdded", adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeOperatorAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) { + event := new(CapabilityRegistryNodeOperatorAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilityRegistryNodeOperatorRemovedIterator struct { + Event *CapabilityRegistryNodeOperatorRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeOperatorRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeOperatorRemovedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeOperatorRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeOperatorRemoved struct { + NodeOperatorId *big.Int + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeOperatorRemovedIterator, error) { + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorRemoved") + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeOperatorRemovedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorRemoved", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorRemoved) (event.Subscription, error) { + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeOperatorRemoved) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorRemoved(log types.Log) (*CapabilityRegistryNodeOperatorRemoved, error) { + event := new(CapabilityRegistryNodeOperatorRemoved) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryOwnershipTransferRequestedIterator struct { Event *CapabilityRegistryOwnershipTransferRequested @@ -703,6 +1002,10 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate switch log.Topics[0] { case _CapabilityRegistry.abi.Events["CapabilityAdded"].ID: return _CapabilityRegistry.ParseCapabilityAdded(log) + case _CapabilityRegistry.abi.Events["NodeOperatorAdded"].ID: + return _CapabilityRegistry.ParseNodeOperatorAdded(log) + case _CapabilityRegistry.abi.Events["NodeOperatorRemoved"].ID: + return _CapabilityRegistry.ParseNodeOperatorRemoved(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: return _CapabilityRegistry.ParseOwnershipTransferRequested(log) case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: @@ -717,6 +1020,14 @@ func (CapabilityRegistryCapabilityAdded) Topic() common.Hash { return common.HexToHash("0x65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff06") } +func (CapabilityRegistryNodeOperatorAdded) Topic() common.Hash { + return common.HexToHash("0xda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b") +} + +func (CapabilityRegistryNodeOperatorRemoved) Topic() common.Hash { + return common.HexToHash("0x1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f") +} + func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -730,17 +1041,23 @@ func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { } type CapabilityRegistryInterface interface { - GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) + GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) + GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) + Owner(opts *bind.CallOpts) (common.Address, error) TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) + AddCapability(opts *bind.TransactOpts, capability CapabilityRegistryCapability) (*types.Transaction, error) + + AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) + + RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -750,6 +1067,18 @@ type CapabilityRegistryInterface interface { ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) + FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) + + WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) + + FilterNodeOperatorRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeOperatorRemovedIterator, error) + + WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorRemoved) (event.Subscription, error) + + ParseNodeOperatorRemoved(log types.Log) (*CapabilityRegistryNodeOperatorRemoved, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 98fd35e188b..66d26cead2d 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin fbaf8eceb929494bdfe0028921a0742da525cb4ec1b6d57a1382eda46fa32c64 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin d526b850decbf88dbe3dd66ed2160f1c311fb4ee6df0ac50c91f31521b361a52 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 diff --git a/core/gethwrappers/ocr2vrf/generated/dkg/dkg.go b/core/gethwrappers/ocr2vrf/generated/dkg/dkg.go new file mode 100644 index 00000000000..7a18b7f55bd --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/dkg/dkg.go @@ -0,0 +1,1274 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package dkg + +import ( + "errors" + "fmt" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type KeyDataStructKeyData struct { + PublicKey []byte + Hashes [][32]byte +} + +var DKGMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"CalldataLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedNumSignatures\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"ssLength\",\"type\":\"uint256\"}],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expectedLength\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"InvalidOnchainConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"KeyIDCopyFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"numFaultyOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"}],\"name\":\"NumberOfFaultyOraclesTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedSignerAddress\",\"type\":\"address\"}],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedTransmitterAddress\",\"type\":\"address\"}],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numTransmitters\",\"type\":\"uint256\"}],\"name\":\"SignersTransmittersMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"maxOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"providedOracles\",\"type\":\"uint256\"}],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contractDKGClient\",\"name\":\"client\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"errorData\",\"type\":\"bytes\"}],\"name\":\"DKGClientError\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashes\",\"type\":\"bytes32[]\"}],\"indexed\":false,\"internalType\":\"structKeyDataStruct.KeyData\",\"name\":\"key\",\"type\":\"tuple\"}],\"name\":\"KeyGenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"},{\"internalType\":\"contractDKGClient\",\"name\":\"clientAddress\",\"type\":\"address\"}],\"name\":\"addClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_keyID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_configDigest\",\"type\":\"bytes32\"}],\"name\":\"getKey\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashes\",\"type\":\"bytes32[]\"}],\"internalType\":\"structKeyDataStruct.KeyData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"},{\"internalType\":\"contractDKGClient\",\"name\":\"clientAddress\",\"type\":\"address\"}],\"name\":\"removeClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612b8080620001606000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638da5cb5b11610081578063c3105a6b1161005b578063c3105a6b146101db578063e3d0e712146101fb578063f2fde38b1461020e57600080fd5b80638da5cb5b14610176578063afcb95d71461019e578063b1dc65a4146101c857600080fd5b806379ba5097116100b257806379ba50971461012b5780637bf1ffc51461013357806381ff70481461014657600080fd5b8063181f5a77146100ce5780635429a79e14610116575b600080fd5b604080518082018252600981527f444b4720302e302e3100000000000000000000000000000000000000000000006020820152905161010d9190611fc8565b60405180910390f35b610129610124366004612004565b610221565b005b6101296104b0565b610129610141366004612004565b6105b2565b6007546005546040805163ffffffff8085168252640100000000909404909316602084015282015260600161010d565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010d565b6005546004546040805160008152602081019390935263ffffffff9091169082015260600161010d565b6101296101d6366004612080565b61061e565b6101ee6101e9366004612165565b610761565b60405161010d9190612187565b6101296102093660046123dd565b61088a565b61012961021c3660046124aa565b6111ec565b610229611200565b60008281526002602090815260408083208054825181850281018501909352808352919290919083018282801561029657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161026b575b505050505090506000815167ffffffffffffffff8111156102b9576102b961220d565b6040519080825280602002602001820160405280156102e2578160200160208202803683370190505b5090506000805b83518110156103b9578473ffffffffffffffffffffffffffffffffffffffff1684828151811061031b5761031b6124c7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff161461039957848361034a8484612525565b8151811061035a5761035a6124c7565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506103a7565b816103a381612538565b9250505b806103b181612538565b9150506102e9565b5060008184516103c99190612525565b67ffffffffffffffff8111156103e1576103e161220d565b60405190808252806020026020018201604052801561040a578160200160208202803683370190505b50905060005b82855161041d9190612525565b81101561048757838181518110610436576104366124c7565b6020026020010151828281518110610450576104506124c7565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101528061047f81612538565b915050610410565b50600086815260026020908152604090912082516104a792840190611e61565b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6105ba611200565b600091825260026020908152604083208054600181018255908452922090910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60005a604080516020601f8b018190048102820181019092528981529192508a3591818c01359161066e9184918491908e908e908190840183828082843760009201919091525061128392505050565b6040805183815263ffffffff600884901c1660208201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260055480825260065460ff808216602085015261010090910416928201929092529083146107215780516040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101919091526024810184905260440161052d565b61072f8b8b8b8b8b8b611512565b6107408c8c8c8c8c8c8c8c89611599565b50505063ffffffff811061075657610756612570565b505050505050505050565b604080518082019091526060808252602082015260008381526003602090815260408083208584529091529081902081518083019092528054829082906107a79061259f565b80601f01602080910402602001604051908101604052809291908181526020018280546107d39061259f565b80156108205780601f106107f557610100808354040283529160200191610820565b820191906000526020600020905b81548152906001019060200180831161080357829003601f168201915b505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561087857602002820191906000526020600020905b815481526020019060010190808311610864575b50505050508152505090505b92915050565b8551855185601f8311156108d4576040517f809fc428000000000000000000000000000000000000000000000000000000008152601f60048201526024810184905260440161052d565b818314610917576040517f988a0804000000000000000000000000000000000000000000000000000000008152600481018490526024810183905260440161052d565b6109228160036125f2565b60ff168311610969576040517ffda9db7800000000000000000000000000000000000000000000000000000000815260ff821660048201526024810184905260440161052d565b8060ff166000036109a6576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ae611200565b6040805160c0810182528a8152602081018a905260ff8916918101919091526060810187905267ffffffffffffffff8616608082015260a081018590525b60095415610ba157600954600090610a0690600190612525565b9050600060098281548110610a1d57610a1d6124c7565b6000918252602082200154600a805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110610a5757610a576124c7565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526008909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600980549192509080610ad757610ad7612615565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055600a805480610b4057610b40612615565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055506109ec915050565b60005b81515181101561101c5760006008600084600001518481518110610bca57610bca6124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115610c1457610c14612644565b14610c84578151805182908110610c2d57610c2d6124c7565b60200260200101516040517f7451f83e00000000000000000000000000000000000000000000000000000000815260040161052d919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040805180820190915260ff82168152600160208201528251805160089160009185908110610cb557610cb56124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610d5657610d56612644565b021790555060009150610d669050565b6008600084602001518481518110610d8057610d806124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115610dca57610dca612644565b14610e3c5781602001518181518110610de557610de56124c7565b60200260200101516040517fe8d2989900000000000000000000000000000000000000000000000000000000815260040161052d919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040805180820190915260ff821681526020810160028152506008600084602001518481518110610e6f57610e6f6124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610f1057610f10612644565b021790555050825180516009925083908110610f2e57610f2e6124c7565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558201518051600a919083908110610faa57610faa6124c7565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790558061101481612538565b915050610ba4565b506040810151600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600754640100000000900463ffffffff1661106c611a2f565b6007805463ffffffff928316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff8216811783556001936000926110bd928692908116911617612673565b92506101000a81548163ffffffff021916908363ffffffff160217905550600061111e4630600760009054906101000a900463ffffffff1663ffffffff1686600001518760200151886040015189606001518a608001518b60a00151611ac6565b6005819055835180516006805460ff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9092169190911790556007546020860151604080880151606089015160808a015160a08b015193519798507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05976111c3978b978b9763ffffffff9091169691959094909390929091906126e1565b60405180910390a16111de8360400151846060015183611b71565b505050505050505050505050565b6111f4611200565b6111fd81611d6c565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611281576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161052d565b565b60006060808380602001905181019061129c9190612777565b60408051808201825283815260208082018490526000868152600282528381208054855181850281018501909652808652979a509598509396509094929391929083018282801561132357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116112f8575b5050505050905060005b815181101561144d57818181518110611348576113486124c7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663bf2732c7846040518263ffffffff1660e01b81526004016113889190612187565b600060405180830381600087803b1580156113a257600080fd5b505af19250505080156113b3575060015b61143b573d8080156113e1576040519150601f19603f3d011682016040523d82523d6000602084013e6113e6565b606091505b507f116391732f5df106193bda7cedf1728f3b07b62f6cdcdd611c9eeec44efcae5483838151811061141a5761141a6124c7565b602002602001015182604051611431929190612875565b60405180910390a1505b8061144581612538565b91505061132d565b5060008581526003602090815260408083208b845290915290208251839190819061147890826128fb565b5060208281015180516114919260018501920190611eeb565b5090505084887fc8db841f5b2231ccf7190311f440aa197b161e369f3b40b023508160cc555656846040516114c69190612187565b60405180910390a350506004805460089690961c63ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000909616959095179094555050505050565b600061151f826020612a15565b61152a856020612a15565b61153688610144612a2c565b6115409190612a2c565b61154a9190612a2c565b611555906000612a2c565b90503681146104a7576040517ff7b94f0a0000000000000000000000000000000000000000000000000000000081526004810182905236602482015260440161052d565b60006002826020015183604001516115b19190612a3f565b6115bb9190612a58565b6115c6906001612a3f565b60408051600180825281830190925260ff929092169250600091906020820181803683370190505090508160f81b81600081518110611607576116076124c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535086821415806116455750868514155b1561168d576040517fe307bd5700000000000000000000000000000000000000000000000000000000815260048101839052602481018890526044810186905260640161052d565b3360009081526008602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156116d0576116d0612644565b60028111156116e1576116e1612644565b90525090506002816020015160028111156116fe576116fe612644565b1415806117465750600a816000015160ff1681548110611720576117206124c7565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff163314155b1561177f576040517f2d0f0c0f00000000000000000000000000000000000000000000000000000000815233600482015260240161052d565b50505060008888604051611794929190612aa1565b6040519081900381206117ab918c90602001612ab1565b6040516020818303038152906040528051906020012090506117cb611f26565b604080518082019091526000808252602082015260005b88811015611a20576000600185888460208110611801576118016124c7565b61180e91901a601b612a3f565b8d8d86818110611820576118206124c7565b905060200201358c8c87818110611839576118396124c7565b9050602002013560405160008152602001604052604051611876949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611898573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526008602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561191857611918612644565b600281111561192957611929612644565b905250925060018360200151600281111561194657611946612644565b14611995576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161052d565b8251849060ff16601f81106119ac576119ac6124c7565b6020020151156119e8576040517f21cf3b4400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184846000015160ff16601f8110611a0357611a036124c7565b911515602090920201525080611a1881612538565b9150506117e2565b50505050505050505050505050565b60004661a4b1811480611a44575062066eed81145b15611abf57606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab99190612ac5565b91505090565b4391505090565b6000808a8a8a8a8a8a8a8a8a604051602001611aea99989796959493929190612ade565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b6000808351602014611bbc5783516040517f1625adfe00000000000000000000000000000000000000000000000000000000815260206004820152602481019190915260440161052d565b60208401519150808203611bfc576040517faf5e77d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152606080825260208201526000838152600360209081526040808320878452909152902081518291908190611c3a90826128fb565b506020828101518051611c539260018501920190611eeb565b505050600083815260026020908152604080832080548251818502810185019093528083529192909190830182828015611cc357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611c98575b5050505050905060005b8151811015611d6257818181518110611ce857611ce86124c7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff166355e487496040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611d3757600080fd5b505af1158015611d4b573d6000803e3d6000fd5b505050508080611d5a90612538565b915050611ccd565b5050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161052d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215611edb579160200282015b82811115611edb57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611e81565b50611ee7929150611f45565b5090565b828054828255906000526020600020908101928215611edb579160200282015b82811115611edb578251825591602001919060010190611f0b565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115611ee75760008155600101611f46565b60005b83811015611f75578181015183820152602001611f5d565b50506000910152565b60008151808452611f96816020860160208601611f5a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611fdb6020830184611f7e565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146111fd57600080fd5b6000806040838503121561201757600080fd5b82359150602083013561202981611fe2565b809150509250929050565b60008083601f84011261204657600080fd5b50813567ffffffffffffffff81111561205e57600080fd5b6020830191508360208260051b850101111561207957600080fd5b9250929050565b60008060008060008060008060e0898b03121561209c57600080fd5b606089018a8111156120ad57600080fd5b8998503567ffffffffffffffff808211156120c757600080fd5b818b0191508b601f8301126120db57600080fd5b8135818111156120ea57600080fd5b8c60208285010111156120fc57600080fd5b6020830199508098505060808b013591508082111561211a57600080fd5b6121268c838d01612034565b909750955060a08b013591508082111561213f57600080fd5b5061214c8b828c01612034565b999c989b50969995989497949560c00135949350505050565b6000806040838503121561217857600080fd5b50508035926020909101359150565b6000602080835283516040828501526121a36060850182611f7e565b858301518582037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0016040870152805180835290840192506000918401905b8083101561220257835182529284019260019290920191908401906121e2565b509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156122835761228361220d565b604052919050565b600067ffffffffffffffff8211156122a5576122a561220d565b5060051b60200190565b600082601f8301126122c057600080fd5b813560206122d56122d08361228b565b61223c565b82815260059290921b840181019181810190868411156122f457600080fd5b8286015b8481101561220257803561230b81611fe2565b83529183019183016122f8565b803560ff8116811461232957600080fd5b919050565b600067ffffffffffffffff8211156123485761234861220d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261238557600080fd5b81356123936122d08261232e565b8181528460208386010111156123a857600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff8116811461232957600080fd5b60008060008060008060c087890312156123f657600080fd5b863567ffffffffffffffff8082111561240e57600080fd5b61241a8a838b016122af565b9750602089013591508082111561243057600080fd5b61243c8a838b016122af565b965061244a60408a01612318565b9550606089013591508082111561246057600080fd5b61246c8a838b01612374565b945061247a60808a016123c5565b935060a089013591508082111561249057600080fd5b5061249d89828a01612374565b9150509295509295509295565b6000602082840312156124bc57600080fd5b8135611fdb81611fe2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610884576108846124f6565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612569576125696124f6565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600181811c908216806125b357607f821691505b6020821081036125ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60ff818116838216029081169081811461260e5761260e6124f6565b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b63ffffffff81811683821601908082111561260e5761260e6124f6565b600081518084526020808501945080840160005b838110156126d657815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016126a4565b509495945050505050565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526127118184018a612690565b905082810360808401526127258189612690565b905060ff871660a084015282810360c08401526127428187611f7e565b905067ffffffffffffffff851660e08401528281036101008401526127678185611f7e565b9c9b505050505050505050505050565b60008060006060848603121561278c57600080fd5b8351925060208085015167ffffffffffffffff808211156127ac57600080fd5b818701915087601f8301126127c057600080fd5b81516127ce6122d08261232e565b81815289858386010111156127e257600080fd5b6127f182868301878701611f5a565b60408901519096509250508082111561280957600080fd5b508501601f8101871361281b57600080fd5b80516128296122d08261228b565b81815260059190911b8201830190838101908983111561284857600080fd5b928401925b828410156128665783518252928401929084019061284d565b80955050505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006128a46040830184611f7e565b949350505050565b601f8211156128f657600081815260208120601f850160051c810160208610156128d35750805b601f850160051c820191505b818110156128f2578281556001016128df565b5050505b505050565b815167ffffffffffffffff8111156129155761291561220d565b61292981612923845461259f565b846128ac565b602080601f83116001811461297c57600084156129465750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556128f2565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156129c9578886015182559484019460019091019084016129aa565b5085821015612a0557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8082028115828204841417610884576108846124f6565b80820180821115610884576108846124f6565b60ff8181168382160190811115610884576108846124f6565b600060ff831680612a92577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612ad757600080fd5b5051919050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152612b258285018b612690565b91508382036080850152612b39828a612690565b915060ff881660a085015283820360c0850152612b568288611f7e565b90861660e085015283810361010085015290506127678185611f7e56fea164736f6c6343000813000a", +} + +var DKGABI = DKGMetaData.ABI + +var DKGBin = DKGMetaData.Bin + +func DeployDKG(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *DKG, error) { + parsed, err := DKGMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(DKGBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &DKG{DKGCaller: DKGCaller{contract: contract}, DKGTransactor: DKGTransactor{contract: contract}, DKGFilterer: DKGFilterer{contract: contract}}, nil +} + +type DKG struct { + address common.Address + abi abi.ABI + DKGCaller + DKGTransactor + DKGFilterer +} + +type DKGCaller struct { + contract *bind.BoundContract +} + +type DKGTransactor struct { + contract *bind.BoundContract +} + +type DKGFilterer struct { + contract *bind.BoundContract +} + +type DKGSession struct { + Contract *DKG + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type DKGCallerSession struct { + Contract *DKGCaller + CallOpts bind.CallOpts +} + +type DKGTransactorSession struct { + Contract *DKGTransactor + TransactOpts bind.TransactOpts +} + +type DKGRaw struct { + Contract *DKG +} + +type DKGCallerRaw struct { + Contract *DKGCaller +} + +type DKGTransactorRaw struct { + Contract *DKGTransactor +} + +func NewDKG(address common.Address, backend bind.ContractBackend) (*DKG, error) { + abi, err := abi.JSON(strings.NewReader(DKGABI)) + if err != nil { + return nil, err + } + contract, err := bindDKG(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &DKG{address: address, abi: abi, DKGCaller: DKGCaller{contract: contract}, DKGTransactor: DKGTransactor{contract: contract}, DKGFilterer: DKGFilterer{contract: contract}}, nil +} + +func NewDKGCaller(address common.Address, caller bind.ContractCaller) (*DKGCaller, error) { + contract, err := bindDKG(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &DKGCaller{contract: contract}, nil +} + +func NewDKGTransactor(address common.Address, transactor bind.ContractTransactor) (*DKGTransactor, error) { + contract, err := bindDKG(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &DKGTransactor{contract: contract}, nil +} + +func NewDKGFilterer(address common.Address, filterer bind.ContractFilterer) (*DKGFilterer, error) { + contract, err := bindDKG(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &DKGFilterer{contract: contract}, nil +} + +func bindDKG(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := DKGMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_DKG *DKGRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DKG.Contract.DKGCaller.contract.Call(opts, result, method, params...) +} + +func (_DKG *DKGRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DKG.Contract.DKGTransactor.contract.Transfer(opts) +} + +func (_DKG *DKGRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DKG.Contract.DKGTransactor.contract.Transact(opts, method, params...) +} + +func (_DKG *DKGCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DKG.Contract.contract.Call(opts, result, method, params...) +} + +func (_DKG *DKGTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DKG.Contract.contract.Transfer(opts) +} + +func (_DKG *DKGTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DKG.Contract.contract.Transact(opts, method, params...) +} + +func (_DKG *DKGCaller) GetKey(opts *bind.CallOpts, _keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "getKey", _keyID, _configDigest) + + if err != nil { + return *new(KeyDataStructKeyData), err + } + + out0 := *abi.ConvertType(out[0], new(KeyDataStructKeyData)).(*KeyDataStructKeyData) + + return out0, err + +} + +func (_DKG *DKGSession) GetKey(_keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) { + return _DKG.Contract.GetKey(&_DKG.CallOpts, _keyID, _configDigest) +} + +func (_DKG *DKGCallerSession) GetKey(_keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) { + return _DKG.Contract.GetKey(&_DKG.CallOpts, _keyID, _configDigest) +} + +func (_DKG *DKGCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "latestConfigDetails") + + outstruct := new(LatestConfigDetails) + if err != nil { + return *outstruct, err + } + + outstruct.ConfigCount = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.BlockNumber = *abi.ConvertType(out[1], new(uint32)).(*uint32) + outstruct.ConfigDigest = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +func (_DKG *DKGSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _DKG.Contract.LatestConfigDetails(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _DKG.Contract.LatestConfigDetails(&_DKG.CallOpts) +} + +func (_DKG *DKGCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "latestConfigDigestAndEpoch") + + outstruct := new(LatestConfigDigestAndEpoch) + if err != nil { + return *outstruct, err + } + + outstruct.ScanLogs = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.Epoch = *abi.ConvertType(out[2], new(uint32)).(*uint32) + + return *outstruct, err + +} + +func (_DKG *DKGSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _DKG.Contract.LatestConfigDigestAndEpoch(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _DKG.Contract.LatestConfigDigestAndEpoch(&_DKG.CallOpts) +} + +func (_DKG *DKGCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_DKG *DKGSession) Owner() (common.Address, error) { + return _DKG.Contract.Owner(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) Owner() (common.Address, error) { + return _DKG.Contract.Owner(&_DKG.CallOpts) +} + +func (_DKG *DKGCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_DKG *DKGSession) TypeAndVersion() (string, error) { + return _DKG.Contract.TypeAndVersion(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) TypeAndVersion() (string, error) { + return _DKG.Contract.TypeAndVersion(&_DKG.CallOpts) +} + +func (_DKG *DKGTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "acceptOwnership") +} + +func (_DKG *DKGSession) AcceptOwnership() (*types.Transaction, error) { + return _DKG.Contract.AcceptOwnership(&_DKG.TransactOpts) +} + +func (_DKG *DKGTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _DKG.Contract.AcceptOwnership(&_DKG.TransactOpts) +} + +func (_DKG *DKGTransactor) AddClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "addClient", keyID, clientAddress) +} + +func (_DKG *DKGSession) AddClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.AddClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactorSession) AddClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.AddClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactor) RemoveClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "removeClient", keyID, clientAddress) +} + +func (_DKG *DKGSession) RemoveClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.RemoveClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactorSession) RemoveClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.RemoveClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactor) SetConfig(opts *bind.TransactOpts, _signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "setConfig", _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_DKG *DKGSession) SetConfig(_signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _DKG.Contract.SetConfig(&_DKG.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_DKG *DKGTransactorSession) SetConfig(_signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _DKG.Contract.SetConfig(&_DKG.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_DKG *DKGTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "transferOwnership", to) +} + +func (_DKG *DKGSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _DKG.Contract.TransferOwnership(&_DKG.TransactOpts, to) +} + +func (_DKG *DKGTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _DKG.Contract.TransferOwnership(&_DKG.TransactOpts, to) +} + +func (_DKG *DKGTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "transmit", reportContext, report, rs, ss, rawVs) +} + +func (_DKG *DKGSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _DKG.Contract.Transmit(&_DKG.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_DKG *DKGTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _DKG.Contract.Transmit(&_DKG.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +type DKGConfigSetIterator struct { + Event *DKGConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGConfigSetIterator) Error() error { + return it.fail +} + +func (it *DKGConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGConfigSet struct { + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterConfigSet(opts *bind.FilterOpts) (*DKGConfigSetIterator, error) { + + logs, sub, err := _DKG.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &DKGConfigSetIterator{contract: _DKG.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *DKGConfigSet) (event.Subscription, error) { + + logs, sub, err := _DKG.contract.WatchLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGConfigSet) + if err := _DKG.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseConfigSet(log types.Log) (*DKGConfigSet, error) { + event := new(DKGConfigSet) + if err := _DKG.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGDKGClientErrorIterator struct { + Event *DKGDKGClientError + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGDKGClientErrorIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGDKGClientError) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGDKGClientError) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGDKGClientErrorIterator) Error() error { + return it.fail +} + +func (it *DKGDKGClientErrorIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGDKGClientError struct { + Client common.Address + ErrorData []byte + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterDKGClientError(opts *bind.FilterOpts) (*DKGDKGClientErrorIterator, error) { + + logs, sub, err := _DKG.contract.FilterLogs(opts, "DKGClientError") + if err != nil { + return nil, err + } + return &DKGDKGClientErrorIterator{contract: _DKG.contract, event: "DKGClientError", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchDKGClientError(opts *bind.WatchOpts, sink chan<- *DKGDKGClientError) (event.Subscription, error) { + + logs, sub, err := _DKG.contract.WatchLogs(opts, "DKGClientError") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGDKGClientError) + if err := _DKG.contract.UnpackLog(event, "DKGClientError", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseDKGClientError(log types.Log) (*DKGDKGClientError, error) { + event := new(DKGDKGClientError) + if err := _DKG.contract.UnpackLog(event, "DKGClientError", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGKeyGeneratedIterator struct { + Event *DKGKeyGenerated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGKeyGeneratedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGKeyGenerated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGKeyGenerated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGKeyGeneratedIterator) Error() error { + return it.fail +} + +func (it *DKGKeyGeneratedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGKeyGenerated struct { + ConfigDigest [32]byte + KeyID [32]byte + Key KeyDataStructKeyData + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterKeyGenerated(opts *bind.FilterOpts, configDigest [][32]byte, keyID [][32]byte) (*DKGKeyGeneratedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + var keyIDRule []interface{} + for _, keyIDItem := range keyID { + keyIDRule = append(keyIDRule, keyIDItem) + } + + logs, sub, err := _DKG.contract.FilterLogs(opts, "KeyGenerated", configDigestRule, keyIDRule) + if err != nil { + return nil, err + } + return &DKGKeyGeneratedIterator{contract: _DKG.contract, event: "KeyGenerated", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchKeyGenerated(opts *bind.WatchOpts, sink chan<- *DKGKeyGenerated, configDigest [][32]byte, keyID [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + var keyIDRule []interface{} + for _, keyIDItem := range keyID { + keyIDRule = append(keyIDRule, keyIDItem) + } + + logs, sub, err := _DKG.contract.WatchLogs(opts, "KeyGenerated", configDigestRule, keyIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGKeyGenerated) + if err := _DKG.contract.UnpackLog(event, "KeyGenerated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseKeyGenerated(log types.Log) (*DKGKeyGenerated, error) { + event := new(DKGKeyGenerated) + if err := _DKG.contract.UnpackLog(event, "KeyGenerated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGOwnershipTransferRequestedIterator struct { + Event *DKGOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *DKGOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &DKGOwnershipTransferRequestedIterator{contract: _DKG.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGOwnershipTransferRequested) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseOwnershipTransferRequested(log types.Log) (*DKGOwnershipTransferRequested, error) { + event := new(DKGOwnershipTransferRequested) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGOwnershipTransferredIterator struct { + Event *DKGOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *DKGOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &DKGOwnershipTransferredIterator{contract: _DKG.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGOwnershipTransferred) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseOwnershipTransferred(log types.Log) (*DKGOwnershipTransferred, error) { + event := new(DKGOwnershipTransferred) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGTransmittedIterator struct { + Event *DKGTransmitted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGTransmittedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGTransmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGTransmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGTransmittedIterator) Error() error { + return it.fail +} + +func (it *DKGTransmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGTransmitted struct { + ConfigDigest [32]byte + Epoch uint32 + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterTransmitted(opts *bind.FilterOpts) (*DKGTransmittedIterator, error) { + + logs, sub, err := _DKG.contract.FilterLogs(opts, "Transmitted") + if err != nil { + return nil, err + } + return &DKGTransmittedIterator{contract: _DKG.contract, event: "Transmitted", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *DKGTransmitted) (event.Subscription, error) { + + logs, sub, err := _DKG.contract.WatchLogs(opts, "Transmitted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGTransmitted) + if err := _DKG.contract.UnpackLog(event, "Transmitted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseTransmitted(log types.Log) (*DKGTransmitted, error) { + event := new(DKGTransmitted) + if err := _DKG.contract.UnpackLog(event, "Transmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LatestConfigDetails struct { + ConfigCount uint32 + BlockNumber uint32 + ConfigDigest [32]byte +} +type LatestConfigDigestAndEpoch struct { + ScanLogs bool + ConfigDigest [32]byte + Epoch uint32 +} + +func (_DKG *DKG) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _DKG.abi.Events["ConfigSet"].ID: + return _DKG.ParseConfigSet(log) + case _DKG.abi.Events["DKGClientError"].ID: + return _DKG.ParseDKGClientError(log) + case _DKG.abi.Events["KeyGenerated"].ID: + return _DKG.ParseKeyGenerated(log) + case _DKG.abi.Events["OwnershipTransferRequested"].ID: + return _DKG.ParseOwnershipTransferRequested(log) + case _DKG.abi.Events["OwnershipTransferred"].ID: + return _DKG.ParseOwnershipTransferred(log) + case _DKG.abi.Events["Transmitted"].ID: + return _DKG.ParseTransmitted(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (DKGConfigSet) Topic() common.Hash { + return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") +} + +func (DKGDKGClientError) Topic() common.Hash { + return common.HexToHash("0x116391732f5df106193bda7cedf1728f3b07b62f6cdcdd611c9eeec44efcae54") +} + +func (DKGKeyGenerated) Topic() common.Hash { + return common.HexToHash("0xc8db841f5b2231ccf7190311f440aa197b161e369f3b40b023508160cc555656") +} + +func (DKGOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (DKGOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (DKGTransmitted) Topic() common.Hash { + return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") +} + +func (_DKG *DKG) Address() common.Address { + return _DKG.address +} + +type DKGInterface interface { + GetKey(opts *bind.CallOpts, _keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) + + LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) + + LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) + + RemoveClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, _signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts) (*DKGConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *DKGConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*DKGConfigSet, error) + + FilterDKGClientError(opts *bind.FilterOpts) (*DKGDKGClientErrorIterator, error) + + WatchDKGClientError(opts *bind.WatchOpts, sink chan<- *DKGDKGClientError) (event.Subscription, error) + + ParseDKGClientError(log types.Log) (*DKGDKGClientError, error) + + FilterKeyGenerated(opts *bind.FilterOpts, configDigest [][32]byte, keyID [][32]byte) (*DKGKeyGeneratedIterator, error) + + WatchKeyGenerated(opts *bind.WatchOpts, sink chan<- *DKGKeyGenerated, configDigest [][32]byte, keyID [][32]byte) (event.Subscription, error) + + ParseKeyGenerated(log types.Log) (*DKGKeyGenerated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*DKGOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*DKGOwnershipTransferred, error) + + FilterTransmitted(opts *bind.FilterOpts) (*DKGTransmittedIterator, error) + + WatchTransmitted(opts *bind.WatchOpts, sink chan<- *DKGTransmitted) (event.Subscription, error) + + ParseTransmitted(log types.Log) (*DKGTransmitted, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer/load_test_beacon_consumer.go b/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer/load_test_beacon_consumer.go new file mode 100644 index 00000000000..32bf1e66219 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer/load_test_beacon_consumer.go @@ -0,0 +1,1422 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package load_test_beacon_consumer + +import ( + "errors" + "fmt" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var LoadTestBeaconVRFConsumerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"beaconPeriodBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"MustBeCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeOwnerOrCoordinator\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fail\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqID\",\"type\":\"uint256\"}],\"name\":\"getFulfillmentDurationByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqID\",\"type\":\"uint256\"}],\"name\":\"getRawFulfillmentDurationByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_beaconPeriodBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingRequests\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestHeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_ReceivedRandomnessByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_arguments\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_averageFulfillmentInMillions\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fastestFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_fulfillmentDurationInBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_gasAvailable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_mostRecentRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_myBeaconRequests\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"slotNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_randomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_rawFulfillmentDurationInBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestIDs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestOutputHeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"name\":\"s_requestsIDs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_resetCounter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_slowestFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_slowestRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_subId\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalFulfilled\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalRequests\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"}],\"name\":\"setFail\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"height\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"delay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"}],\"name\":\"storeBeaconRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"}],\"name\":\"testRedeemRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelayArg\",\"type\":\"uint24\"}],\"name\":\"testRequestRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"testRequestRandomnessFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelayArg\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"batchSize\",\"type\":\"uint256\"}],\"name\":\"testRequestRandomnessFulfillmentBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040526000600d556000600e556103e7600f556000601055600060115560006012553480156200003057600080fd5b5060405162001f6138038062001f618339810160408190526200005391620001d0565b828282823380600081620000ae5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000e157620000e18162000125565b5050600280546001600160a01b0319166001600160a01b03939093169290921790915550600b805460ff191692151592909217909155600c55506200022792505050565b336001600160a01b038216036200017f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620000a5565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080600060608486031215620001e657600080fd5b83516001600160a01b0381168114620001fe57600080fd5b602085015190935080151581146200021557600080fd5b80925050604084015190509250925092565b611d2a80620002376000396000f3fe608060405234801561001057600080fd5b50600436106102775760003560e01c806379ba509711610160578063d0705f04116100d8578063f2fde38b1161008c578063f6eaffc811610071578063f6eaffc8146105bc578063fc7fea37146105cf578063ffe97ca4146105d857600080fd5b8063f2fde38b1461057e578063f371829b1461059157600080fd5b8063d826f88f116100bd578063d826f88f1461055a578063ea7502ab14610562578063f08c5daa1461057557600080fd5b8063d0705f0414610534578063d21ea8fd1461054757600080fd5b80638ea981171161012f578063a9cc471811610114578063a9cc4718146104fb578063c6d6130114610518578063cd0593df1461052b57600080fd5b80638ea98117146104a95780639d769402146104bc57600080fd5b806379ba5097146104675780638866c6bd1461046f5780638d0e3165146104785780638da5cb5b1461048157600080fd5b80635a947873116101f35780636df57cc3116101c2578063737144bc116101a7578063737144bc1461044057806374dba124146104495780637716cdaa1461045257600080fd5b80636df57cc314610400578063706da1ca1461041357600080fd5b80635a947873146103b05780635f15cccc146103c3578063601201d3146103ee578063689b77ab146103f757600080fd5b80632b1a21301161024a578063341867a21161022f578063341867a21461035b578063353e0f60146103705780634a0aee291461039b57600080fd5b80632b1a21301461031d5780632fe8fa311461033057600080fd5b80631591950a1461027c5780631757f11c146102ba578063195e0d75146102c35780631e87f20e146102f0575b600080fd5b6102a761028a366004611503565b601560209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6102a7600e5481565b6102a76102d1366004611525565b6012546000908152601860209081526040808320938352929052205490565b6102a76102fe366004611525565b6012546000908152601760209081526040808320938352929052205490565b6102a761032b366004611503565b61068b565b6102a761033e366004611503565b601760209081526000928352604080842090915290825290205481565b61036e610369366004611503565b6106bc565b005b6102a761037e366004611503565b601660209081526000928352604080842090915290825290205481565b6103a36107b1565b6040516102b1919061153e565b6103a36103be3660046116cc565b6108c1565b6102a76103d136600461174d565b600460209081526000928352604080842090915290825290205481565b6102a760115481565b6102a760085481565b61036e61040e366004611779565b610a1f565b6009546104279067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102b1565b6102a7600d5481565b6102a7600f5481565b61045a610b5a565b6040516102b19190611823565b61036e610be8565b6102a760105481565b6102a760135481565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b1565b61036e6104b736600461183d565b610cea565b61036e6104ca366004611873565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600b546105089060ff1681565b60405190151581526020016102b1565b6102a7610526366004611895565b610dd0565b6102a7600c5481565b6102a7610542366004611503565b610eda565b61036e6105553660046118f5565b610ef6565b61036e610f57565b6102a76105703660046119be565b610f8d565b6102a7600a5481565b61036e61058c36600461183d565b61109d565b6102a761059f366004611503565b601860209081526000928352604080842090915290825290205481565b6102a76105ca366004611525565b6110b1565b6102a760125481565b6106416105e6366004611525565b60056020526000908152604090205463ffffffff811690640100000000810462ffffff1690670100000000000000810461ffff16906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1684565b6040805163ffffffff909516855262ffffff909316602085015261ffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff1660608201526080016102b1565b601460205281600052604060002081815481106106a757600080fd5b90600052602060002001600091509150505481565b60025460408051602081018252600080825291517facfc6cdd000000000000000000000000000000000000000000000000000000008152919273ffffffffffffffffffffffffffffffffffffffff169163acfc6cdd916107229187918791600401611a37565b6000604051808303816000875af1158015610741573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526107879190810190611a5f565b600083815260066020908152604090912082519293506107ab9290918401906114a3565b50505050565b6012546000908152601460205260408120546060919067ffffffffffffffff8111156107df576107df6115c0565b604051908082528060200260200182016040528015610808578160200160208202803683370190505b5090506000805b6012546000908152601460205260409020548110156108b957601254600090815260146020526040812080548390811061084b5761084b611af0565b600091825260208083209091015460125483526017825260408084208285529092529082205490925090036108a6578084848151811061088d5761088d611af0565b6020908102919091010152826108a281611b4e565b9350505b50806108b181611b4e565b91505061080f565b508152919050565b606060008267ffffffffffffffff8111156108de576108de6115c0565b604051908082528060200260200182016040528015610907578160200160208202803683370190505b5090506000600c546109176110d2565b6109219190611bb5565b9050600081600c546109316110d2565b61093b9190611bc9565b6109459190611be2565b905060005b85811015610a105760006109618c8c8c8c8c610f8d565b60108054919250600061097383611b4e565b90915550506012546000908152601560209081526040808320848452909152902083905561099f6110d2565b60128054600090815260166020908152604080832086845282528083209490945591548152601482529182208054600181018255908352912001819055845181908690849081106109f2576109f2611af0565b60209081029190910101525080610a0881611b4e565b91505061094a565b50919998505050505050505050565b600083815260046020908152604080832062ffffff861684529091528120859055600c54610a4d9085611bf5565b6040805160808101825263ffffffff928316815262ffffff958616602080830191825261ffff968716838501908152306060850190815260009b8c526005909252939099209151825491519351995173ffffffffffffffffffffffffffffffffffffffff166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff9a90971667010000000000000002999099167fffffff00000000000000000000000000000000000000000000ffffffffffffff93909716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091169890931697909717919091171692909217179092555050565b60078054610b6790611c09565b80601f0160208091040260200160405190810160405280929190818152602001828054610b9390611c09565b8015610be05780601f10610bb557610100808354040283529160200191610be0565b820191906000526020600020905b815481529060010190602001808311610bc357829003601f168201915b505050505081565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590610d2a575060025473ffffffffffffffffffffffffffffffffffffffff163314155b15610d61576040517fd4e06fd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc90600090a250565b600080600c54610dde6110d2565b610de89190611bb5565b9050600081600c54610df86110d2565b610e029190611bc9565b610e0c9190611be2565b60025460408051602081018252600080825291517f4ffac83a000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff90921691634ffac83a91610e7a918a918c918b9190600401611c5c565b6020604051808303816000875af1158015610e99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebd9190611c94565b9050610ecb8183878a610a1f565b60088190559695505050505050565b600660205281600052604060002081815481106106a757600080fd5b60025473ffffffffffffffffffffffffffffffffffffffff163314610f47576040517f66bf9c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f52838383611169565b505050565b6000600d819055600e8190556103e7600f556010819055601181905560138190556012805491610f8683611b4e565b9190505550565b600080600c54610f9b6110d2565b610fa59190611bb5565b9050600081600c54610fb56110d2565b610fbf9190611bc9565b610fc99190611be2565b60025460408051602081018252600080825291517fdb972c8b000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff9092169163db972c8b9161103b918d918d918d918d918d9190600401611cad565b6020604051808303816000875af115801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190611c94565b905061108c8183898b610a1f565b600881905598975050505050505050565b6110a561132b565b6110ae816113ae565b50565b600381815481106110c157600080fd5b600091825260209091200154905081565b60004661a4b18114806110e7575062066eed81145b1561116257606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611138573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115c9190611c94565b91505090565b4391505090565b600b5460ff16156111d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f206661696c656420696e2066756c66696c6c52616e646f6d576f7264730000006044820152606401610c65565b600083815260066020908152604090912083516111f5928501906114a3565b50601254600090815260156020908152604080832086845290915281205461121b6110d2565b6112259190611be2565b60125460009081526016602090815260408083208884529091528120549192509061124e6110d2565b6112589190611be2565b9050600061126983620f4240611d06565b9050600e5483111561128057600e83905560138690555b600f54831061129157600f54611293565b825b600f556011546112a357806112d6565b6011546112b1906001611bc9565b81601154600d546112c29190611d06565b6112cc9190611bc9565b6112d69190611bf5565b600d55601180549060006112e983611b4e565b90915550506012805460009081526017602090815260408083208a84528252808320969096559154815260188252848120978152969052509320929092555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146113ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c65565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361142d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c65565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8280548282559060005260206000209081019282156114de579160200282015b828111156114de5782518255916020019190600101906114c3565b506114ea9291506114ee565b5090565b5b808211156114ea57600081556001016114ef565b6000806040838503121561151657600080fd5b50508035926020909101359150565b60006020828403121561153757600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156115765783518352928401929184019160010161155a565b50909695505050505050565b803561ffff8116811461159457600080fd5b919050565b803562ffffff8116811461159457600080fd5b803563ffffffff8116811461159457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611636576116366115c0565b604052919050565b600082601f83011261164f57600080fd5b813567ffffffffffffffff811115611669576116696115c0565b61169a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115ef565b8181528460208386010111156116af57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c087890312156116e557600080fd5b863595506116f560208801611582565b945061170360408801611599565b9350611711606088016115ac565b9250608087013567ffffffffffffffff81111561172d57600080fd5b61173989828a0161163e565b92505060a087013590509295509295509295565b6000806040838503121561176057600080fd5b8235915061177060208401611599565b90509250929050565b6000806000806080858703121561178f57600080fd5b84359350602085013592506117a660408601611599565b91506117b460608601611582565b905092959194509250565b6000815180845260005b818110156117e5576020818501810151868301820152016117c9565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061183660208301846117bf565b9392505050565b60006020828403121561184f57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461183657600080fd5b60006020828403121561188557600080fd5b8135801515811461183657600080fd5b6000806000606084860312156118aa57600080fd5b6118b384611582565b9250602084013591506118c860408501611599565b90509250925092565b600067ffffffffffffffff8211156118eb576118eb6115c0565b5060051b60200190565b60008060006060848603121561190a57600080fd5b8335925060208085013567ffffffffffffffff8082111561192a57600080fd5b818701915087601f83011261193e57600080fd5b813561195161194c826118d1565b6115ef565b81815260059190911b8301840190848101908a83111561197057600080fd5b938501935b8285101561198e57843582529385019390850190611975565b9650505060408701359250808311156119a657600080fd5b50506119b48682870161163e565b9150509250925092565b600080600080600060a086880312156119d657600080fd5b853594506119e660208701611582565b93506119f460408701611599565b9250611a02606087016115ac565b9150608086013567ffffffffffffffff811115611a1e57600080fd5b611a2a8882890161163e565b9150509295509295909350565b838152826020820152606060408201526000611a5660608301846117bf565b95945050505050565b60006020808385031215611a7257600080fd5b825167ffffffffffffffff811115611a8957600080fd5b8301601f81018513611a9a57600080fd5b8051611aa861194c826118d1565b81815260059190911b82018301908381019087831115611ac757600080fd5b928401925b82841015611ae557835182529284019290840190611acc565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b7f57611b7f611b1f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611bc457611bc4611b86565b500690565b80820180821115611bdc57611bdc611b1f565b92915050565b81810381811115611bdc57611bdc611b1f565b600082611c0457611c04611b86565b500490565b600181811c90821680611c1d57607f821691505b602082108103611c56577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b84815261ffff8416602082015262ffffff83166040820152608060608201526000611c8a60808301846117bf565b9695505050505050565b600060208284031215611ca657600080fd5b5051919050565b86815261ffff8616602082015262ffffff8516604082015263ffffffff8416606082015260c060808201526000611ce760c08301856117bf565b82810360a0840152611cf981856117bf565b9998505050505050505050565b8082028115828204841417611bdc57611bdc611b1f56fea164736f6c6343000813000a", +} + +var LoadTestBeaconVRFConsumerABI = LoadTestBeaconVRFConsumerMetaData.ABI + +var LoadTestBeaconVRFConsumerBin = LoadTestBeaconVRFConsumerMetaData.Bin + +func DeployLoadTestBeaconVRFConsumer(auth *bind.TransactOpts, backend bind.ContractBackend, coordinator common.Address, shouldFail bool, beaconPeriodBlocks *big.Int) (common.Address, *types.Transaction, *LoadTestBeaconVRFConsumer, error) { + parsed, err := LoadTestBeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LoadTestBeaconVRFConsumerBin), backend, coordinator, shouldFail, beaconPeriodBlocks) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &LoadTestBeaconVRFConsumer{LoadTestBeaconVRFConsumerCaller: LoadTestBeaconVRFConsumerCaller{contract: contract}, LoadTestBeaconVRFConsumerTransactor: LoadTestBeaconVRFConsumerTransactor{contract: contract}, LoadTestBeaconVRFConsumerFilterer: LoadTestBeaconVRFConsumerFilterer{contract: contract}}, nil +} + +type LoadTestBeaconVRFConsumer struct { + address common.Address + abi abi.ABI + LoadTestBeaconVRFConsumerCaller + LoadTestBeaconVRFConsumerTransactor + LoadTestBeaconVRFConsumerFilterer +} + +type LoadTestBeaconVRFConsumerCaller struct { + contract *bind.BoundContract +} + +type LoadTestBeaconVRFConsumerTransactor struct { + contract *bind.BoundContract +} + +type LoadTestBeaconVRFConsumerFilterer struct { + contract *bind.BoundContract +} + +type LoadTestBeaconVRFConsumerSession struct { + Contract *LoadTestBeaconVRFConsumer + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type LoadTestBeaconVRFConsumerCallerSession struct { + Contract *LoadTestBeaconVRFConsumerCaller + CallOpts bind.CallOpts +} + +type LoadTestBeaconVRFConsumerTransactorSession struct { + Contract *LoadTestBeaconVRFConsumerTransactor + TransactOpts bind.TransactOpts +} + +type LoadTestBeaconVRFConsumerRaw struct { + Contract *LoadTestBeaconVRFConsumer +} + +type LoadTestBeaconVRFConsumerCallerRaw struct { + Contract *LoadTestBeaconVRFConsumerCaller +} + +type LoadTestBeaconVRFConsumerTransactorRaw struct { + Contract *LoadTestBeaconVRFConsumerTransactor +} + +func NewLoadTestBeaconVRFConsumer(address common.Address, backend bind.ContractBackend) (*LoadTestBeaconVRFConsumer, error) { + abi, err := abi.JSON(strings.NewReader(LoadTestBeaconVRFConsumerABI)) + if err != nil { + return nil, err + } + contract, err := bindLoadTestBeaconVRFConsumer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumer{address: address, abi: abi, LoadTestBeaconVRFConsumerCaller: LoadTestBeaconVRFConsumerCaller{contract: contract}, LoadTestBeaconVRFConsumerTransactor: LoadTestBeaconVRFConsumerTransactor{contract: contract}, LoadTestBeaconVRFConsumerFilterer: LoadTestBeaconVRFConsumerFilterer{contract: contract}}, nil +} + +func NewLoadTestBeaconVRFConsumerCaller(address common.Address, caller bind.ContractCaller) (*LoadTestBeaconVRFConsumerCaller, error) { + contract, err := bindLoadTestBeaconVRFConsumer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerCaller{contract: contract}, nil +} + +func NewLoadTestBeaconVRFConsumerTransactor(address common.Address, transactor bind.ContractTransactor) (*LoadTestBeaconVRFConsumerTransactor, error) { + contract, err := bindLoadTestBeaconVRFConsumer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerTransactor{contract: contract}, nil +} + +func NewLoadTestBeaconVRFConsumerFilterer(address common.Address, filterer bind.ContractFilterer) (*LoadTestBeaconVRFConsumerFilterer, error) { + contract, err := bindLoadTestBeaconVRFConsumer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerFilterer{contract: contract}, nil +} + +func bindLoadTestBeaconVRFConsumer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := LoadTestBeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LoadTestBeaconVRFConsumer.Contract.LoadTestBeaconVRFConsumerCaller.contract.Call(opts, result, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.LoadTestBeaconVRFConsumerTransactor.contract.Transfer(opts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.LoadTestBeaconVRFConsumerTransactor.contract.Transact(opts, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LoadTestBeaconVRFConsumer.Contract.contract.Call(opts, result, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.contract.Transfer(opts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.contract.Transact(opts, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) Fail(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "fail") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) Fail() (bool, error) { + return _LoadTestBeaconVRFConsumer.Contract.Fail(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) Fail() (bool, error) { + return _LoadTestBeaconVRFConsumer.Contract.Fail(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) GetFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "getFulfillmentDurationByRequestID", reqID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) GetFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) GetFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) GetRawFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "getRawFulfillmentDurationByRequestID", reqID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) GetRawFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetRawFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) GetRawFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetRawFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "i_beaconPeriodBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) Owner() (common.Address, error) { + return _LoadTestBeaconVRFConsumer.Contract.Owner(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) Owner() (common.Address, error) { + return _LoadTestBeaconVRFConsumer.Contract.Owner(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) PendingRequests(opts *bind.CallOpts) ([]*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "pendingRequests") + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) PendingRequests() ([]*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.PendingRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) PendingRequests() ([]*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.PendingRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) RequestHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "requestHeights", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) RequestHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.RequestHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) RequestHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.RequestHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_ReceivedRandomnessByRequestID", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SArguments(opts *bind.CallOpts) ([]byte, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_arguments") + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SArguments() ([]byte, error) { + return _LoadTestBeaconVRFConsumer.Contract.SArguments(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SArguments() ([]byte, error) { + return _LoadTestBeaconVRFConsumer.Contract.SArguments(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SAverageFulfillmentInMillions(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_averageFulfillmentInMillions") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SAverageFulfillmentInMillions() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SAverageFulfillmentInMillions(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SAverageFulfillmentInMillions() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SAverageFulfillmentInMillions(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SFastestFulfillment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_fastestFulfillment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SFastestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFastestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SFastestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFastestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_fulfillmentDurationInBlocks", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SGasAvailable(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_gasAvailable") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SGasAvailable() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SGasAvailable(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SGasAvailable() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SGasAvailable(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_mostRecentRequestID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SMostRecentRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SMostRecentRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SMostRecentRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SMostRecentRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_myBeaconRequests", arg0) + + outstruct := new(SMyBeaconRequests) + if err != nil { + return *outstruct, err + } + + outstruct.SlotNumber = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.ConfirmationDelay = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.NumWords = *abi.ConvertType(out[2], new(uint16)).(*uint16) + outstruct.Requester = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _LoadTestBeaconVRFConsumer.Contract.SMyBeaconRequests(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _LoadTestBeaconVRFConsumer.Contract.SMyBeaconRequests(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_randomWords", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRandomWords(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRandomWords(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRawFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_rawFulfillmentDurationInBlocks", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRawFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRawFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRawFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRawFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRequestIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_requestIDs", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRequestIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRequestIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRequestOutputHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_requestOutputHeights", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRequestOutputHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestOutputHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRequestOutputHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestOutputHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_requestsIDs", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestsIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestsIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SResetCounter(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_resetCounter") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SResetCounter() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SResetCounter(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SResetCounter() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SResetCounter(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SSlowestFulfillment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_slowestFulfillment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SSlowestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SSlowestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SSlowestRequestID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_slowestRequestID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SSlowestRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SSlowestRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SSubId(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_subId") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SSubId() (uint64, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSubId(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SSubId() (uint64, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSubId(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) STotalFulfilled(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_totalFulfilled") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) STotalFulfilled() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalFulfilled(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) STotalFulfilled() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalFulfilled(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) STotalRequests(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_totalRequests") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) STotalRequests() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) STotalRequests() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "acceptOwnership") +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) AcceptOwnership() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.AcceptOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.AcceptOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "rawFulfillRandomWords", requestID, randomWords, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.RawFulfillRandomWords(&_LoadTestBeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.RawFulfillRandomWords(&_LoadTestBeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) Reset(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "reset") +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) Reset() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.Reset(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) Reset() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.Reset(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "setCoordinator", coordinator) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetCoordinator(&_LoadTestBeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetCoordinator(&_LoadTestBeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "setFail", shouldFail) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetFail(&_LoadTestBeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetFail(&_LoadTestBeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "storeBeaconRequest", reqId, height, delay, numWords) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.StoreBeaconRequest(&_LoadTestBeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.StoreBeaconRequest(&_LoadTestBeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRedeemRandomness", subID, requestID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRedeemRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRedeemRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRequestRandomness", numWords, subID, confirmationDelayArg) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRequestRandomnessFulfillment", subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRequestRandomnessFulfillmentBatch(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRequestRandomnessFulfillmentBatch", subID, numWords, confirmationDelayArg, callbackGasLimit, arguments, batchSize) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRequestRandomnessFulfillmentBatch(subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillmentBatch(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confirmationDelayArg, callbackGasLimit, arguments, batchSize) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRequestRandomnessFulfillmentBatch(subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillmentBatch(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confirmationDelayArg, callbackGasLimit, arguments, batchSize) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "transferOwnership", to) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TransferOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts, to) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TransferOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts, to) +} + +type LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator struct { + Event *LoadTestBeaconVRFConsumerCoordinatorUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator) Error() error { + return it.fail +} + +func (it *LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LoadTestBeaconVRFConsumerCoordinatorUpdated struct { + Coordinator common.Address + Raw types.Log +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.FilterLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator{contract: _LoadTestBeaconVRFConsumer.contract, event: "CoordinatorUpdated", logs: logs, sub: sub}, nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.WatchLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) ParseCoordinatorUpdated(log types.Log) (*LoadTestBeaconVRFConsumerCoordinatorUpdated, error) { + event := new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator struct { + Event *LoadTestBeaconVRFConsumerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator{contract: _LoadTestBeaconVRFConsumer.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) ParseOwnershipTransferRequested(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferRequested, error) { + event := new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferredIterator struct { + Event *LoadTestBeaconVRFConsumerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerOwnershipTransferredIterator{contract: _LoadTestBeaconVRFConsumer.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) ParseOwnershipTransferred(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferred, error) { + event := new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type SMyBeaconRequests struct { + SlotNumber uint32 + ConfirmationDelay *big.Int + NumWords uint16 + Requester common.Address +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumer) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _LoadTestBeaconVRFConsumer.abi.Events["CoordinatorUpdated"].ID: + return _LoadTestBeaconVRFConsumer.ParseCoordinatorUpdated(log) + case _LoadTestBeaconVRFConsumer.abi.Events["OwnershipTransferRequested"].ID: + return _LoadTestBeaconVRFConsumer.ParseOwnershipTransferRequested(log) + case _LoadTestBeaconVRFConsumer.abi.Events["OwnershipTransferred"].ID: + return _LoadTestBeaconVRFConsumer.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (LoadTestBeaconVRFConsumerCoordinatorUpdated) Topic() common.Hash { + return common.HexToHash("0xc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc") +} + +func (LoadTestBeaconVRFConsumerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (LoadTestBeaconVRFConsumerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumer) Address() common.Address { + return _LoadTestBeaconVRFConsumer.address +} + +type LoadTestBeaconVRFConsumerInterface interface { + Fail(opts *bind.CallOpts) (bool, error) + + GetFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) + + GetRawFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) + + IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + PendingRequests(opts *bind.CallOpts) ([]*big.Int, error) + + RequestHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SArguments(opts *bind.CallOpts) ([]byte, error) + + SAverageFulfillmentInMillions(opts *bind.CallOpts) (*big.Int, error) + + SFastestFulfillment(opts *bind.CallOpts) (*big.Int, error) + + SFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SGasAvailable(opts *bind.CallOpts) (*big.Int, error) + + SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) + + SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) + + SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) + + SRawFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SRequestIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SRequestOutputHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SResetCounter(opts *bind.CallOpts) (*big.Int, error) + + SSlowestFulfillment(opts *bind.CallOpts) (*big.Int, error) + + SSlowestRequestID(opts *bind.CallOpts) (*big.Int, error) + + SSubId(opts *bind.CallOpts) (uint64, error) + + STotalFulfilled(opts *bind.CallOpts) (*big.Int, error) + + STotalRequests(opts *bind.CallOpts) (*big.Int, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) + + Reset(opts *bind.TransactOpts) (*types.Transaction, error) + + SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) + + SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) + + StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) + + TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) + + TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) + + TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) + + TestRequestRandomnessFulfillmentBatch(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator, error) + + WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) + + ParseCoordinatorUpdated(log types.Log) (*LoadTestBeaconVRFConsumerCoordinatorUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/vrf_beacon/vrf_beacon.go b/core/gethwrappers/ocr2vrf/generated/vrf_beacon/vrf_beacon.go new file mode 100644 index 00000000000..b44019de548 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/vrf_beacon/vrf_beacon.go @@ -0,0 +1,2846 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vrf_beacon + +import ( + "errors" + "fmt" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type ECCArithmeticG1Point struct { + P [2]*big.Int +} + +type KeyDataStructKeyData struct { + PublicKey []byte + Hashes [][32]byte +} + +type VRFBeaconReportReport struct { + Outputs []VRFBeaconTypesVRFOutput + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + RecentBlockHeight uint64 + RecentBlockHash [32]byte +} + +type VRFBeaconTypesCallback struct { + RequestID *big.Int + NumWords uint16 + Requester common.Address + Arguments []byte + GasAllowance *big.Int + SubID *big.Int + GasPrice *big.Int + WeiPerUnitLink *big.Int +} + +type VRFBeaconTypesCostedCallback struct { + Callback VRFBeaconTypesCallback + Price *big.Int +} + +type VRFBeaconTypesOutputServed struct { + Height uint64 + ConfirmationDelay *big.Int + ProofG1X *big.Int + ProofG1Y *big.Int +} + +type VRFBeaconTypesVRFOutput struct { + BlockHeight uint64 + ConfirmationDelay *big.Int + VrfOutput ECCArithmeticG1Point + Callbacks []VRFBeaconTypesCostedCallback + ShouldStore bool +} + +var VRFBeaconMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"contractIVRFCoordinatorProducerAPI\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"contractDKG\",\"name\":\"keyProvider\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"CalldataLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotAcceptPayeeship\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"providedHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"onchainHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"}],\"name\":\"HistoryDomainSeparatorWrong\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numTransmitters\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numPayees\",\"type\":\"uint256\"}],\"name\":\"IncorrectNumberOfPayees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expectedNumSignatures\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"rsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"ssLength\",\"type\":\"uint256\"}],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actualBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredBalance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyProvider\",\"type\":\"address\"}],\"name\":\"KeyInfoMustComeFromProvider\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeftGasExceedsInitialGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeOwnerOrBillingAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"numFaultyOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"}],\"name\":\"NumberOfFaultyOraclesTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"expectedLength\",\"type\":\"uint256\"}],\"name\":\"OnchainConfigHasWrongLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCurrentPayee\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"existingPayee\",\"type\":\"address\"}],\"name\":\"PayeeAlreadySet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedSignerAddress\",\"type\":\"address\"}],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedTransmitterAddress\",\"type\":\"address\"}],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportDoesNotContainNewOutputs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numTransmitters\",\"type\":\"uint256\"}],\"name\":\"SignersTransmittersMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"maxOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"providedOracles\",\"type\":\"uint256\"}],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"ocrVersion\",\"type\":\"uint64\"}],\"name\":\"UnknownConfigVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contractAccessControllerInterface\",\"name\":\"old\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contractAccessControllerInterface\",\"name\":\"current\",\"type\":\"address\"}],\"name\":\"BillingAccessControllerSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"maximumGasPrice\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"observationPayment\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"transmissionPayment\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"accountingGas\",\"type\":\"uint24\"}],\"name\":\"BillingSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint40\",\"name\":\"epochAndRound\",\"type\":\"uint40\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"NewTransmission\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contractLinkTokenInterface\",\"name\":\"linkToken\",\"type\":\"address\"}],\"name\":\"OraclePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"recentBlockHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"height\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint256\",\"name\":\"proofG1X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofG1Y\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structVRFBeaconTypes.OutputServed[]\",\"name\":\"outputsServed\",\"type\":\"tuple[]\"}],\"name\":\"OutputsServed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"current\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previous\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"current\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"requestIDs\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"successfulFulfillment\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"truncatedErrorData\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint96[]\",\"name\":\"subBalances\",\"type\":\"uint96[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"subIDs\",\"type\":\"uint256[]\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAllowance\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessFulfillmentRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"}],\"name\":\"RandomnessRedeemed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessRequested\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUM_CONF_DELAYS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"p\",\"type\":\"uint256[2]\"}],\"internalType\":\"structECCArithmetic.G1Point\",\"name\":\"vrfOutput\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"gasAllowance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"}],\"internalType\":\"structVRFBeaconTypes.Callback\",\"name\":\"callback\",\"type\":\"tuple\"},{\"internalType\":\"uint96\",\"name\":\"price\",\"type\":\"uint96\"}],\"internalType\":\"structVRFBeaconTypes.CostedCallback[]\",\"name\":\"callbacks\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"shouldStore\",\"type\":\"bool\"}],\"internalType\":\"structVRFBeaconTypes.VRFOutput[]\",\"name\":\"outputs\",\"type\":\"tuple[]\"},{\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"recentBlockHeight\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"recentBlockHash\",\"type\":\"bytes32\"}],\"internalType\":\"structVRFBeaconReport.Report\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"exposeType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBilling\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"maximumGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"observationPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"transmissionPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"accountingGas\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingAccessController\",\"outputs\":[{\"internalType\":\"contractAccessControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_coordinator\",\"outputs\":[{\"internalType\":\"contractIVRFCoordinatorProducerAPI\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_link\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashes\",\"type\":\"bytes32[]\"}],\"internalType\":\"structKeyDataStruct.KeyData\",\"name\":\"kd\",\"type\":\"tuple\"}],\"name\":\"keyGenerated\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"availableBalance\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"newKeyRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"}],\"name\":\"owedPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_keyID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_keyProvider\",\"outputs\":[{\"internalType\":\"contractDKG\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_provingKeyHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"maximumGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"observationPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"transmissionPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"accountingGas\",\"type\":\"uint24\"}],\"name\":\"setBilling\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractAccessControllerInterface\",\"name\":\"_billingAccessController\",\"type\":\"address\"}],\"name\":\"setBillingAccessController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b5060405162004dfe38038062004dfe8339810160408190526200003491620001c7565b8181858581813380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000103565b5050506001600160a01b03918216608052811660a052600e80546001600160a01b03191695909116949094179093555060c05250620002219350505050565b336001600160a01b038216036200015d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001c457600080fd5b50565b60008060008060808587031215620001de57600080fd5b8451620001eb81620001ae565b6020860151909450620001fe81620001ae565b60408601519093506200021181620001ae565b6060959095015193969295505050565b60805160a05160c051614b28620002d660003960006104810152600081816103820152818161114e015281816112260152818161131c0152818161141d015281816114bb01528181612216015281816122ee015281816124650152818161275a01528181612b8301528181612c5b0152818161316501526136cd01526000818161032b015281816112540152818161144a0152818161231c015281816124c301528181612c8901526130500152614b286000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c8063afcb95d7116100f9578063d09dc33911610097578063e53bbc9a11610071578063e53bbc9a146104c7578063eb5dcd6c146104da578063f2fde38b146104ed578063fbffd2c11461050057600080fd5b8063d09dc339146104a3578063d57fc45a146104ab578063e3d0e712146104b457600080fd5b8063bf2732c7116100d3578063bf2732c714610438578063c10753291461044b578063c4c92b371461045e578063cc31f7dd1461047c57600080fd5b8063afcb95d7146103e8578063b121e14714610412578063b1dc65a41461042557600080fd5b806379ba5097116101665780638a1b1772116101405780638a1b17721461037d5780638ac28d5a146103a45780638da5cb5b146103b75780639c849b30146103d557600080fd5b806379ba50971461031e5780637d253aff1461032657806381ff70481461034d57600080fd5b806329937268116101a257806329937268146102415780632f7527cc146102b757806355e48749146102d15780635f27026f146102d957600080fd5b806305aeed58146101c95780630eafb25b146101dc578063181f5a7714610202575b600080fd5b6101da6101d73660046137f7565b50565b005b6101ef6101ea366004613854565b610513565b6040519081526020015b60405180910390f35b604080518082018252600f81527f565246426561636f6e20312e302e300000000000000000000000000000000000602082015290516101f991906138df565b60025460035460408051610100840467ffffffffffffffff9081168252690100000000000000000085048116602083015271010000000000000000000000000000000000909404841691810191909152918116606083015268010000000000000000900462ffffff16608082015260a0016101f9565b6102bf600881565b60405160ff90911681526020016101f9565b6101da61059f565b600e546102f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f9565b6101da61061c565b6102f97f000000000000000000000000000000000000000000000000000000000000000081565b6004546005546040805163ffffffff808516825264010000000090940490931660208401528201526060016101f9565b6102f97f000000000000000000000000000000000000000000000000000000000000000081565b6101da6103b2366004613854565b610719565b60005473ffffffffffffffffffffffffffffffffffffffff166102f9565b6101da6103e336600461393e565b610782565b6005546006546040805160008152602081019390935263ffffffff909116908201526060016101f9565b6101da610420366004613854565b6109d4565b6101da6104333660046139ec565b610acc565b6101da610446366004613c89565b610f87565b6101da610459366004613d56565b611046565b600d5473ffffffffffffffffffffffffffffffffffffffff166102f9565b6101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6101ef6113e0565b6101ef600f5481565b6101da6104c2366004613db9565b611573565b6101da6104d5366004613eb8565b611dc9565b6101da6104e8366004613f29565b61201b565b6101da6104fb366004613854565b612174565b6101da61050e366004613854565b612185565b73ffffffffffffffffffffffffffffffffffffffff811660009081526007602090815260408083208151606081018352905460ff80821615158084526101008304909116948301949094526201000090046bffffffffffffffffffffffff1691810191909152906105875750600092915050565b604001516bffffffffffffffffffffffff1692915050565b600e5473ffffffffffffffffffffffffffffffffffffffff16338114610614576040517f292f4fb500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff821660248201526044015b60405180910390fd5b506000600f55565b60015473ffffffffffffffffffffffffffffffffffffffff16331461069d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161060b565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600b6020526040902054163314610779576040517fdce38c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101d781612196565b61078a612569565b8281146107cd576040517f36d20459000000000000000000000000000000000000000000000000000000008152600481018490526024810182905260440161060b565b60005b838110156109cd5760008585838181106107ec576107ec613f62565b90506020020160208101906108019190613854565b9050600084848481811061081757610817613f62565b905060200201602081019061082c9190613854565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600b602052604090205491925016801580158161089257508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b156108e9576040517febdf175600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80861660048301528316602482015260440161060b565b73ffffffffffffffffffffffffffffffffffffffff8481166000908152600b6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016858316908117909155908316146109b6578273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b360405160405180910390a45b5050505080806109c590613fc0565b9150506107d0565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600c6020526040902054163314610a34576040517f9d12ec4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8181166000818152600b602090815260408083208054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217909355600c909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b60005a6040805160c08101825260025460ff808216835267ffffffffffffffff61010083048116602080860191909152690100000000000000000084048216858701527101000000000000000000000000000000000090930481166060850152600354908116608085015262ffffff680100000000000000009091041660a08401523360009081526007835293909320549394509092908c01359116610ba0576040517fb1c1f68e00000000000000000000000000000000000000000000000000000000815233600482015260240161060b565b6005548b3514610bea576005546040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101919091528b35602482015260440161060b565b610bf88a8a8a8a8a8a6125ec565b8151610c05906001613ff8565b60ff1687141580610c165750868514155b15610c6e578151610c28906001613ff8565b6040517ffc33647500000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018890526044810186905260640161060b565b60008a8a604051610c80929190614011565b604051908190038120610c97918e90602001614021565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012083830190925260008084529083018190529092509060005b8a811015610e885760006001858a8460208110610d0457610d04613f62565b610d1191901a601b613ff8565b8f8f86818110610d2357610d23613f62565b905060200201358e8e87818110610d3c57610d3c613f62565b9050602002013560405160008152602001604052604051610d79949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610d9b573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526008602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955092509050610e61576040517f20fb74ee00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161060b565b826020015160080260ff166001901b84019350508080610e8090613fc0565b915050610ce5565b5081827e010101010101010101010101010101010101010101010101010101010101011614610ee3576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060009150819050610f328d826020020135848e8e8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061267c92505050565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff600888901c161790559092509050610f7884838388336128c6565b50505050505050505050505050565b600e5473ffffffffffffffffffffffffffffffffffffffff16338114610ff7576040517f292f4fb500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161060b565b81516040516110099190602001614035565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120600f555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906111075750600d546040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690636b14daf8906110c4903390600090369060040161409a565b602060405180830381865afa1580156110e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110591906140da565b155b1561113e576040517fc04ecc2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611148612a24565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111db91906140f5565b905060006111e9828461410e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561129b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bf91906140f5565b905081811015611305576040517fcf479181000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161060b565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f99b1d688761135561134f8686614121565b89612b1f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b1580156113c057600080fd5b505af11580156113d4573d6000803e3d6000fd5b50505050505050505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611491573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b591906140f5565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611524573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154891906140f5565b90506000611554612a24565b9050816115618285614134565b61156b9190614134565b935050505090565b888787601f8311156115bb576040517f809fc428000000000000000000000000000000000000000000000000000000008152601f60048201526024810184905260440161060b565b8183146115fe576040517f988a0804000000000000000000000000000000000000000000000000000000008152600481018490526024810183905260440161060b565b61160981600361415b565b60ff168311611650576040517ffda9db7800000000000000000000000000000000000000000000000000000000815260ff821660048201526024810184905260440161060b565b61165c8160ff16612b39565b611664612569565b60006040518060c001604052808f8f80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018d8d8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060ff8c1660208083019190915260408051601f8d0183900483028101830182528c8152920191908c908c908190840183828082843760009201919091525050509082525067ffffffffffffffff891660208083019190915260408051601f8a01839004830281018301825289815292019190899089908190840183828082843760009201919091525050509152509050611786612b73565b60095460005b8181101561187f576000600982815481106117a9576117a9613f62565b6000918252602082200154600a805473ffffffffffffffffffffffffffffffffffffffff909216935090849081106117e3576117e3613f62565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff948516835260088252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905594168252600790529190912080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169055508061187781613fc0565b91505061178c565b5061188c6009600061373a565b611898600a600061373a565b60005b825151811015611c215760086000846000015183815181106118bf576118bf613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff161561196357825180518290811061190c5761190c613f62565b60200260200101516040517f7451f83e00000000000000000000000000000000000000000000000000000000815260040161060b919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b604080518082019091526001815260ff82166020820152835180516008916000918590811061199457611994613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281810192909252604001600090812083518154948401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010060ff90951694909402939093179092558401518051600792919084908110611a4657611a46613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611aec5782602001518181518110611a9557611a95613f62565b60200260200101516040517fe8d2989900000000000000000000000000000000000000000000000000000000815260040161060b919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180606001604052806001151581526020018260ff16815260200160006bffffffffffffffffffffffff168152506007600085602001518481518110611b3657611b36613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040908101600020835181549385015194909201516bffffffffffffffffffffffff1662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff931515939093167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090941693909317919091179290921617905580611c1981613fc0565b91505061189b565b5081518051611c3891600991602090910190613758565b506020808301518051611c4f92600a920190613758565b506040820151600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600454640100000000900463ffffffff16611c9f6131d5565b6004805463ffffffff928316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff82168117909255600092611ced9281169116176001614177565b905080600460006101000a81548163ffffffff021916908363ffffffff1602179055506000611d4146308463ffffffff16886000015189602001518a604001518b606001518c608001518d60a0015161326c565b9050806005819055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e058360055484886000015189602001518a604001518b606001518c608001518d60a00151604051611da3999897969594939291906141e5565b60405180910390a1611db58d8d613317565b505050505050505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590611e8a5750600d546040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690636b14daf890611e47903390600090369060040161409a565b602060405180830381865afa158015611e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8891906140da565b155b15611ec1576040517fc04ecc2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ec9612b73565b6002805467ffffffffffffffff8581167101000000000000000000000000000000000081027fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff898416690100000000000000000081027fffffffffffffffffffffffffffffff0000000000000000ffffffffffffffffff8d87166101008102919091167fffffffffffffffffffffffffffffff00000000000000000000000000000000ff909816979097171791909116919091179094556003805462ffffff87166801000000000000000081027fffffffffffffffffffffffffffffffffffffffffff00000000000000000000009092169489169485179190911790915560408051948552602085019590955293830152606082015260808101919091527f49275ddcdfc9c0519b3d094308c8bf675f06070a754ce90c152163cb6e66e8a09060a00160405180910390a15050505050565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600b602052604090205416331461207b576040517fdce38c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811633036120ca576040517fb387a23800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600c6020526040902080548383167fffffffffffffffffffffffff00000000000000000000000000000000000000008216811790925590911690811461216f5760405173ffffffffffffffffffffffffffffffffffffffff8084169133918616907f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836790600090a45b505050565b61217c612569565b6101d781613325565b61218d612569565b6101d78161341a565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600760209081526040918290208251606081018452905460ff80821615158084526101008304909116938301939093526201000090046bffffffffffffffffffffffff1692810192909252612205575050565b600061221083610513565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561227f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a391906140f5565b905060006122b1828461410e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612363573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238791906140f5565b9050818110156123cd576040517fcf479181000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161060b565b83156125615773ffffffffffffffffffffffffffffffffffffffff8681166000908152600b602090815260408083205460079092529182902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905590517ff99b1d680000000000000000000000000000000000000000000000000000000081529082166004820181905260248201879052917f0000000000000000000000000000000000000000000000000000000000000000169063f99b1d6890604401600060405180830381600087803b1580156124a957600080fd5b505af11580156124bd573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c8860405161255791815260200190565b60405180910390a4505b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146125ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161060b565b565b60006125f982602061427b565b61260485602061427b565b6126108861014461410e565b61261a919061410e565b612624919061410e565b61262f90600061410e565b9050368114612673576040517ff7b94f0a0000000000000000000000000000000000000000000000000000000081526004810182905236602482015260440161060b565b50505050505050565b60008060008380602001905181019061269591906144bf565b905060006126a682606001516134c2565b90508082608001511461270957608082015160608301516040517faed0afe500000000000000000000000000000000000000000000000000000000815260048101929092526024820183905267ffffffffffffffff16604482015260640161060b565b81516020830151604080850151606086015191517f76f2e3f400000000000000000000000000000000000000000000000000000000815260009473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016946376f2e3f4946127929492939192916004016147fa565b6020604051808303816000875af11580156127b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d591906140da565b90508061280e576040517f69c920fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8664ffffffffff167ffc3c7a7927e878a0fca37c904953c3c75cee3ca1d1640184a0ab1c65eec6274333856020015186604001518c6040516128a5949392919073ffffffffffffffffffffffffffffffffffffffff94909416845277ffffffffffffffffffffffffffffffffffffffffffffffff92909216602084015267ffffffffffffffff166040830152606082015260800190565b60405180910390a28260200151836040015194509450505050935093915050565b60006128f23a67ffffffffffffffff8616156128e257856128e8565b87604001515b88602001516135a5565b90506010360260005a9050600061291b8663ffffffff1685858c60a0015162ffffff16866135f6565b90506000670de0b6b3a764000077ffffffffffffffffffffffffffffffffffffffffffffffff8a16830273ffffffffffffffffffffffffffffffffffffffff881660009081526007602052604090205460808d01519290910492506201000090046bffffffffffffffffffffffff9081169167ffffffffffffffff16828401019081168211156129b157505050505050506109cd565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260076020526040902080546bffffffffffffffffffffffff90921662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff9092169190911790555050505050505050505050565b600080600a805480602002602001604051908101604052809291908181526020018280548015612a8a57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612a5f575b505083519394506000925050505b81811015612b195760076000848381518110612ab657612ab6613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054612b05906201000090046bffffffffffffffffffffffff168561410e565b935080612b1181613fc0565b915050612a98565b50505090565b600081831015612b30575081612b33565b50805b92915050565b806000036101d7576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612b7d612a24565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c1091906140f5565b90506000612c1e828461410e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612cd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf491906140f5565b905081811015612d3a576040517fcf479181000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161060b565b6000600a805480602002602001604051908101604052809291908181526020018280548015612d9f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612d74575b5050505050905060008151905060008167ffffffffffffffff811115612dc757612dc7613aa3565b604051908082528060200260200182016040528015612df0578160200160208202803683370190505b50905060008267ffffffffffffffff811115612e0e57612e0e613aa3565b604051908082528060200260200182016040528015612e37578160200160208202803683370190505b5090506000805b8481101561311157600060076000888481518110612e5e57612e5e613f62565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160029054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff169050600060076000898581518110612ee457612ee4613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080546bffffffffffffffffffffffff9290921662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff909216919091179055808015613107576000600b60008a8681518110612f7557612f75613f62565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080878681518110612fed57612fed613f62565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508186868151811061303a5761303a613f62565b60200260200101818152505084806001019550507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168a86815181106130ae576130ae613f62565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c856040516130fd91815260200190565b60405180910390a4505b5050600101612e3e565b5081518114613121578082528083525b8151156131ca576040517f73433a2f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906373433a2f9061319c908690869060040161496a565b600060405180830381600087803b1580156131b657600080fd5b505af1158015610f78573d6000803e3d6000fd5b505050505050505050565b60004661a4b18114806131ea575062066eed81145b1561326557606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561323b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061325f91906140f5565b91505090565b4391505090565b6000808a8a8a8a8a8a8a8a8a604051602001613290999897969594939291906149c1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b613321828261363e565b5050565b3373ffffffffffffffffffffffffffffffffffffffff8216036133a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161060b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600d5473ffffffffffffffffffffffffffffffffffffffff908116908216811461332157600d80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84811691821790925560408051928416835260208301919091527f793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d48912910160405180910390a15050565b60004661a4b18114806134d7575062066eed81145b15613595576101008367ffffffffffffffff166134f26131d5565b6134fc9190614121565b111561350b5750600092915050565b6040517f2b407a8200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152606490632b407a8290602401602060405180830381865afa15801561356a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061358e91906140f5565b9392505050565b505067ffffffffffffffff164090565b60008367ffffffffffffffff84168110156135d9576002858567ffffffffffffffff1603816135d6576135d661493b565b04015b6135ed818467ffffffffffffffff16612b1f565b95945050505050565b600081861015613632576040517f3fef97df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50909303019091010290565b610100818114613680578282826040517f418a179b00000000000000000000000000000000000000000000000000000000815260040161060b93929190614a56565b600061368e83850185614a7a565b90506040517f8eef585f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690638eef585f90613702908490600401614ae4565b600060405180830381600087803b15801561371c57600080fd5b505af1158015613730573d6000803e3d6000fd5b5050505050505050565b50805460008255906000526020600020908101906101d791906137e2565b8280548282559060005260206000209081019282156137d2579160200282015b828111156137d257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613778565b506137de9291506137e2565b5090565b5b808211156137de57600081556001016137e3565b60006020828403121561380957600080fd5b813567ffffffffffffffff81111561382057600080fd5b820160a0818503121561358e57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146101d757600080fd5b60006020828403121561386657600080fd5b813561358e81613832565b60005b8381101561388c578181015183820152602001613874565b50506000910152565b600081518084526138ad816020860160208601613871565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061358e6020830184613895565b60008083601f84011261390457600080fd5b50813567ffffffffffffffff81111561391c57600080fd5b6020830191508360208260051b850101111561393757600080fd5b9250929050565b6000806000806040858703121561395457600080fd5b843567ffffffffffffffff8082111561396c57600080fd5b613978888389016138f2565b9096509450602087013591508082111561399157600080fd5b5061399e878288016138f2565b95989497509550505050565b60008083601f8401126139bc57600080fd5b50813567ffffffffffffffff8111156139d457600080fd5b60208301915083602082850101111561393757600080fd5b60008060008060008060008060e0898b031215613a0857600080fd5b606089018a811115613a1957600080fd5b8998503567ffffffffffffffff80821115613a3357600080fd5b613a3f8c838d016139aa565b909950975060808b0135915080821115613a5857600080fd5b613a648c838d016138f2565b909750955060a08b0135915080821115613a7d57600080fd5b50613a8a8b828c016138f2565b999c989b50969995989497949560c00135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613af557613af5613aa3565b60405290565b604051610100810167ffffffffffffffff81118282101715613af557613af5613aa3565b60405160a0810167ffffffffffffffff81118282101715613af557613af5613aa3565b6040516020810167ffffffffffffffff81118282101715613af557613af5613aa3565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bac57613bac613aa3565b604052919050565b600067ffffffffffffffff821115613bce57613bce613aa3565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600067ffffffffffffffff821115613c1457613c14613aa3565b5060051b60200190565b600082601f830112613c2f57600080fd5b81356020613c44613c3f83613bfa565b613b65565b82815260059290921b84018101918181019086841115613c6357600080fd5b8286015b84811015613c7e5780358352918301918301613c67565b509695505050505050565b60006020808385031215613c9c57600080fd5b823567ffffffffffffffff80821115613cb457600080fd5b9084019060408287031215613cc857600080fd5b613cd0613ad2565b823582811115613cdf57600080fd5b8301601f81018813613cf057600080fd5b8035613cfe613c3f82613bb4565b8181528987838501011115613d1257600080fd5b818784018883013760008783830101528084525050508383013582811115613d3957600080fd5b613d4588828601613c1e565b948201949094529695505050505050565b60008060408385031215613d6957600080fd5b8235613d7481613832565b946020939093013593505050565b803560ff81168114613d9357600080fd5b919050565b67ffffffffffffffff811681146101d757600080fd5b8035613d9381613d98565b60008060008060008060008060008060c08b8d031215613dd857600080fd5b8a3567ffffffffffffffff80821115613df057600080fd5b613dfc8e838f016138f2565b909c509a5060208d0135915080821115613e1557600080fd5b613e218e838f016138f2565b909a509850889150613e3560408e01613d82565b975060608d0135915080821115613e4b57600080fd5b613e578e838f016139aa565b9097509550859150613e6b60808e01613dae565b945060a08d0135915080821115613e8157600080fd5b50613e8e8d828e016139aa565b915080935050809150509295989b9194979a5092959850565b62ffffff811681146101d757600080fd5b600080600080600060a08688031215613ed057600080fd5b8535613edb81613d98565b94506020860135613eeb81613d98565b93506040860135613efb81613d98565b92506060860135613f0b81613d98565b91506080860135613f1b81613ea7565b809150509295509295909350565b60008060408385031215613f3c57600080fd5b8235613f4781613832565b91506020830135613f5781613832565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ff157613ff1613f91565b5060010190565b60ff8181168382160190811115612b3357612b33613f91565b8183823760009101908152919050565b828152606082602083013760800192915050565b60008251614047818460208701613871565b9190910192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff841681526040602082015260006135ed604083018486614051565b80518015158114613d9357600080fd5b6000602082840312156140ec57600080fd5b61358e826140ca565b60006020828403121561410757600080fd5b5051919050565b80820180821115612b3357612b33613f91565b81810381811115612b3357612b33613f91565b818103600083128015838313168383128216171561415457614154613f91565b5092915050565b60ff818116838216029081169081811461415457614154613f91565b63ffffffff81811683821601908082111561415457614154613f91565b600081518084526020808501945080840160005b838110156141da57815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016141a8565b509495945050505050565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526142158184018a614194565b905082810360808401526142298189614194565b905060ff871660a084015282810360c08401526142468187613895565b905067ffffffffffffffff851660e084015282810361010084015261426b8185613895565b9c9b505050505050505050505050565b8082028115828204841417612b3357612b33613f91565b8051613d9381613d98565b805161ffff81168114613d9357600080fd5b8051613d9381613832565b600082601f8301126142cb57600080fd5b81516142d9613c3f82613bb4565b8181528460208386010111156142ee57600080fd5b6142ff826020830160208701613871565b949350505050565b80516bffffffffffffffffffffffff81168114613d9357600080fd5b600082601f83011261433457600080fd5b81516020614344613c3f83613bfa565b82815260059290921b8401810191818101908684111561436357600080fd5b8286015b84811015613c7e57805167ffffffffffffffff8082111561438757600080fd5b908801907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06040838c03820112156143be57600080fd5b6143c6613ad2565b87840151838111156143d757600080fd5b8401610100818e03840112156143ec57600080fd5b6143f4613afb565b92508881015183526144086040820161429d565b89840152614418606082016142af565b604084015260808101518481111561442f57600080fd5b61443d8e8b838501016142ba565b60608501525061444f60a08201614307565b608084015260c081015160a084015260e081015160c084015261010081015160e08401525081815261448360408501614307565b818901528652505050918301918301614367565b805177ffffffffffffffffffffffffffffffffffffffffffffffff81168114613d9357600080fd5b6000602082840312156144d157600080fd5b815167ffffffffffffffff808211156144e957600080fd5b9083019060a082860312156144fd57600080fd5b614505613b1f565b82518281111561451457600080fd5b8301601f8101871361452557600080fd5b8051614533613c3f82613bfa565b8082825260208201915060208360051b85010192508983111561455557600080fd5b602084015b838110156146a25780518781111561457157600080fd5b850160c0818d037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00112156145a557600080fd5b6145ad613b1f565b60208201516145bb81613d98565b815260408201516145cb81613ea7565b60208201526040828e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa001121561460257600080fd5b61460a613b42565b8d607f84011261461957600080fd5b614621613ad2565b808f60a08601111561463257600080fd5b606085015b60a08601811015614652578051835260209283019201614637565b50825250604082015260a08201518981111561466d57600080fd5b61467c8e602083860101614323565b60608301525061468e60c083016140ca565b60808201528452506020928301920161455a565b508452506146b591505060208401614497565b60208201526146c660408401614292565b60408201526146d760608401614292565b60608201526080830151608082015280935050505092915050565b600081518084526020808501808196508360051b8101915082860160005b858110156147ed57828403895281516040815181875280518288015287810151606061ffff8216818a01528383015193506080915073ffffffffffffffffffffffffffffffffffffffff8416828a01528083015193505061010060a081818b015261477f6101408b0186613895565b9284015192945060c06147a18b8201856bffffffffffffffffffffffff169052565b9084015160e08b81019190915290840151918a01919091529091015161012088015250908601516bffffffffffffffffffffffff16948601949094529784019790840190600101614710565b5091979650505050505050565b6000608080830181845280885180835260a092508286019150828160051b8701016020808c016000805b858110156148df578a85037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600187528251805167ffffffffffffffff1686528481015162ffffff16858701526040808201515160c091859089015b600282101561489e57825181529188019160019190910190880161487f565b5050506060820151818c8901526148b7828901826146f2565b928c0151801515898d01529291506148cc9050565b9785019795505091830191600101614824565b50505081965061490a8189018c77ffffffffffffffffffffffffffffffffffffffffffffffff169052565b505050505050614926604083018567ffffffffffffffff169052565b67ffffffffffffffff831660608301526135ed565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60408152600061497d6040830185614194565b82810360208481019190915284518083528582019282019060005b818110156149b457845183529383019391830191600101614998565b5090979650505050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614a088285018b614194565b91508382036080850152614a1c828a614194565b915060ff881660a085015283820360c0850152614a398288613895565b90861660e0850152838103610100850152905061426b8185613895565b604081526000614a6a604083018587614051565b9050826020830152949350505050565b6000610100808385031215614a8e57600080fd5b83601f840112614a9d57600080fd5b614aa5613afb565b908301908085831115614ab757600080fd5b845b83811015614ada578035614acc81613ea7565b835260209283019201614ab9565b5095945050505050565b6101008101818360005b6008811015614b1257815162ffffff16835260209283019290910190600101614aee565b5050509291505056fea164736f6c6343000813000a", +} + +var VRFBeaconABI = VRFBeaconMetaData.ABI + +var VRFBeaconBin = VRFBeaconMetaData.Bin + +func DeployVRFBeacon(auth *bind.TransactOpts, backend bind.ContractBackend, link common.Address, coordinator common.Address, keyProvider common.Address, keyID [32]byte) (common.Address, *types.Transaction, *VRFBeacon, error) { + parsed, err := VRFBeaconMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(VRFBeaconBin), backend, link, coordinator, keyProvider, keyID) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &VRFBeacon{VRFBeaconCaller: VRFBeaconCaller{contract: contract}, VRFBeaconTransactor: VRFBeaconTransactor{contract: contract}, VRFBeaconFilterer: VRFBeaconFilterer{contract: contract}}, nil +} + +type VRFBeacon struct { + address common.Address + abi abi.ABI + VRFBeaconCaller + VRFBeaconTransactor + VRFBeaconFilterer +} + +type VRFBeaconCaller struct { + contract *bind.BoundContract +} + +type VRFBeaconTransactor struct { + contract *bind.BoundContract +} + +type VRFBeaconFilterer struct { + contract *bind.BoundContract +} + +type VRFBeaconSession struct { + Contract *VRFBeacon + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type VRFBeaconCallerSession struct { + Contract *VRFBeaconCaller + CallOpts bind.CallOpts +} + +type VRFBeaconTransactorSession struct { + Contract *VRFBeaconTransactor + TransactOpts bind.TransactOpts +} + +type VRFBeaconRaw struct { + Contract *VRFBeacon +} + +type VRFBeaconCallerRaw struct { + Contract *VRFBeaconCaller +} + +type VRFBeaconTransactorRaw struct { + Contract *VRFBeaconTransactor +} + +func NewVRFBeacon(address common.Address, backend bind.ContractBackend) (*VRFBeacon, error) { + abi, err := abi.JSON(strings.NewReader(VRFBeaconABI)) + if err != nil { + return nil, err + } + contract, err := bindVRFBeacon(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &VRFBeacon{address: address, abi: abi, VRFBeaconCaller: VRFBeaconCaller{contract: contract}, VRFBeaconTransactor: VRFBeaconTransactor{contract: contract}, VRFBeaconFilterer: VRFBeaconFilterer{contract: contract}}, nil +} + +func NewVRFBeaconCaller(address common.Address, caller bind.ContractCaller) (*VRFBeaconCaller, error) { + contract, err := bindVRFBeacon(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VRFBeaconCaller{contract: contract}, nil +} + +func NewVRFBeaconTransactor(address common.Address, transactor bind.ContractTransactor) (*VRFBeaconTransactor, error) { + contract, err := bindVRFBeacon(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VRFBeaconTransactor{contract: contract}, nil +} + +func NewVRFBeaconFilterer(address common.Address, filterer bind.ContractFilterer) (*VRFBeaconFilterer, error) { + contract, err := bindVRFBeacon(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VRFBeaconFilterer{contract: contract}, nil +} + +func bindVRFBeacon(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VRFBeaconMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_VRFBeacon *VRFBeaconRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFBeacon.Contract.VRFBeaconCaller.contract.Call(opts, result, method, params...) +} + +func (_VRFBeacon *VRFBeaconRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.Contract.VRFBeaconTransactor.contract.Transfer(opts) +} + +func (_VRFBeacon *VRFBeaconRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFBeacon.Contract.VRFBeaconTransactor.contract.Transact(opts, method, params...) +} + +func (_VRFBeacon *VRFBeaconCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFBeacon.Contract.contract.Call(opts, result, method, params...) +} + +func (_VRFBeacon *VRFBeaconTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.Contract.contract.Transfer(opts) +} + +func (_VRFBeacon *VRFBeaconTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFBeacon.Contract.contract.Transact(opts, method, params...) +} + +func (_VRFBeacon *VRFBeaconCaller) NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "NUM_CONF_DELAYS") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) NUMCONFDELAYS() (uint8, error) { + return _VRFBeacon.Contract.NUMCONFDELAYS(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) NUMCONFDELAYS() (uint8, error) { + return _VRFBeacon.Contract.NUMCONFDELAYS(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) GetBilling(opts *bind.CallOpts) (GetBilling, + + error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "getBilling") + + outstruct := new(GetBilling) + if err != nil { + return *outstruct, err + } + + outstruct.MaximumGasPrice = *abi.ConvertType(out[0], new(uint64)).(*uint64) + outstruct.ReasonableGasPrice = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.ObservationPayment = *abi.ConvertType(out[2], new(uint64)).(*uint64) + outstruct.TransmissionPayment = *abi.ConvertType(out[3], new(uint64)).(*uint64) + outstruct.AccountingGas = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_VRFBeacon *VRFBeaconSession) GetBilling() (GetBilling, + + error) { + return _VRFBeacon.Contract.GetBilling(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) GetBilling() (GetBilling, + + error) { + return _VRFBeacon.Contract.GetBilling(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) GetBillingAccessController(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "getBillingAccessController") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) GetBillingAccessController() (common.Address, error) { + return _VRFBeacon.Contract.GetBillingAccessController(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) GetBillingAccessController() (common.Address, error) { + return _VRFBeacon.Contract.GetBillingAccessController(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) ICoordinator(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "i_coordinator") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) ICoordinator() (common.Address, error) { + return _VRFBeacon.Contract.ICoordinator(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) ICoordinator() (common.Address, error) { + return _VRFBeacon.Contract.ICoordinator(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) ILink(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "i_link") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) ILink() (common.Address, error) { + return _VRFBeacon.Contract.ILink(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) ILink() (common.Address, error) { + return _VRFBeacon.Contract.ILink(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "latestConfigDetails") + + outstruct := new(LatestConfigDetails) + if err != nil { + return *outstruct, err + } + + outstruct.ConfigCount = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.BlockNumber = *abi.ConvertType(out[1], new(uint32)).(*uint32) + outstruct.ConfigDigest = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +func (_VRFBeacon *VRFBeaconSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _VRFBeacon.Contract.LatestConfigDetails(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _VRFBeacon.Contract.LatestConfigDetails(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "latestConfigDigestAndEpoch") + + outstruct := new(LatestConfigDigestAndEpoch) + if err != nil { + return *outstruct, err + } + + outstruct.ScanLogs = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.Epoch = *abi.ConvertType(out[2], new(uint32)).(*uint32) + + return *outstruct, err + +} + +func (_VRFBeacon *VRFBeaconSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _VRFBeacon.Contract.LatestConfigDigestAndEpoch(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _VRFBeacon.Contract.LatestConfigDigestAndEpoch(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "linkAvailableForPayment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) LinkAvailableForPayment() (*big.Int, error) { + return _VRFBeacon.Contract.LinkAvailableForPayment(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) LinkAvailableForPayment() (*big.Int, error) { + return _VRFBeacon.Contract.LinkAvailableForPayment(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) OwedPayment(opts *bind.CallOpts, transmitterAddress common.Address) (*big.Int, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "owedPayment", transmitterAddress) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) OwedPayment(transmitterAddress common.Address) (*big.Int, error) { + return _VRFBeacon.Contract.OwedPayment(&_VRFBeacon.CallOpts, transmitterAddress) +} + +func (_VRFBeacon *VRFBeaconCallerSession) OwedPayment(transmitterAddress common.Address) (*big.Int, error) { + return _VRFBeacon.Contract.OwedPayment(&_VRFBeacon.CallOpts, transmitterAddress) +} + +func (_VRFBeacon *VRFBeaconCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) Owner() (common.Address, error) { + return _VRFBeacon.Contract.Owner(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) Owner() (common.Address, error) { + return _VRFBeacon.Contract.Owner(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) SKeyID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "s_keyID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) SKeyID() ([32]byte, error) { + return _VRFBeacon.Contract.SKeyID(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) SKeyID() ([32]byte, error) { + return _VRFBeacon.Contract.SKeyID(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) SKeyProvider(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "s_keyProvider") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) SKeyProvider() (common.Address, error) { + return _VRFBeacon.Contract.SKeyProvider(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) SKeyProvider() (common.Address, error) { + return _VRFBeacon.Contract.SKeyProvider(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) SProvingKeyHash(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "s_provingKeyHash") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) SProvingKeyHash() ([32]byte, error) { + return _VRFBeacon.Contract.SProvingKeyHash(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) SProvingKeyHash() ([32]byte, error) { + return _VRFBeacon.Contract.SProvingKeyHash(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) TypeAndVersion() (string, error) { + return _VRFBeacon.Contract.TypeAndVersion(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) TypeAndVersion() (string, error) { + return _VRFBeacon.Contract.TypeAndVersion(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "acceptOwnership") +} + +func (_VRFBeacon *VRFBeaconSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptOwnership(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptOwnership(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactor) AcceptPayeeship(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "acceptPayeeship", transmitter) +} + +func (_VRFBeacon *VRFBeaconSession) AcceptPayeeship(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptPayeeship(&_VRFBeacon.TransactOpts, transmitter) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) AcceptPayeeship(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptPayeeship(&_VRFBeacon.TransactOpts, transmitter) +} + +func (_VRFBeacon *VRFBeaconTransactor) ExposeType(opts *bind.TransactOpts, arg0 VRFBeaconReportReport) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "exposeType", arg0) +} + +func (_VRFBeacon *VRFBeaconSession) ExposeType(arg0 VRFBeaconReportReport) (*types.Transaction, error) { + return _VRFBeacon.Contract.ExposeType(&_VRFBeacon.TransactOpts, arg0) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) ExposeType(arg0 VRFBeaconReportReport) (*types.Transaction, error) { + return _VRFBeacon.Contract.ExposeType(&_VRFBeacon.TransactOpts, arg0) +} + +func (_VRFBeacon *VRFBeaconTransactor) KeyGenerated(opts *bind.TransactOpts, kd KeyDataStructKeyData) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "keyGenerated", kd) +} + +func (_VRFBeacon *VRFBeaconSession) KeyGenerated(kd KeyDataStructKeyData) (*types.Transaction, error) { + return _VRFBeacon.Contract.KeyGenerated(&_VRFBeacon.TransactOpts, kd) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) KeyGenerated(kd KeyDataStructKeyData) (*types.Transaction, error) { + return _VRFBeacon.Contract.KeyGenerated(&_VRFBeacon.TransactOpts, kd) +} + +func (_VRFBeacon *VRFBeaconTransactor) NewKeyRequested(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "newKeyRequested") +} + +func (_VRFBeacon *VRFBeaconSession) NewKeyRequested() (*types.Transaction, error) { + return _VRFBeacon.Contract.NewKeyRequested(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) NewKeyRequested() (*types.Transaction, error) { + return _VRFBeacon.Contract.NewKeyRequested(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetBilling(opts *bind.TransactOpts, maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setBilling", maximumGasPrice, reasonableGasPrice, observationPayment, transmissionPayment, accountingGas) +} + +func (_VRFBeacon *VRFBeaconSession) SetBilling(maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBilling(&_VRFBeacon.TransactOpts, maximumGasPrice, reasonableGasPrice, observationPayment, transmissionPayment, accountingGas) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetBilling(maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBilling(&_VRFBeacon.TransactOpts, maximumGasPrice, reasonableGasPrice, observationPayment, transmissionPayment, accountingGas) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetBillingAccessController(opts *bind.TransactOpts, _billingAccessController common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setBillingAccessController", _billingAccessController) +} + +func (_VRFBeacon *VRFBeaconSession) SetBillingAccessController(_billingAccessController common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBillingAccessController(&_VRFBeacon.TransactOpts, _billingAccessController) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetBillingAccessController(_billingAccessController common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBillingAccessController(&_VRFBeacon.TransactOpts, _billingAccessController) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetConfig(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setConfig", signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_VRFBeacon *VRFBeaconSession) SetConfig(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetConfig(&_VRFBeacon.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetConfig(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetConfig(&_VRFBeacon.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetPayees(opts *bind.TransactOpts, transmitters []common.Address, payees []common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setPayees", transmitters, payees) +} + +func (_VRFBeacon *VRFBeaconSession) SetPayees(transmitters []common.Address, payees []common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetPayees(&_VRFBeacon.TransactOpts, transmitters, payees) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetPayees(transmitters []common.Address, payees []common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetPayees(&_VRFBeacon.TransactOpts, transmitters, payees) +} + +func (_VRFBeacon *VRFBeaconTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "transferOwnership", to) +} + +func (_VRFBeacon *VRFBeaconSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferOwnership(&_VRFBeacon.TransactOpts, to) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferOwnership(&_VRFBeacon.TransactOpts, to) +} + +func (_VRFBeacon *VRFBeaconTransactor) TransferPayeeship(opts *bind.TransactOpts, transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "transferPayeeship", transmitter, proposed) +} + +func (_VRFBeacon *VRFBeaconSession) TransferPayeeship(transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferPayeeship(&_VRFBeacon.TransactOpts, transmitter, proposed) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) TransferPayeeship(transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferPayeeship(&_VRFBeacon.TransactOpts, transmitter, proposed) +} + +func (_VRFBeacon *VRFBeaconTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "transmit", reportContext, report, rs, ss, rawVs) +} + +func (_VRFBeacon *VRFBeaconSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.Transmit(&_VRFBeacon.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.Transmit(&_VRFBeacon.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_VRFBeacon *VRFBeaconTransactor) WithdrawFunds(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "withdrawFunds", recipient, amount) +} + +func (_VRFBeacon *VRFBeaconSession) WithdrawFunds(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawFunds(&_VRFBeacon.TransactOpts, recipient, amount) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) WithdrawFunds(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawFunds(&_VRFBeacon.TransactOpts, recipient, amount) +} + +func (_VRFBeacon *VRFBeaconTransactor) WithdrawPayment(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "withdrawPayment", transmitter) +} + +func (_VRFBeacon *VRFBeaconSession) WithdrawPayment(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawPayment(&_VRFBeacon.TransactOpts, transmitter) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) WithdrawPayment(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawPayment(&_VRFBeacon.TransactOpts, transmitter) +} + +type VRFBeaconBillingAccessControllerSetIterator struct { + Event *VRFBeaconBillingAccessControllerSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconBillingAccessControllerSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingAccessControllerSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingAccessControllerSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconBillingAccessControllerSetIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconBillingAccessControllerSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconBillingAccessControllerSet struct { + Old common.Address + Current common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterBillingAccessControllerSet(opts *bind.FilterOpts) (*VRFBeaconBillingAccessControllerSetIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "BillingAccessControllerSet") + if err != nil { + return nil, err + } + return &VRFBeaconBillingAccessControllerSetIterator{contract: _VRFBeacon.contract, event: "BillingAccessControllerSet", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchBillingAccessControllerSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingAccessControllerSet) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "BillingAccessControllerSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconBillingAccessControllerSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingAccessControllerSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseBillingAccessControllerSet(log types.Log) (*VRFBeaconBillingAccessControllerSet, error) { + event := new(VRFBeaconBillingAccessControllerSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingAccessControllerSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconBillingSetIterator struct { + Event *VRFBeaconBillingSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconBillingSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconBillingSetIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconBillingSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconBillingSet struct { + MaximumGasPrice uint64 + ReasonableGasPrice uint64 + ObservationPayment uint64 + TransmissionPayment uint64 + AccountingGas *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterBillingSet(opts *bind.FilterOpts) (*VRFBeaconBillingSetIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "BillingSet") + if err != nil { + return nil, err + } + return &VRFBeaconBillingSetIterator{contract: _VRFBeacon.contract, event: "BillingSet", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchBillingSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingSet) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "BillingSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconBillingSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseBillingSet(log types.Log) (*VRFBeaconBillingSet, error) { + event := new(VRFBeaconBillingSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconConfigSetIterator struct { + Event *VRFBeaconConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconConfigSetIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconConfigSet struct { + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterConfigSet(opts *bind.FilterOpts) (*VRFBeaconConfigSetIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &VRFBeaconConfigSetIterator{contract: _VRFBeacon.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconConfigSet) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconConfigSet) + if err := _VRFBeacon.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseConfigSet(log types.Log) (*VRFBeaconConfigSet, error) { + event := new(VRFBeaconConfigSet) + if err := _VRFBeacon.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconNewTransmissionIterator struct { + Event *VRFBeaconNewTransmission + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconNewTransmissionIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconNewTransmission) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconNewTransmission) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconNewTransmissionIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconNewTransmissionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconNewTransmission struct { + EpochAndRound *big.Int + Transmitter common.Address + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + ConfigDigest [32]byte + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterNewTransmission(opts *bind.FilterOpts, epochAndRound []*big.Int) (*VRFBeaconNewTransmissionIterator, error) { + + var epochAndRoundRule []interface{} + for _, epochAndRoundItem := range epochAndRound { + epochAndRoundRule = append(epochAndRoundRule, epochAndRoundItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "NewTransmission", epochAndRoundRule) + if err != nil { + return nil, err + } + return &VRFBeaconNewTransmissionIterator{contract: _VRFBeacon.contract, event: "NewTransmission", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchNewTransmission(opts *bind.WatchOpts, sink chan<- *VRFBeaconNewTransmission, epochAndRound []*big.Int) (event.Subscription, error) { + + var epochAndRoundRule []interface{} + for _, epochAndRoundItem := range epochAndRound { + epochAndRoundRule = append(epochAndRoundRule, epochAndRoundItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "NewTransmission", epochAndRoundRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconNewTransmission) + if err := _VRFBeacon.contract.UnpackLog(event, "NewTransmission", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseNewTransmission(log types.Log) (*VRFBeaconNewTransmission, error) { + event := new(VRFBeaconNewTransmission) + if err := _VRFBeacon.contract.UnpackLog(event, "NewTransmission", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOraclePaidIterator struct { + Event *VRFBeaconOraclePaid + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOraclePaidIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOraclePaid) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOraclePaid) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOraclePaidIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOraclePaidIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOraclePaid struct { + Transmitter common.Address + Payee common.Address + Amount *big.Int + LinkToken common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOraclePaid(opts *bind.FilterOpts, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (*VRFBeaconOraclePaidIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var payeeRule []interface{} + for _, payeeItem := range payee { + payeeRule = append(payeeRule, payeeItem) + } + + var linkTokenRule []interface{} + for _, linkTokenItem := range linkToken { + linkTokenRule = append(linkTokenRule, linkTokenItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OraclePaid", transmitterRule, payeeRule, linkTokenRule) + if err != nil { + return nil, err + } + return &VRFBeaconOraclePaidIterator{contract: _VRFBeacon.contract, event: "OraclePaid", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOraclePaid(opts *bind.WatchOpts, sink chan<- *VRFBeaconOraclePaid, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var payeeRule []interface{} + for _, payeeItem := range payee { + payeeRule = append(payeeRule, payeeItem) + } + + var linkTokenRule []interface{} + for _, linkTokenItem := range linkToken { + linkTokenRule = append(linkTokenRule, linkTokenItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OraclePaid", transmitterRule, payeeRule, linkTokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOraclePaid) + if err := _VRFBeacon.contract.UnpackLog(event, "OraclePaid", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOraclePaid(log types.Log) (*VRFBeaconOraclePaid, error) { + event := new(VRFBeaconOraclePaid) + if err := _VRFBeacon.contract.UnpackLog(event, "OraclePaid", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOutputsServedIterator struct { + Event *VRFBeaconOutputsServed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOutputsServedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOutputsServedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOutputsServedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOutputsServed struct { + RecentBlockHeight uint64 + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + OutputsServed []VRFBeaconTypesOutputServed + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOutputsServed(opts *bind.FilterOpts) (*VRFBeaconOutputsServedIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return &VRFBeaconOutputsServedIterator{contract: _VRFBeacon.contract, event: "OutputsServed", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFBeaconOutputsServed) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOutputsServed) + if err := _VRFBeacon.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOutputsServed(log types.Log) (*VRFBeaconOutputsServed, error) { + event := new(VRFBeaconOutputsServed) + if err := _VRFBeacon.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOwnershipTransferRequestedIterator struct { + Event *VRFBeaconOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFBeaconOwnershipTransferRequestedIterator{contract: _VRFBeacon.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOwnershipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOwnershipTransferRequested(log types.Log) (*VRFBeaconOwnershipTransferRequested, error) { + event := new(VRFBeaconOwnershipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOwnershipTransferredIterator struct { + Event *VRFBeaconOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFBeaconOwnershipTransferredIterator{contract: _VRFBeacon.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOwnershipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOwnershipTransferred(log types.Log) (*VRFBeaconOwnershipTransferred, error) { + event := new(VRFBeaconOwnershipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconPayeeshipTransferRequestedIterator struct { + Event *VRFBeaconPayeeshipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconPayeeshipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconPayeeshipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconPayeeshipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconPayeeshipTransferRequested struct { + Transmitter common.Address + Current common.Address + Proposed common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterPayeeshipTransferRequested(opts *bind.FilterOpts, transmitter []common.Address, current []common.Address, proposed []common.Address) (*VRFBeaconPayeeshipTransferRequestedIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + var proposedRule []interface{} + for _, proposedItem := range proposed { + proposedRule = append(proposedRule, proposedItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "PayeeshipTransferRequested", transmitterRule, currentRule, proposedRule) + if err != nil { + return nil, err + } + return &VRFBeaconPayeeshipTransferRequestedIterator{contract: _VRFBeacon.contract, event: "PayeeshipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchPayeeshipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferRequested, transmitter []common.Address, current []common.Address, proposed []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + var proposedRule []interface{} + for _, proposedItem := range proposed { + proposedRule = append(proposedRule, proposedItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "PayeeshipTransferRequested", transmitterRule, currentRule, proposedRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconPayeeshipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParsePayeeshipTransferRequested(log types.Log) (*VRFBeaconPayeeshipTransferRequested, error) { + event := new(VRFBeaconPayeeshipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconPayeeshipTransferredIterator struct { + Event *VRFBeaconPayeeshipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconPayeeshipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconPayeeshipTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconPayeeshipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconPayeeshipTransferred struct { + Transmitter common.Address + Previous common.Address + Current common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterPayeeshipTransferred(opts *bind.FilterOpts, transmitter []common.Address, previous []common.Address, current []common.Address) (*VRFBeaconPayeeshipTransferredIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var previousRule []interface{} + for _, previousItem := range previous { + previousRule = append(previousRule, previousItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "PayeeshipTransferred", transmitterRule, previousRule, currentRule) + if err != nil { + return nil, err + } + return &VRFBeaconPayeeshipTransferredIterator{contract: _VRFBeacon.contract, event: "PayeeshipTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchPayeeshipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferred, transmitter []common.Address, previous []common.Address, current []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var previousRule []interface{} + for _, previousItem := range previous { + previousRule = append(previousRule, previousItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "PayeeshipTransferred", transmitterRule, previousRule, currentRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconPayeeshipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParsePayeeshipTransferred(log types.Log) (*VRFBeaconPayeeshipTransferred, error) { + event := new(VRFBeaconPayeeshipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomWordsFulfilledIterator struct { + Event *VRFBeaconRandomWordsFulfilled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomWordsFulfilledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomWordsFulfilledIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomWordsFulfilledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomWordsFulfilled struct { + RequestIDs []*big.Int + SuccessfulFulfillment []byte + TruncatedErrorData [][]byte + SubBalances []*big.Int + SubIDs []*big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFBeaconRandomWordsFulfilledIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return &VRFBeaconRandomWordsFulfilledIterator{contract: _VRFBeacon.contract, event: "RandomWordsFulfilled", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomWordsFulfilled) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomWordsFulfilled) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomWordsFulfilled(log types.Log) (*VRFBeaconRandomWordsFulfilled, error) { + event := new(VRFBeaconRandomWordsFulfilled) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomnessFulfillmentRequestedIterator struct { + Event *VRFBeaconRandomnessFulfillmentRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomnessFulfillmentRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomnessFulfillmentRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomnessFulfillmentRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomnessFulfillmentRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + GasAllowance uint32 + GasPrice *big.Int + WeiPerUnitLink *big.Int + Arguments []byte + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessFulfillmentRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFBeaconRandomnessFulfillmentRequestedIterator{contract: _VRFBeacon.contract, event: "RandomnessFulfillmentRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomnessFulfillmentRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomnessFulfillmentRequested(log types.Log) (*VRFBeaconRandomnessFulfillmentRequested, error) { + event := new(VRFBeaconRandomnessFulfillmentRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomnessRedeemedIterator struct { + Event *VRFBeaconRandomnessRedeemed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomnessRedeemedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomnessRedeemedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomnessRedeemedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomnessRedeemed struct { + RequestID *big.Int + Requester common.Address + SubID *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFBeaconRandomnessRedeemedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return &VRFBeaconRandomnessRedeemedIterator{contract: _VRFBeacon.contract, event: "RandomnessRedeemed", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomnessRedeemed) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomnessRedeemed(log types.Log) (*VRFBeaconRandomnessRedeemed, error) { + event := new(VRFBeaconRandomnessRedeemed) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomnessRequestedIterator struct { + Event *VRFBeaconRandomnessRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomnessRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomnessRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomnessRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomnessRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFBeaconRandomnessRequestedIterator{contract: _VRFBeacon.contract, event: "RandomnessRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomnessRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomnessRequested(log types.Log) (*VRFBeaconRandomnessRequested, error) { + event := new(VRFBeaconRandomnessRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetBilling struct { + MaximumGasPrice uint64 + ReasonableGasPrice uint64 + ObservationPayment uint64 + TransmissionPayment uint64 + AccountingGas *big.Int +} +type LatestConfigDetails struct { + ConfigCount uint32 + BlockNumber uint32 + ConfigDigest [32]byte +} +type LatestConfigDigestAndEpoch struct { + ScanLogs bool + ConfigDigest [32]byte + Epoch uint32 +} + +func (_VRFBeacon *VRFBeacon) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _VRFBeacon.abi.Events["BillingAccessControllerSet"].ID: + return _VRFBeacon.ParseBillingAccessControllerSet(log) + case _VRFBeacon.abi.Events["BillingSet"].ID: + return _VRFBeacon.ParseBillingSet(log) + case _VRFBeacon.abi.Events["ConfigSet"].ID: + return _VRFBeacon.ParseConfigSet(log) + case _VRFBeacon.abi.Events["NewTransmission"].ID: + return _VRFBeacon.ParseNewTransmission(log) + case _VRFBeacon.abi.Events["OraclePaid"].ID: + return _VRFBeacon.ParseOraclePaid(log) + case _VRFBeacon.abi.Events["OutputsServed"].ID: + return _VRFBeacon.ParseOutputsServed(log) + case _VRFBeacon.abi.Events["OwnershipTransferRequested"].ID: + return _VRFBeacon.ParseOwnershipTransferRequested(log) + case _VRFBeacon.abi.Events["OwnershipTransferred"].ID: + return _VRFBeacon.ParseOwnershipTransferred(log) + case _VRFBeacon.abi.Events["PayeeshipTransferRequested"].ID: + return _VRFBeacon.ParsePayeeshipTransferRequested(log) + case _VRFBeacon.abi.Events["PayeeshipTransferred"].ID: + return _VRFBeacon.ParsePayeeshipTransferred(log) + case _VRFBeacon.abi.Events["RandomWordsFulfilled"].ID: + return _VRFBeacon.ParseRandomWordsFulfilled(log) + case _VRFBeacon.abi.Events["RandomnessFulfillmentRequested"].ID: + return _VRFBeacon.ParseRandomnessFulfillmentRequested(log) + case _VRFBeacon.abi.Events["RandomnessRedeemed"].ID: + return _VRFBeacon.ParseRandomnessRedeemed(log) + case _VRFBeacon.abi.Events["RandomnessRequested"].ID: + return _VRFBeacon.ParseRandomnessRequested(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (VRFBeaconBillingAccessControllerSet) Topic() common.Hash { + return common.HexToHash("0x793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d48912") +} + +func (VRFBeaconBillingSet) Topic() common.Hash { + return common.HexToHash("0x49275ddcdfc9c0519b3d094308c8bf675f06070a754ce90c152163cb6e66e8a0") +} + +func (VRFBeaconConfigSet) Topic() common.Hash { + return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") +} + +func (VRFBeaconNewTransmission) Topic() common.Hash { + return common.HexToHash("0xfc3c7a7927e878a0fca37c904953c3c75cee3ca1d1640184a0ab1c65eec62743") +} + +func (VRFBeaconOraclePaid) Topic() common.Hash { + return common.HexToHash("0xd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c") +} + +func (VRFBeaconOutputsServed) Topic() common.Hash { + return common.HexToHash("0xf10ea936d00579b4c52035ee33bf46929646b3aa87554c565d8fb2c7aa549c44") +} + +func (VRFBeaconOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (VRFBeaconOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (VRFBeaconPayeeshipTransferRequested) Topic() common.Hash { + return common.HexToHash("0x84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e38367") +} + +func (VRFBeaconPayeeshipTransferred) Topic() common.Hash { + return common.HexToHash("0x78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b3") +} + +func (VRFBeaconRandomWordsFulfilled) Topic() common.Hash { + return common.HexToHash("0x8f79f730779e875ce76c428039cc2052b5b5918c2a55c598fab251c1198aec54") +} + +func (VRFBeaconRandomnessFulfillmentRequested) Topic() common.Hash { + return common.HexToHash("0x01872fb9c7d6d68af06a17347935e04412da302a377224c205e672c26e18c37f") +} + +func (VRFBeaconRandomnessRedeemed) Topic() common.Hash { + return common.HexToHash("0x16f3f633197fafab10a5df69e6f3f2f7f20092f08d8d47de0a91c0f4b96a1a25") +} + +func (VRFBeaconRandomnessRequested) Topic() common.Hash { + return common.HexToHash("0xb7933fba96b6b452eb44f99fdc08052a45dff82363d59abaff0456931c3d2459") +} + +func (_VRFBeacon *VRFBeacon) Address() common.Address { + return _VRFBeacon.address +} + +type VRFBeaconInterface interface { + NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) + + GetBilling(opts *bind.CallOpts) (GetBilling, + + error) + + GetBillingAccessController(opts *bind.CallOpts) (common.Address, error) + + ICoordinator(opts *bind.CallOpts) (common.Address, error) + + ILink(opts *bind.CallOpts) (common.Address, error) + + LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) + + LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) + + LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) + + OwedPayment(opts *bind.CallOpts, transmitterAddress common.Address) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SKeyID(opts *bind.CallOpts) ([32]byte, error) + + SKeyProvider(opts *bind.CallOpts) (common.Address, error) + + SProvingKeyHash(opts *bind.CallOpts) ([32]byte, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AcceptPayeeship(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) + + ExposeType(opts *bind.TransactOpts, arg0 VRFBeaconReportReport) (*types.Transaction, error) + + KeyGenerated(opts *bind.TransactOpts, kd KeyDataStructKeyData) (*types.Transaction, error) + + NewKeyRequested(opts *bind.TransactOpts) (*types.Transaction, error) + + SetBilling(opts *bind.TransactOpts, maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) + + SetBillingAccessController(opts *bind.TransactOpts, _billingAccessController common.Address) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) + + SetPayees(opts *bind.TransactOpts, transmitters []common.Address, payees []common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + TransferPayeeship(opts *bind.TransactOpts, transmitter common.Address, proposed common.Address) (*types.Transaction, error) + + Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + + WithdrawFunds(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) + + WithdrawPayment(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) + + FilterBillingAccessControllerSet(opts *bind.FilterOpts) (*VRFBeaconBillingAccessControllerSetIterator, error) + + WatchBillingAccessControllerSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingAccessControllerSet) (event.Subscription, error) + + ParseBillingAccessControllerSet(log types.Log) (*VRFBeaconBillingAccessControllerSet, error) + + FilterBillingSet(opts *bind.FilterOpts) (*VRFBeaconBillingSetIterator, error) + + WatchBillingSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingSet) (event.Subscription, error) + + ParseBillingSet(log types.Log) (*VRFBeaconBillingSet, error) + + FilterConfigSet(opts *bind.FilterOpts) (*VRFBeaconConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*VRFBeaconConfigSet, error) + + FilterNewTransmission(opts *bind.FilterOpts, epochAndRound []*big.Int) (*VRFBeaconNewTransmissionIterator, error) + + WatchNewTransmission(opts *bind.WatchOpts, sink chan<- *VRFBeaconNewTransmission, epochAndRound []*big.Int) (event.Subscription, error) + + ParseNewTransmission(log types.Log) (*VRFBeaconNewTransmission, error) + + FilterOraclePaid(opts *bind.FilterOpts, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (*VRFBeaconOraclePaidIterator, error) + + WatchOraclePaid(opts *bind.WatchOpts, sink chan<- *VRFBeaconOraclePaid, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (event.Subscription, error) + + ParseOraclePaid(log types.Log) (*VRFBeaconOraclePaid, error) + + FilterOutputsServed(opts *bind.FilterOpts) (*VRFBeaconOutputsServedIterator, error) + + WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFBeaconOutputsServed) (event.Subscription, error) + + ParseOutputsServed(log types.Log) (*VRFBeaconOutputsServed, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*VRFBeaconOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*VRFBeaconOwnershipTransferred, error) + + FilterPayeeshipTransferRequested(opts *bind.FilterOpts, transmitter []common.Address, current []common.Address, proposed []common.Address) (*VRFBeaconPayeeshipTransferRequestedIterator, error) + + WatchPayeeshipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferRequested, transmitter []common.Address, current []common.Address, proposed []common.Address) (event.Subscription, error) + + ParsePayeeshipTransferRequested(log types.Log) (*VRFBeaconPayeeshipTransferRequested, error) + + FilterPayeeshipTransferred(opts *bind.FilterOpts, transmitter []common.Address, previous []common.Address, current []common.Address) (*VRFBeaconPayeeshipTransferredIterator, error) + + WatchPayeeshipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferred, transmitter []common.Address, previous []common.Address, current []common.Address) (event.Subscription, error) + + ParsePayeeshipTransferred(log types.Log) (*VRFBeaconPayeeshipTransferred, error) + + FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFBeaconRandomWordsFulfilledIterator, error) + + WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomWordsFulfilled) (event.Subscription, error) + + ParseRandomWordsFulfilled(log types.Log) (*VRFBeaconRandomWordsFulfilled, error) + + FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessFulfillmentRequestedIterator, error) + + WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessFulfillmentRequested(log types.Log) (*VRFBeaconRandomnessFulfillmentRequested, error) + + FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFBeaconRandomnessRedeemedIterator, error) + + WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) + + ParseRandomnessRedeemed(log types.Log) (*VRFBeaconRandomnessRedeemed, error) + + FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessRequestedIterator, error) + + WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessRequested(log types.Log) (*VRFBeaconRandomnessRequested, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer/vrf_beacon_consumer.go b/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer/vrf_beacon_consumer.go new file mode 100644 index 00000000000..edc4ec6556d --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer/vrf_beacon_consumer.go @@ -0,0 +1,1034 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vrf_beacon_consumer + +import ( + "errors" + "fmt" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var BeaconVRFConsumerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"beaconPeriodBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"MustBeCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeOwnerOrCoordinator\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fail\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_beaconPeriodBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_ReceivedRandomnessByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_arguments\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_gasAvailable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_mostRecentRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_myBeaconRequests\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"slotNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_randomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"name\":\"s_requestsIDs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_subId\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"}],\"name\":\"setFail\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"height\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"delay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"}],\"name\":\"storeBeaconRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"}],\"name\":\"testRedeemRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelayArg\",\"type\":\"uint24\"}],\"name\":\"testRequestRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"testRequestRandomnessFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b50604051620018db380380620018db8339810160408190526200003491620001aa565b8233806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620000ff565b5050600280546001600160a01b0319166001600160a01b03939093169290921790915550600b805460ff191692151592909217909155600c555062000201565b336001600160a01b03821603620001595760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080600060608486031215620001c057600080fd5b83516001600160a01b0381168114620001d857600080fd5b60208501519093508015158114620001ef57600080fd5b80925050604084015190509250925092565b6116ca80620002116000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c8063a9cc4718116100cd578063ea7502ab11610081578063f2fde38b11610066578063f2fde38b1461031f578063f6eaffc814610332578063ffe97ca41461034557600080fd5b8063ea7502ab14610303578063f08c5daa1461031657600080fd5b8063cd0593df116100b2578063cd0593df146102d4578063d0705f04146102dd578063d21ea8fd146102f057600080fd5b8063a9cc4718146102a4578063c6d61301146102c157600080fd5b80637716cdaa116101245780638da5cb5b116101095780638da5cb5b1461022a5780638ea98117146102525780639d7694021461026557600080fd5b80637716cdaa1461020d57806379ba50971461022257600080fd5b8063689b77ab11610155578063689b77ab146101c45780636df57cc3146101cd578063706da1ca146101e057600080fd5b8063341867a2146101715780635f15cccc14610186575b600080fd5b61018461017f366004610e87565b6103f8565b005b6101b1610194366004610ec1565b600460209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101b160085481565b6101846101db366004610eff565b6104ed565b6009546101f49067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101bb565b610215610628565b6040516101bb9190610fa9565b6101846106b6565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bb565b610184610260366004610fc3565b6107b8565b610184610273366004610ff9565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600b546102b19060ff1681565b60405190151581526020016101bb565b6101b16102cf36600461101b565b61089e565b6101b1600c5481565b6101b16102eb366004610e87565b6109a8565b6101846102fe366004611187565b6109d9565b6101b1610311366004611250565b610a3a565b6101b1600a5481565b61018461032d366004610fc3565b610b4a565b6101b16103403660046112d4565b610b5e565b6103ae6103533660046112d4565b60056020526000908152604090205463ffffffff811690640100000000810462ffffff1690670100000000000000810461ffff16906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1684565b6040805163ffffffff909516855262ffffff909316602085015261ffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff1660608201526080016101bb565b60025460408051602081018252600080825291517facfc6cdd000000000000000000000000000000000000000000000000000000008152919273ffffffffffffffffffffffffffffffffffffffff169163acfc6cdd9161045e91879187916004016112ed565b6000604051808303816000875af115801561047d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104c39190810190611315565b600083815260066020908152604090912082519293506104e7929091840190610e27565b50505050565b600083815260046020908152604080832062ffffff861684529091528120859055600c5461051b9085611404565b6040805160808101825263ffffffff928316815262ffffff958616602080830191825261ffff968716838501908152306060850190815260009b8c526005909252939099209151825491519351995173ffffffffffffffffffffffffffffffffffffffff166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff9a90971667010000000000000002999099167fffffff00000000000000000000000000000000000000000000ffffffffffffff93909716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091169890931697909717919091171692909217179092555050565b6007805461063590611418565b80601f016020809104026020016040519081016040528092919081815260200182805461066190611418565b80156106ae5780601f10610683576101008083540402835291602001916106ae565b820191906000526020600020905b81548152906001019060200180831161069157829003601f168201915b505050505081565b60015473ffffffffffffffffffffffffffffffffffffffff16331461073c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906107f8575060025473ffffffffffffffffffffffffffffffffffffffff163314155b1561082f576040517fd4e06fd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc90600090a250565b600080600c546108ac610b7f565b6108b6919061146b565b9050600081600c546108c6610b7f565b6108d0919061147f565b6108da9190611498565b60025460408051602081018252600080825291517f4ffac83a000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff90921691634ffac83a91610948918a918c918b91906004016114ab565b6020604051808303816000875af1158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b91906114e3565b90506109998183878a6104ed565b60088190559695505050505050565b600660205281600052604060002081815481106109c457600080fd5b90600052602060002001600091509150505481565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a2a576040517f66bf9c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a35838383610c16565b505050565b600080600c54610a48610b7f565b610a52919061146b565b9050600081600c54610a62610b7f565b610a6c919061147f565b610a769190611498565b60025460408051602081018252600080825291517fdb972c8b000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff9092169163db972c8b91610ae8918d918d918d918d918d91906004016114fc565b6020604051808303816000875af1158015610b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2b91906114e3565b9050610b398183898b6104ed565b600881905598975050505050505050565b610b52610caf565b610b5b81610d32565b50565b60038181548110610b6e57600080fd5b600091825260209091200154905081565b60004661a4b1811480610b94575062066eed81145b15610c0f57606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610be5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0991906114e3565b91505090565b4391505090565b600b5460ff1615610c83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f206661696c656420696e2066756c66696c6c52616e646f6d576f7264730000006044820152606401610733565b60008381526006602090815260409091208351610ca292850190610e27565b5060076104e782826115a3565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610733565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610733565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610e62579160200282015b82811115610e62578251825591602001919060010190610e47565b50610e6e929150610e72565b5090565b5b80821115610e6e5760008155600101610e73565b60008060408385031215610e9a57600080fd5b50508035926020909101359150565b803562ffffff81168114610ebc57600080fd5b919050565b60008060408385031215610ed457600080fd5b82359150610ee460208401610ea9565b90509250929050565b803561ffff81168114610ebc57600080fd5b60008060008060808587031215610f1557600080fd5b8435935060208501359250610f2c60408601610ea9565b9150610f3a60608601610eed565b905092959194509250565b6000815180845260005b81811015610f6b57602081850181015186830182015201610f4f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610fbc6020830184610f45565b9392505050565b600060208284031215610fd557600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fbc57600080fd5b60006020828403121561100b57600080fd5b81358015158114610fbc57600080fd5b60008060006060848603121561103057600080fd5b61103984610eed565b92506020840135915061104e60408501610ea9565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110cd576110cd611057565b604052919050565b600067ffffffffffffffff8211156110ef576110ef611057565b5060051b60200190565b600082601f83011261110a57600080fd5b813567ffffffffffffffff81111561112457611124611057565b61115560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611086565b81815284602083860101111561116a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561119c57600080fd5b8335925060208085013567ffffffffffffffff808211156111bc57600080fd5b818701915087601f8301126111d057600080fd5b81356111e36111de826110d5565b611086565b81815260059190911b8301840190848101908a83111561120257600080fd5b938501935b8285101561122057843582529385019390850190611207565b96505050604087013592508083111561123857600080fd5b5050611246868287016110f9565b9150509250925092565b600080600080600060a0868803121561126857600080fd5b8535945061127860208701610eed565b935061128660408701610ea9565b9250606086013563ffffffff8116811461129f57600080fd5b9150608086013567ffffffffffffffff8111156112bb57600080fd5b6112c7888289016110f9565b9150509295509295909350565b6000602082840312156112e657600080fd5b5035919050565b83815282602082015260606040820152600061130c6060830184610f45565b95945050505050565b6000602080838503121561132857600080fd5b825167ffffffffffffffff81111561133f57600080fd5b8301601f8101851361135057600080fd5b805161135e6111de826110d5565b81815260059190911b8201830190838101908783111561137d57600080fd5b928401925b8284101561139b57835182529284019290840190611382565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082611413576114136113a6565b500490565b600181811c9082168061142c57607f821691505b602082108103611465577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008261147a5761147a6113a6565b500690565b80820180821115611492576114926113d5565b92915050565b81810381811115611492576114926113d5565b84815261ffff8416602082015262ffffff831660408201526080606082015260006114d96080830184610f45565b9695505050505050565b6000602082840312156114f557600080fd5b5051919050565b86815261ffff8616602082015262ffffff8516604082015263ffffffff8416606082015260c06080820152600061153660c0830185610f45565b82810360a08401526115488185610f45565b9998505050505050505050565b601f821115610a3557600081815260208120601f850160051c8101602086101561157c5750805b601f850160051c820191505b8181101561159b57828155600101611588565b505050505050565b815167ffffffffffffffff8111156115bd576115bd611057565b6115d1816115cb8454611418565b84611555565b602080601f83116001811461162457600084156115ee5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561159b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561167157888601518255948401946001909101908401611652565b50858210156116ad57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000813000a", +} + +var BeaconVRFConsumerABI = BeaconVRFConsumerMetaData.ABI + +var BeaconVRFConsumerBin = BeaconVRFConsumerMetaData.Bin + +func DeployBeaconVRFConsumer(auth *bind.TransactOpts, backend bind.ContractBackend, coordinator common.Address, shouldFail bool, beaconPeriodBlocks *big.Int) (common.Address, *types.Transaction, *BeaconVRFConsumer, error) { + parsed, err := BeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BeaconVRFConsumerBin), backend, coordinator, shouldFail, beaconPeriodBlocks) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &BeaconVRFConsumer{BeaconVRFConsumerCaller: BeaconVRFConsumerCaller{contract: contract}, BeaconVRFConsumerTransactor: BeaconVRFConsumerTransactor{contract: contract}, BeaconVRFConsumerFilterer: BeaconVRFConsumerFilterer{contract: contract}}, nil +} + +type BeaconVRFConsumer struct { + address common.Address + abi abi.ABI + BeaconVRFConsumerCaller + BeaconVRFConsumerTransactor + BeaconVRFConsumerFilterer +} + +type BeaconVRFConsumerCaller struct { + contract *bind.BoundContract +} + +type BeaconVRFConsumerTransactor struct { + contract *bind.BoundContract +} + +type BeaconVRFConsumerFilterer struct { + contract *bind.BoundContract +} + +type BeaconVRFConsumerSession struct { + Contract *BeaconVRFConsumer + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type BeaconVRFConsumerCallerSession struct { + Contract *BeaconVRFConsumerCaller + CallOpts bind.CallOpts +} + +type BeaconVRFConsumerTransactorSession struct { + Contract *BeaconVRFConsumerTransactor + TransactOpts bind.TransactOpts +} + +type BeaconVRFConsumerRaw struct { + Contract *BeaconVRFConsumer +} + +type BeaconVRFConsumerCallerRaw struct { + Contract *BeaconVRFConsumerCaller +} + +type BeaconVRFConsumerTransactorRaw struct { + Contract *BeaconVRFConsumerTransactor +} + +func NewBeaconVRFConsumer(address common.Address, backend bind.ContractBackend) (*BeaconVRFConsumer, error) { + abi, err := abi.JSON(strings.NewReader(BeaconVRFConsumerABI)) + if err != nil { + return nil, err + } + contract, err := bindBeaconVRFConsumer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &BeaconVRFConsumer{address: address, abi: abi, BeaconVRFConsumerCaller: BeaconVRFConsumerCaller{contract: contract}, BeaconVRFConsumerTransactor: BeaconVRFConsumerTransactor{contract: contract}, BeaconVRFConsumerFilterer: BeaconVRFConsumerFilterer{contract: contract}}, nil +} + +func NewBeaconVRFConsumerCaller(address common.Address, caller bind.ContractCaller) (*BeaconVRFConsumerCaller, error) { + contract, err := bindBeaconVRFConsumer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerCaller{contract: contract}, nil +} + +func NewBeaconVRFConsumerTransactor(address common.Address, transactor bind.ContractTransactor) (*BeaconVRFConsumerTransactor, error) { + contract, err := bindBeaconVRFConsumer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerTransactor{contract: contract}, nil +} + +func NewBeaconVRFConsumerFilterer(address common.Address, filterer bind.ContractFilterer) (*BeaconVRFConsumerFilterer, error) { + contract, err := bindBeaconVRFConsumer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerFilterer{contract: contract}, nil +} + +func bindBeaconVRFConsumer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := BeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BeaconVRFConsumer.Contract.BeaconVRFConsumerCaller.contract.Call(opts, result, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.BeaconVRFConsumerTransactor.contract.Transfer(opts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.BeaconVRFConsumerTransactor.contract.Transact(opts, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BeaconVRFConsumer.Contract.contract.Call(opts, result, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.contract.Transfer(opts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.contract.Transact(opts, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) Fail(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "fail") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) Fail() (bool, error) { + return _BeaconVRFConsumer.Contract.Fail(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) Fail() (bool, error) { + return _BeaconVRFConsumer.Contract.Fail(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "i_beaconPeriodBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) Owner() (common.Address, error) { + return _BeaconVRFConsumer.Contract.Owner(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) Owner() (common.Address, error) { + return _BeaconVRFConsumer.Contract.Owner(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_ReceivedRandomnessByRequestID", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SArguments(opts *bind.CallOpts) ([]byte, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_arguments") + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SArguments() ([]byte, error) { + return _BeaconVRFConsumer.Contract.SArguments(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SArguments() ([]byte, error) { + return _BeaconVRFConsumer.Contract.SArguments(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SGasAvailable(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_gasAvailable") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SGasAvailable() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SGasAvailable(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SGasAvailable() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SGasAvailable(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_mostRecentRequestID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SMostRecentRequestID() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SMostRecentRequestID(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SMostRecentRequestID() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SMostRecentRequestID(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_myBeaconRequests", arg0) + + outstruct := new(SMyBeaconRequests) + if err != nil { + return *outstruct, err + } + + outstruct.SlotNumber = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.ConfirmationDelay = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.NumWords = *abi.ConvertType(out[2], new(uint16)).(*uint16) + outstruct.Requester = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _BeaconVRFConsumer.Contract.SMyBeaconRequests(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _BeaconVRFConsumer.Contract.SMyBeaconRequests(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_randomWords", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRandomWords(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRandomWords(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_requestsIDs", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRequestsIDs(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRequestsIDs(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SSubId(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_subId") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SSubId() (uint64, error) { + return _BeaconVRFConsumer.Contract.SSubId(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SSubId() (uint64, error) { + return _BeaconVRFConsumer.Contract.SSubId(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "acceptOwnership") +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) AcceptOwnership() (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.AcceptOwnership(&_BeaconVRFConsumer.TransactOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.AcceptOwnership(&_BeaconVRFConsumer.TransactOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "rawFulfillRandomWords", requestID, randomWords, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.RawFulfillRandomWords(&_BeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.RawFulfillRandomWords(&_BeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "setCoordinator", coordinator) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetCoordinator(&_BeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetCoordinator(&_BeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "setFail", shouldFail) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetFail(&_BeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetFail(&_BeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "storeBeaconRequest", reqId, height, delay, numWords) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.StoreBeaconRequest(&_BeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.StoreBeaconRequest(&_BeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "testRedeemRandomness", subID, requestID) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRedeemRandomness(&_BeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRedeemRandomness(&_BeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "testRequestRandomness", numWords, subID, confirmationDelayArg) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomness(&_BeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomness(&_BeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "testRequestRandomnessFulfillment", subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_BeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_BeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "transferOwnership", to) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TransferOwnership(&_BeaconVRFConsumer.TransactOpts, to) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TransferOwnership(&_BeaconVRFConsumer.TransactOpts, to) +} + +type BeaconVRFConsumerCoordinatorUpdatedIterator struct { + Event *BeaconVRFConsumerCoordinatorUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BeaconVRFConsumerCoordinatorUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BeaconVRFConsumerCoordinatorUpdatedIterator) Error() error { + return it.fail +} + +func (it *BeaconVRFConsumerCoordinatorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BeaconVRFConsumerCoordinatorUpdated struct { + Coordinator common.Address + Raw types.Log +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*BeaconVRFConsumerCoordinatorUpdatedIterator, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.FilterLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerCoordinatorUpdatedIterator{contract: _BeaconVRFConsumer.contract, event: "CoordinatorUpdated", logs: logs, sub: sub}, nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.WatchLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BeaconVRFConsumerCoordinatorUpdated) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) ParseCoordinatorUpdated(log types.Log) (*BeaconVRFConsumerCoordinatorUpdated, error) { + event := new(BeaconVRFConsumerCoordinatorUpdated) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BeaconVRFConsumerOwnershipTransferRequestedIterator struct { + Event *BeaconVRFConsumerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BeaconVRFConsumerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BeaconVRFConsumerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *BeaconVRFConsumerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BeaconVRFConsumerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerOwnershipTransferRequestedIterator{contract: _BeaconVRFConsumer.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BeaconVRFConsumerOwnershipTransferRequested) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) ParseOwnershipTransferRequested(log types.Log) (*BeaconVRFConsumerOwnershipTransferRequested, error) { + event := new(BeaconVRFConsumerOwnershipTransferRequested) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BeaconVRFConsumerOwnershipTransferredIterator struct { + Event *BeaconVRFConsumerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BeaconVRFConsumerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BeaconVRFConsumerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *BeaconVRFConsumerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BeaconVRFConsumerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerOwnershipTransferredIterator{contract: _BeaconVRFConsumer.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BeaconVRFConsumerOwnershipTransferred) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) ParseOwnershipTransferred(log types.Log) (*BeaconVRFConsumerOwnershipTransferred, error) { + event := new(BeaconVRFConsumerOwnershipTransferred) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type SMyBeaconRequests struct { + SlotNumber uint32 + ConfirmationDelay *big.Int + NumWords uint16 + Requester common.Address +} + +func (_BeaconVRFConsumer *BeaconVRFConsumer) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _BeaconVRFConsumer.abi.Events["CoordinatorUpdated"].ID: + return _BeaconVRFConsumer.ParseCoordinatorUpdated(log) + case _BeaconVRFConsumer.abi.Events["OwnershipTransferRequested"].ID: + return _BeaconVRFConsumer.ParseOwnershipTransferRequested(log) + case _BeaconVRFConsumer.abi.Events["OwnershipTransferred"].ID: + return _BeaconVRFConsumer.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (BeaconVRFConsumerCoordinatorUpdated) Topic() common.Hash { + return common.HexToHash("0xc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc") +} + +func (BeaconVRFConsumerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (BeaconVRFConsumerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_BeaconVRFConsumer *BeaconVRFConsumer) Address() common.Address { + return _BeaconVRFConsumer.address +} + +type BeaconVRFConsumerInterface interface { + Fail(opts *bind.CallOpts) (bool, error) + + IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SArguments(opts *bind.CallOpts) ([]byte, error) + + SGasAvailable(opts *bind.CallOpts) (*big.Int, error) + + SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) + + SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) + + SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) + + SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SSubId(opts *bind.CallOpts) (uint64, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) + + SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) + + SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) + + StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) + + TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) + + TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) + + TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*BeaconVRFConsumerCoordinatorUpdatedIterator, error) + + WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) + + ParseCoordinatorUpdated(log types.Log) (*BeaconVRFConsumerCoordinatorUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*BeaconVRFConsumerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*BeaconVRFConsumerOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/vrf_coordinator/vrf_coordinator.go b/core/gethwrappers/ocr2vrf/generated/vrf_coordinator/vrf_coordinator.go new file mode 100644 index 00000000000..f20d5494452 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/vrf_coordinator/vrf_coordinator.go @@ -0,0 +1,3870 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vrf_coordinator + +import ( + "errors" + "fmt" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type ECCArithmeticG1Point struct { + P [2]*big.Int +} + +type VRFBeaconTypesCallback struct { + RequestID *big.Int + NumWords uint16 + Requester common.Address + Arguments []byte + GasAllowance *big.Int + SubID *big.Int + GasPrice *big.Int + WeiPerUnitLink *big.Int +} + +type VRFBeaconTypesCoordinatorConfig struct { + UseReasonableGasPrice bool + ReentrancyLock bool + Paused bool + PremiumPercentage uint8 + UnusedGasPenaltyPercent uint8 + StalenessSeconds uint32 + RedeemableRequestGasOverhead uint32 + CallbackRequestGasOverhead uint32 + ReasonableGasPriceStalenessBlocks uint32 + FallbackWeiPerUnitLink *big.Int +} + +type VRFBeaconTypesCostedCallback struct { + Callback VRFBeaconTypesCallback + Price *big.Int +} + +type VRFBeaconTypesOutputServed struct { + Height uint64 + ConfirmationDelay *big.Int + ProofG1X *big.Int + ProofG1Y *big.Int +} + +type VRFBeaconTypesVRFOutput struct { + BlockHeight uint64 + ConfirmationDelay *big.Int + VrfOutput ECCArithmeticG1Point + Callbacks []VRFBeaconTypesCostedCallback + ShouldStore bool +} + +type VRFCoordinatorCallbackConfig struct { + MaxCallbackGasLimit uint32 + MaxCallbackArgumentsLength uint32 +} + +var VRFCoordinatorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"beaconPeriodBlocksArg\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BeaconPeriodMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestHeight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"earliestAllowed\",\"type\":\"uint256\"}],\"name\":\"BlockTooRecent\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16[10]\",\"name\":\"confirmationDelays\",\"type\":\"uint16[10]\"},{\"internalType\":\"uint8\",\"name\":\"violatingIndex\",\"type\":\"uint8\"}],\"name\":\"ConfirmationDelaysNotIncreasing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractPaused\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorNotRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLeft\",\"type\":\"uint256\"}],\"name\":\"GasAllowanceExceedsGasLeft\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"separatorHeight\",\"type\":\"uint64\"}],\"name\":\"HistoryDomainSeparatorTooOld\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actualBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredBalance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"expectedLength\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCoordinatorConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidJuelsConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numRecipients\",\"type\":\"uint256\"}],\"name\":\"InvalidNumberOfRecipients\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestedSubID\",\"type\":\"uint256\"}],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"requestedVersion\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"coordinatorVersion\",\"type\":\"uint8\"}],\"name\":\"MigrationVersionMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProducer\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedOwner\",\"type\":\"address\"}],\"name\":\"MustBeRequestedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativePaymentGiven\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoWordsRequested\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16[10]\",\"name\":\"confDelays\",\"type\":\"uint16[10]\"}],\"name\":\"NonZeroDelayAfterZeroDelay\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnMigrationNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"producer\",\"type\":\"address\"}],\"name\":\"ProducerAlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestHeight\",\"type\":\"uint256\"}],\"name\":\"RandomnessNotAvailable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestHeight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"confDelay\",\"type\":\"uint256\"}],\"name\":\"RandomnessSeedNotFoundForCallbacks\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numRecipients\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numPayments\",\"type\":\"uint256\"}],\"name\":\"RecipientsPaymentsMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"expected\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"actual\",\"type\":\"address\"}],\"name\":\"ResponseMustBeRetrievedByRequester\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyRequestsReplaceContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySlotsReplaceContract\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyWords\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockHeight\",\"type\":\"uint256\"}],\"name\":\"UniverseHasEndedBangBangBang\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxCallbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCallbackArgumentsLength\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structVRFCoordinator.CallbackConfig\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"CallbackConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"useReasonableGasPrice\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"unusedGasPenaltyPercent\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"redeemableRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"callbackRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reasonableGasPriceStalenessBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structVRFBeaconTypes.CoordinatorConfig\",\"name\":\"coordinatorConfig\",\"type\":\"tuple\"}],\"name\":\"CoordinatorConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"newVersion\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"recentBlockHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"height\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint256\",\"name\":\"proofG1X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofG1Y\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structVRFBeaconTypes.OutputServed[]\",\"name\":\"outputsServed\",\"type\":\"tuple[]\"}],\"name\":\"OutputsServed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"PauseFlagChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"requestIDs\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"successfulFulfillment\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"truncatedErrorData\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint96[]\",\"name\":\"subBalances\",\"type\":\"uint96[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"subIDs\",\"type\":\"uint256[]\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAllowance\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessFulfillmentRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"}],\"name\":\"RandomnessRedeemed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SubscriptionCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"SubscriptionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NUM_CONF_DELAYS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"acceptSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"addConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"paymentsInJuels\",\"type\":\"uint256[]\"}],\"name\":\"batchTransferLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"cancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createSubscription\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"deregisterMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"getCallbackMemo\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfirmationDelays\",\"outputs\":[{\"internalType\":\"uint24[8]\",\"name\":\"\",\"type\":\"uint24[8]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getFulfillmentFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"pendingFulfillments\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSubscriptionLinkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_beaconPeriodBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_link\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIVRFMigration\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"encodedRequest\",\"type\":\"bytes\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrationVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onMigration\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"p\",\"type\":\"uint256[2]\"}],\"internalType\":\"structECCArithmetic.G1Point\",\"name\":\"vrfOutput\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"gasAllowance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"}],\"internalType\":\"structVRFBeaconTypes.Callback\",\"name\":\"callback\",\"type\":\"tuple\"},{\"internalType\":\"uint96\",\"name\":\"price\",\"type\":\"uint96\"}],\"internalType\":\"structVRFBeaconTypes.CostedCallback[]\",\"name\":\"callbacks\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"shouldStore\",\"type\":\"bool\"}],\"internalType\":\"structVRFBeaconTypes.VRFOutput[]\",\"name\":\"vrfOutputs\",\"type\":\"tuple[]\"},{\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"}],\"name\":\"processVRFOutputs\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"containsNewOutputs\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"redeemRandomness\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"randomness\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"removeConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"requestRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"requestRandomnessFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"requestSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_callbackConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"maxCallbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCallbackArgumentsLength\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_coordinatorConfig\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"useReasonableGasPrice\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"unusedGasPenaltyPercent\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"redeemableRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"callbackRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reasonableGasPriceStalenessBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_pendingRequests\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"slotNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_producer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxCallbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCallbackArgumentsLength\",\"type\":\"uint32\"}],\"internalType\":\"structVRFCoordinator.CallbackConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"setCallbackConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint24[8]\",\"name\":\"confDelays\",\"type\":\"uint24[8]\"}],\"name\":\"setConfirmationDelays\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"useReasonableGasPrice\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"unusedGasPenaltyPercent\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"redeemableRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"callbackRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reasonableGasPriceStalenessBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"uint96\"}],\"internalType\":\"structVRFBeaconTypes.CoordinatorConfig\",\"name\":\"coordinatorConfig\",\"type\":\"tuple\"}],\"name\":\"setCoordinatorConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"setPauseFlag\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"producer\",\"type\":\"address\"}],\"name\":\"setProducer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"juelsAmount\",\"type\":\"uint256\"}],\"name\":\"transferLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60c06040523480156200001157600080fd5b50604051620062f5380380620062f5833981016040819052620000349162000239565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200018e565b5050506001600160a01b03166080908152604080519182018152600080835260208301819052908201819052662386f26fc10000606090920191909152642386f26fc160b01b6006556004805463ffffffff60281b191668ffffffff00000000001790558290036200014457604051632abc297960e01b815260040160405180910390fd5b60a0829052600e805465ffffffffffff16906000620001638362000278565b91906101000a81548165ffffffffffff021916908365ffffffffffff160217905550505050620002ac565b336001600160a01b03821603620001e85760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080604083850312156200024d57600080fd5b825160208401519092506001600160a01b03811681146200026d57600080fd5b809150509250929050565b600065ffffffffffff808316818103620002a257634e487b7160e01b600052601160045260246000fd5b6001019392505050565b60805160a051615fdd620003186000396000818161075f01528181611ca301528181613cb301528181613ce201528181613d1a015261430e01526000818161047501528181610bb501528181611a410152818161237b01528181612d610152612df60152615fdd6000f3fe6080604052600436106101d65760003560e01c806304104edb146101db5780630ae09540146101fd57806316f6ee9a1461021d578063294daa491461025d5780632b38bafc1461027f5780632f7527cc1461029f5780633e79167f146102b457806340d6bb82146102d457806347c3e2cb146102ea5780634ffac83a14610385578063597d2f3c146103985780635d06b4ab146103b657806364d51a2a146103d657806373433a2f146103fe57806376f2e3f41461041e57806379ba50971461044e5780637d253aff1461046357806385c64e11146104a45780638c7cba66146104c65780638da5cb5b146104e65780638da92e71146105045780638eef585f146105245780639e20103614610544578063a21a23e414610564578063a4c0ed3614610579578063acfc6cdd14610599578063b2a7cac5146105c6578063b79fa6f7146105e6578063bd58017f146106cd578063bec4c08c146106ed578063c3fbb6fd1461070d578063cb6317971461072d578063cd0593df1461074d578063ce3f471914610781578063dac83d29146107a1578063db972c8b146107c1578063dc311dd3146107d4578063e30afa4a14610804578063f2fde38b14610849578063f99b1d6814610869578063f9c45ced14610889575b600080fd5b3480156101e757600080fd5b506101fb6101f6366004614abd565b6108a9565b005b34801561020957600080fd5b506101fb610218366004614ae1565b610a5e565b34801561022957600080fd5b5061024a610238366004614b11565b6000908152600c602052604090205490565b6040519081526020015b60405180910390f35b34801561026957600080fd5b5060015b60405160ff9091168152602001610254565b34801561028b57600080fd5b506101fb61029a366004614abd565b610cc0565b3480156102ab57600080fd5b5061026d600881565b3480156102c057600080fd5b506101fb6102cf366004614b2a565b610d21565b3480156102e057600080fd5b5061024a6103e881565b3480156102f657600080fd5b50610348610305366004614b11565b60106020526000908152604090205463ffffffff811690600160201b810462ffffff1690600160381b810461ffff1690600160481b90046001600160a01b031684565b6040805163ffffffff909516855262ffffff909316602085015261ffff909116918301919091526001600160a01b03166060820152608001610254565b61024a610393366004614cac565b610dd2565b3480156103a457600080fd5b506002546001600160601b031661024a565b3480156103c257600080fd5b506101fb6103d1366004614abd565b610f7e565b3480156103e257600080fd5b506103eb606481565b60405161ffff9091168152602001610254565b34801561040a57600080fd5b506101fb610419366004614d57565b61102a565b34801561042a57600080fd5b5061043e610439366004614dd9565b611115565b6040519015158152602001610254565b34801561045a57600080fd5b506101fb611453565b34801561046f57600080fd5b506104977f000000000000000000000000000000000000000000000000000000000000000081565b6040516102549190614e5b565b3480156104b057600080fd5b506104b96114fd565b6040516102549190614e6f565b3480156104d257600080fd5b506101fb6104e1366004614ec3565b611562565b3480156104f257600080fd5b506000546001600160a01b0316610497565b34801561051057600080fd5b506101fb61051f366004614f1d565b6115d6565b34801561053057600080fd5b506101fb61053f366004614f3a565b611640565b34801561055057600080fd5b5061024a61055f366004614f65565b61167c565b34801561057057600080fd5b5061024a61179d565b34801561058557600080fd5b506101fb610594366004615019565b6119e3565b3480156105a557600080fd5b506105b96105b4366004615068565b611bce565b60405161025491906150f2565b3480156105d257600080fd5b506101fb6105e1366004614b11565b611dd2565b3480156105f257600080fd5b506004546005546106629160ff80821692610100830482169262010000810483169263010000008204811692600160201b83049091169163ffffffff600160281b8204811692600160481b8304821692600160681b8104831692600160881b90910416906001600160601b03168a565b604080519a15158b5298151560208b01529615159789019790975260ff948516606089015292909316608087015263ffffffff90811660a087015291821660c0860152811660e08501529091166101008301526001600160601b031661012082015261014001610254565b3480156106d957600080fd5b50600a54610497906001600160a01b031681565b3480156106f957600080fd5b506101fb610708366004614ae1565b611f03565b34801561071957600080fd5b506101fb610728366004615105565b6120bf565b34801561073957600080fd5b506101fb610748366004614ae1565b6125ac565b34801561075957600080fd5b5061024a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561078d57600080fd5b506101fb61079c366004615159565b612899565b3480156107ad57600080fd5b506101fb6107bc366004614ae1565b6128b2565b61024a6107cf36600461519a565b6129c3565b3480156107e057600080fd5b506107f46107ef366004614b11565b612c21565b6040516102549493929190615272565b34801561081057600080fd5b50600b5461082c9063ffffffff80821691600160201b90041682565b6040805163ffffffff938416815292909116602083015201610254565b34801561085557600080fd5b506101fb610864366004614abd565b612d0e565b34801561087557600080fd5b506101fb6108843660046152be565b612d1f565b34801561089557600080fd5b5061024a6108a43660046152ea565b612e88565b6108b1612f9f565b60095460005b81811015610a3657826001600160a01b0316600982815481106108dc576108dc615330565b6000918252602090912001546001600160a01b031603610a2457600961090360018461535c565b8154811061091357610913615330565b600091825260209091200154600980546001600160a01b03909216918390811061093f5761093f615330565b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905582600961097660018561535c565b8154811061098657610986615330565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060098054806109c5576109c561536f565b600082815260209020810160001990810180546001600160a01b03191690550190556040517ff80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af3790610a17908590614e5b565b60405180910390a1505050565b80610a2e81615385565b9150506108b7565b5081604051635428d44960e01b8152600401610a529190614e5b565b60405180910390fd5b50565b60008281526007602052604090205482906001600160a01b031680610a995760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b03821614610ac45780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff1615610aed5760405163769dd35360e11b815260040160405180910390fd5b600084815260086020526040902054600160601b90046001600160401b031615610b2a57604051631685ecdd60e31b815260040160405180910390fd5b6000848152600860209081526040918290208251808401909352546001600160601b038116808452600160601b9091046001600160401b031691830191909152610b7386612ff4565b600280546001600160601b03169082906000610b8f838561539e565b92506101000a8154816001600160601b0302191690836001600160601b031602179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb87846001600160601b03166040518363ffffffff1660e01b8152600401610c0a9291906153c5565b6020604051808303816000875af1158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d91906153de565b610c7d5760405163cf47918160e01b81526001600160601b03808316600483015283166024820152604401610a52565b867f3784f77e8e883de95b5d47cd713ced01229fa74d118c0a462224bcb0516d43f18784604051610caf9291906153fb565b60405180910390a250505050505050565b610cc8612f9f565b600a546001600160a01b031615610cff57600a5460405163ea6d390560e01b8152610a52916001600160a01b031690600401614e5b565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b610d29612f9f565b6064610d3b60a0830160808401615437565b60ff161180610d555750610d556040820160208301614f1d565b80610d6b5750610d6b6060820160408301614f1d565b15610d895760405163b0e7bd8360e01b815260040160405180910390fd5b806004610d96828261549d565b9050507e28d3a46e95e67def989d41c66eb331add9809460b95b5fb4eb006157728fc581604051610dc79190615670565b60405180910390a150565b60045460009062010000900460ff1615610dff5760405163ab35696f60e01b815260040160405180910390fd5b600454610100900460ff1615610e285760405163769dd35360e11b815260040160405180910390fd5b3415610e4957604051630b829bad60e21b8152346004820152602401610a52565b6000806000610e5a88338989613143565b925092509250600080610e6d338b61328e565b600087815260106020908152604091829020885181548a8401518b8601516060808e015163ffffffff90951666ffffffffffffff1990941693909317600160201b62ffffff9384160217600160381b600160e81b031916600160381b61ffff92831602600160481b600160e81b03191617600160481b6001600160a01b03909516949094029390931790935584513381526001600160401b038b1694810194909452918e169383019390935281018e9052908c16608082015260a081018390526001600160601b03821660c0820152919350915085907fb7933fba96b6b452eb44f99fdc08052a45dff82363d59abaff0456931c3d24599060e00160405180910390a2509298975050505050505050565b610f86612f9f565b610f8f8161346a565b15610faf578060405163ac8a27ef60e01b8152600401610a529190614e5b565b600980546001810182556000919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af0162590610dc7908390614e5b565b600a546001600160a01b0316331461105557604051634bea32db60e11b815260040160405180910390fd5b828015806110635750601f81115b1561108457604051634ecc4fef60e01b815260048101829052602401610a52565b8082146110a85760405163339f8a9d60e01b8152610a529082908490600401615758565b60005b8181101561110d576110fb8686838181106110c8576110c8615330565b90506020020160208101906110dd9190614abd565b8585848181106110ef576110ef615330565b90506020020135612d1f565b8061110581615385565b9150506110ab565b505050505050565b600a546000906001600160a01b0316331461114357604051634bea32db60e11b815260040160405180910390fd5b60045462010000900460ff161561116d5760405163ab35696f60e01b815260040160405180910390fd5b6001600160c01b038416156111aa57600680546001600160601b038616600160a01b02600160201b600160a01b0390911663ffffffff4216171790555b6001600160401b038316156111ff5760068054436001600160401b03908116600160201b02600160201b600160601b0319918716600160601b0291909116600160201b600160a01b0319909216919091171790555b600080866001600160401b0381111561121a5761121a614b68565b60405190808252806020026020018201604052801561125357816020015b6112406148f6565b8152602001906001900390816112385790505b50905060005b8781101561135557600089898381811061127557611275615330565b90506020028101906112879190615766565b611290906158ea565b9050600061129f82888b6134d3565b905085806112aa5750805b604083015151519096501515806112c957506040820151516020015115155b15611340576040805160808101825283516001600160401b0316815260208085015162ffffff168183015284830180515151938301939093529151519091015160608201528451859061ffff881690811061132657611326615330565b6020026020010181905250848061133c906159d0565b9550505b5050808061134d90615385565b915050611259565b5060008261ffff166001600160401b0381111561137457611374614b68565b6040519080825280602002602001820160405280156113ad57816020015b61139a6148f6565b8152602001906001900390816113925790505b50905060005b8361ffff16811015611409578281815181106113d1576113d1615330565b60200260200101518282815181106113eb576113eb615330565b6020026020010181905250808061140190615385565b9150506113b3565b507ff10ea936d00579b4c52035ee33bf46929646b3aa87554c565d8fb2c7aa549c448588888460405161143f94939291906159f1565b60405180910390a150505095945050505050565b6001546001600160a01b031633146114a65760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610a52565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61150561492c565b6040805161010081019182905290600f90600890826000855b82829054906101000a900462ffffff1662ffffff168152602001906003019060208260020104928301926001038202915080841161151e5790505050505050905090565b61156a612f9f565b8051600b80546020808501805163ffffffff908116600160201b026001600160401b031990941695811695861793909317909355604080519485529251909116908301527f0cc54509a45ab33cd67614d4a2892c083ecf8fb43b9d29f6ea8130b9023e51df9101610dc7565b6115de612f9f565b60045460ff6201000090910416151581151514610a5b5760048054821515620100000262ff0000199091161790556040517f49ba7c1de2d8853088b6270e43df2118516b217f38b917dd2b80dea360860fbe90610dc790831515815260200190565b600a546001600160a01b0316331461166b57604051634bea32db60e11b815260040160405180910390fd5b611678600f82600861494b565b5050565b604080516101408101825260045460ff80821615158352610100808304821615156020808601919091526201000084048316151585870152630100000084048316606080870191909152600160201b808604909416608080880191909152600160281b860463ffffffff90811660a0890152600160481b8704811660c0890152600160681b8704811660e0890152600160881b9096048616938701939093526005546001600160601b039081166101208801528751938401885260065480871685526001600160401b03958104861693850193909352600160601b830490941696830196909652600160a01b90049091169381019390935260009283926117889288169187919061366b565b50506001600160601b03169695505050505050565b600454600090610100900460ff16156117c95760405163769dd35360e11b815260040160405180910390fd5b60045462010000900460ff16156117f35760405163ab35696f60e01b815260040160405180910390fd5b60003361180160014361535c565b6001546040516001600160601b0319606094851b81166020830152924060348201523090931b90911660548301526001600160c01b0319600160a01b90910460c01b16606882015260700160408051808303601f19018152919052805160209091012060018054919250600160a01b9091046001600160401b031690601461188883615a86565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550506000806001600160401b038111156118c7576118c7614b68565b6040519080825280602002602001820160405280156118f0578160200160208202803683370190505b5060408051808201825260008082526020808301828152878352600882528483209351845491516001600160601b039091166001600160a01b031992831617600160601b6001600160401b039092169190910217909355835160608101855233815280820183815281860187815289855260078452959093208151815486166001600160a01b03918216178255935160018201805490961694169390931790935592518051949550919390926119ad9260028501929101906149e9565b505060405133915083907f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d90600090a350905090565b600454610100900460ff1615611a0c5760405163769dd35360e11b815260040160405180910390fd5b60045462010000900460ff1615611a365760405163ab35696f60e01b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611a7f576040516344b0e3c360e01b815260040160405180910390fd5b60208114611aa557604051636865567560e01b8152610a52906020908390600401615aaa565b6000611ab382840184614b11565b6000818152600760205260409020549091506001600160a01b0316611aee5760405163c5171ee960e01b815260048101829052602401610a52565b600081815260086020526040812080546001600160601b031691869190611b158385615abe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600260008282829054906101000a90046001600160601b0316611b5d9190615abe565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a828784611bb09190615ade565b604051611bbe929190615758565b60405180910390a2505050505050565b600454606090610100900460ff1615611bfa5760405163769dd35360e11b815260040160405180910390fd5b60008381526010602081815260408084208151608081018352815463ffffffff8116825262ffffff600160201b8204168286015261ffff600160381b820416938201939093526001600160a01b03600160481b8404811660608301908152968a9052949093526001600160e81b031990911690559151163314611c9857806060015133604051638e30e82360e01b8152600401610a52929190615af1565b8051600090611cce907f00000000000000000000000000000000000000000000000000000000000000009063ffffffff16615b0b565b90506000611cda613715565b90506000836020015162ffffff1682611cf3919061535c565b9050808310611d385782846020015162ffffff1684611d129190615ade565b611d1d906001615ade565b6040516315ad27c360e01b8152600401610a52929190615758565b6001600160401b03831115611d63576040516302c6ef8160e11b815260048101849052602401610a52565b604051888152339088907f16f3f633197fafab10a5df69e6f3f2f7f20092f08d8d47de0a91c0f4b96a1a259060200160405180910390a3611dc68785600d6000611db1888a6020015161379f565b815260200190815260200160002054866137ae565b98975050505050505050565b600454610100900460ff1615611dfb5760405163769dd35360e11b815260040160405180910390fd5b6000818152600760205260409020546001600160a01b0316611e335760405163c5171ee960e01b815260048101829052602401610a52565b6000818152600760205260409020600101546001600160a01b03163314611e8a576000818152600760205260409081902060010154905163d084e97560e01b8152610a52916001600160a01b031690600401614e5b565b6000818152600760205260409081902080546001600160a01b031980821633908117845560019093018054909116905591516001600160a01b039092169183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c938691611ef7918591615af1565b60405180910390a25050565b60008281526007602052604090205482906001600160a01b031680611f3e5760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b03821614611f695780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff1615611f925760405163769dd35360e11b815260040160405180910390fd5b60045462010000900460ff1615611fbc5760405163ab35696f60e01b815260040160405180910390fd5b60008481526007602052604090206002015460631901611fef576040516305a48e0f60e01b815260040160405180910390fd5b60036000611ffd8587613967565b815260208101919091526040016000205460ff166120b9576001600360006120258688613967565b815260208082019290925260409081016000908120805460ff191694151594909417909355868352600782528083206002018054600181018255908452919092200180546001600160a01b0319166001600160a01b0386161790555184907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e1906120b0908690614e5b565b60405180910390a25b50505050565b600454610100900460ff16156120e85760405163769dd35360e11b815260040160405180910390fd5b6120f18361346a565b6121105782604051635428d44960e01b8152600401610a529190614e5b565b604081146121355760408051636865567560e01b8152610a5291908390600401615aaa565b600061214382840184615b22565b90506000806000806121588560200151612c21565b9350935093509350816001600160a01b0316336001600160a01b0316146121945781604051636c51fda960e11b8152600401610a529190614e5b565b876001600160a01b031663294daa496040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f69190615b5c565b60ff16856000015160ff1614612293578460000151886001600160a01b031663294daa496040518163ffffffff1660e01b8152600401602060405180830381865afa158015612249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226d9190615b5c565b60405163e7aada9560e01b815260ff928316600482015291166024820152604401610a52565b6001600160401b038316156122bb57604051631685ecdd60e31b815260040160405180910390fd5b60006040518060a001604052806122d0600190565b60ff16815260200187602001518152602001846001600160a01b03168152602001838152602001866001600160601b031681525090506000816040516020016123199190615b79565b60405160208183030381529060405290506123378760200151612ff4565b600280548791906000906123559084906001600160601b031661539e565b92506101000a8154816001600160601b0302191690836001600160601b031602179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb8b886040518363ffffffff1660e01b81526004016123c79291906153fb565b6020604051808303816000875af11580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a91906153de565b61244b5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b6044820152606401610a52565b60405163ce3f471960e01b81526001600160a01b038b169063ce3f471990612477908490600401615c25565b600060405180830381600087803b15801561249157600080fd5b505af11580156124a5573d6000803e3d6000fd5b50506004805461ff00191661010017905550600090505b835181101561254f578381815181106124d7576124d7615330565b60200260200101516001600160a01b0316638ea981178c6040518263ffffffff1660e01b815260040161250a9190614e5b565b600060405180830381600087803b15801561252457600080fd5b505af1158015612538573d6000803e3d6000fd5b50505050808061254790615385565b9150506124bc565b506004805461ff00191690556020870151875160405160ff909116907fbd89b747474d3fc04664dfbd1d56ae7ffbe46ee097cdb9979c13916bb76269ce90612598908e90614e5b565b60405180910390a350505050505050505050565b60008281526007602052604090205482906001600160a01b0316806125e75760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b038216146126125780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff161561263b5760405163769dd35360e11b815260040160405180910390fd5b600084815260086020526040902054600160601b90046001600160401b03161561267857604051631685ecdd60e31b815260040160405180910390fd5b600360006126868587613967565b815260208101919091526040016000205460ff166126bb5783836040516379bfd40160e01b8152600401610a52929190615c38565b60008481526007602090815260408083206002018054825181850281018501909352808352919290919083018282801561271e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612700575b50505050509050600060018251612735919061535c565b905060005b825181101561284057856001600160a01b031683828151811061275f5761275f615330565b60200260200101516001600160a01b03160361282e57600083838151811061278957612789615330565b6020026020010151905080600760008a815260200190815260200160002060020183815481106127bb576127bb615330565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394909416939093179092558981526007909152604090206002018054806128065761280661536f565b600082815260209020810160001990810180546001600160a01b031916905501905550612840565b8061283881615385565b91505061273a565b506003600061284f8789613967565b815260208101919091526040908101600020805460ff191690555186907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a790611bbe908890614e5b565b604051632cb6686f60e01b815260040160405180910390fd5b60008281526007602052604090205482906001600160a01b0316806128ed5760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b038216146129185780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff16156129415760405163769dd35360e11b815260040160405180910390fd5b6000848152600760205260409020600101546001600160a01b038481169116146120b9576000848152600760205260409081902060010180546001600160a01b0319166001600160a01b0386161790555184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a1906120b09033908790615af1565b60045460009062010000900460ff16156129f05760405163ab35696f60e01b815260040160405180910390fd5b600454610100900460ff1615612a195760405163769dd35360e11b815260040160405180910390fd5b3415612a3a57604051630b829bad60e21b8152346004820152602401610a52565b600080612a4989338a8a613143565b925050915060006040518061010001604052808481526020018a61ffff168152602001336001600160a01b031681526020018781526020018863ffffffff166001600160601b031681526020018b81526020016000815260200160008152509050600080612ab68361397d565b60c087019190915260e08601919091526040519193509150612ae29085908c908f908790602001615c4f565b60405160208183030381529060405280519060200120600c6000878152602001908152602001600020819055506000604051806101600160405280878152602001336001600160a01b03168152602001866001600160401b031681526020018c62ffffff1681526020018e81526020018d61ffff1681526020018b63ffffffff1681526020018581526020018a8152602001848152602001836001600160601b0316815250905080600001517f01872fb9c7d6d68af06a17347935e04412da302a377224c205e672c26e18c37f82602001518360400151846060015185608001518660a001518760c001518860e0015160c001518960e0015160e001518a61010001518b61012001518c6101400151604051612c089b9a99989796959493929190615d02565b60405180910390a250939b9a5050505050505050505050565b600081815260076020526040812054819081906060906001600160a01b0316612c605760405163c5171ee960e01b815260048101869052602401610a52565b60008581526008602090815260408083205460078352928190208054600290910180548351818602810186019094528084526001600160601b03861695600160601b90046001600160401b0316946001600160a01b03909316939192839190830182828015612cf857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612cda575b5050505050905093509350935093509193509193565b612d16612f9f565b610a5b81613bb4565b600a546001600160a01b03163314612d4a57604051634bea32db60e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90612d9890859085906004016153c5565b6020604051808303816000875af1158015612db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddb91906153de565b611678576040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190612e2b903090600401614e5b565b602060405180830381865afa158015612e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6c9190615d98565b8160405163cf47918160e01b8152600401610a52929190615758565b604080516101408101825260045460ff80821615158352610100808304821615156020808601919091526201000084048316151585870152630100000084048316606080870191909152600160201b80860490941660808088019190915263ffffffff600160281b8704811660a0890152600160481b8704811660c0890152600160681b8704811660e0890152600160881b9096048616938701939093526005546001600160601b039081166101208801528751938401885260065495861684526001600160401b03948604851692840192909252600160601b850490931695820195909552600160a01b90920490931692810192909252600091612f8d9190613c57565b6001600160601b031690505b92915050565b6000546001600160a01b03163314612ff25760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610a52565b565b6000818152600760209081526040808320815160608101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181529295939486019383018282801561307a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161305c575b505050505081525050905060005b8160400151518110156130ea57600360006130c0846040015184815181106130b2576130b2615330565b602002602001015186613967565b81526020810191909152604001600020805460ff19169055806130e281615385565b915050613088565b50600082815260076020526040812080546001600160a01b031990811682556001820180549091169055906131226002830182614a3e565b505050600090815260086020526040902080546001600160a01b0319169055565b600061314d614a5c565b60006103e88561ffff16111561317c57846103e8604051634a90778560e01b8152600401610a52929190615aaa565b8461ffff166000036131a1576040516308fad2a760e01b815260040160405180910390fd5b6000806131ac613c9d565b600e54919350915065ffffffffffff1660006132178b8b84604080513060208201529081018490526001600160a01b038316606082015265ffffffffffff8216608082015260009060a00160408051601f198184030181529190528051602090910120949350505050565b9050613224826001615db1565b600e805465ffffffffffff9290921665ffffffffffff199092169190911790556040805160808101825263ffffffff909416845262ffffff8916602085015261ffff8a16908401526001600160a01b038a1660608401529550909350909150509450945094915050565b604080516080808201835260065463ffffffff8082168452600160201b8083046001600160401b03908116602080880191909152600160601b850490911686880152600160a01b9093046001600160601b0390811660608088019190915287516101408101895260045460ff808216151583526101008083048216151598840198909852620100008204811615159a83019a909a52630100000081048a169282019290925292810490971694820194909452600160281b8604821660a0820152600160481b8604821660c0820152600160681b8604821660e0820152600160881b9095041690840152600554166101208301526000918291906003836133948888613967565b815260208101919091526040016000205460ff166133c95784866040516379bfd40160e01b8152600401610a52929190615c38565b60006133d58284613c57565b600087815260086020526040902080546001600160601b0392831693509091168281101561342457815460405163cf47918160e01b8152610a52916001600160601b0316908590600401615dd0565b81546001600160601b0319908116918490036001600160601b038181169390931790935560028054918216918316859003909216179055909450925050505b9250929050565b6000805b6009548110156134ca57826001600160a01b03166009828154811061349557613495615330565b6000918252602090912001546001600160a01b0316036134b85750600192915050565b806134c281615385565b91505061346e565b50600092915050565b6000826001600160401b031684600001516001600160401b0316111561352257835160405163012d824d60e01b81526001600160401b0380861660048301529091166024820152604401610a52565b606084015151604080860151905160009161353f91602001615de9565b60405160208183030381529060405280519060200120905085604001516000015160006002811061357257613572615330565b602002015115801561358b575060408601515160200151155b156135c557600d60006135af88600001516001600160401b0316896020015161379f565b8152602001908152602001600020549050613648565b856080015115613648576000600d60006135f089600001516001600160401b03168a6020015161379f565b81526020810191909152604001600020549050806136425781600d60006136288a600001516001600160401b03168b6020015161379f565b815260208101919091526040016000205560019350613646565b8091505b505b6000613655838389613d70565b905083806136605750805b979650505050505050565b60008060008061367b8686614189565b6001600160401b031690506000613693826010615b0b565b9050600060146136a4836015615b0b565b6136ae9190615e29565b89516136ba9190615b0b565b838960e0015163ffffffff168c6136d19190615abe565b6001600160601b03166136e49190615b0b565b6136ee9190615ade565b90506000806137008360008c8c614202565b909d909c50949a509398505050505050505050565b60004661a4b181148061372a575062066eed81145b156137985760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561376e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137929190615d98565b91505090565b4391505090565b62ffffff1660189190911b1790565b6060826137e05760405163220a34e960e11b8152600481018690526001600160401b0383166024820152604401610a52565b604080516020808201889052865163ffffffff168284015286015162ffffff166060808301919091529186015161ffff166080820152908501516001600160a01b031660a082015260c0810184905260009060e0016040516020818303038152906040528051906020012090506103e8856040015161ffff1611156138825784604001516103e8604051634a90778560e01b8152600401610a52929190615aaa565b6000856040015161ffff166001600160401b038111156138a4576138a4614b68565b6040519080825280602002602001820160405280156138cd578160200160208202803683370190505b50905060005b866040015161ffff168161ffff16101561395c57828160405160200161391092919091825260f01b6001600160f01b031916602082015260220190565b6040516020818303038152906040528051906020012060001c828261ffff168151811061393f5761393f615330565b602090810291909101015280613954816159d0565b9150506138d3565b509695505050505050565b60a081901b6001600160a01b0383161792915050565b6000806000806003600061399987604001518860a00151613967565b815260208101919091526040016000205460ff166139d6578460a0015185604001516040516379bfd40160e01b8152600401610a52929190615c38565b604080516080808201835260065463ffffffff80821684526001600160401b03600160201b8084048216602080880191909152600160601b8504909216868801526001600160601b03600160a01b909404841660608088019190915287516101408101895260045460ff808216151583526101008083048216151596840196909652620100008204811615159a83019a909a52630100000081048a168284015292830490981688870152600160281b8204841660a0890152600160481b8204841660c0890152600160681b8204841660e0890152600160881b90910490921690860152600554909116610120850152908801519088015191929160009182918291613ae291868861366b565b60a08d0151600090815260086020526040902080546001600160601b0394851697509295509093509116841115613b3a57805460405163cf47918160e01b8152610a52916001600160601b0316908690600401615dd0565b80546001600160601b0360016001600160401b03600160601b8085048216929092011602818116828416178790038083166001600160601b03199283166001600160a01b03199095169490941793909317909355600280548083168890039092169190931617909155929a91995097509095509350505050565b336001600160a01b03821603613c065760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610a52565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080613c648484614189565b8460c0015163ffffffff16613c799190615e3d565b6001600160401b031690506000613c938260008787614202565b5095945050505050565b6000806000613caa613715565b90506000613cd87f000000000000000000000000000000000000000000000000000000000000000083615e60565b9050600081613d077f000000000000000000000000000000000000000000000000000000000000000085615ade565b613d11919061535c565b90506000613d3f7f000000000000000000000000000000000000000000000000000000000000000083615e29565b905063ffffffff8110613d65576040516307b2a52360e41b815260040160405180910390fd5b909590945092505050565b6000806040518060c00160405280866001600160401b03811115613d9657613d96614b68565b604051908082528060200260200182016040528015613dbf578160200160208202803683370190505b508152602001866001600160401b03811115613ddd57613ddd614b68565b6040519080825280601f01601f191660200182016040528015613e07576020820181803683370190505b508152602001866001600160401b03811115613e2557613e25614b68565b604051908082528060200260200182016040528015613e5857816020015b6060815260200190600190039081613e435790505b50815260006020820152604001866001600160401b03811115613e7d57613e7d614b68565b604051908082528060200260200182016040528015613ea6578160200160208202803683370190505b508152602001866001600160401b03811115613ec457613ec4614b68565b604051908082528060200260200182016040528015613eed578160200160208202803683370190505b509052905060005b8581101561406c57600084606001518281518110613f1557613f15615330565b60200260200101519050600080600080613f3989600001518a602001518c8861424d565b93509350935093508315613f8d57828760400151886060015161ffff1681518110613f6657613f66615330565b602090810291909101015260608701805190613f81826159d0565b61ffff16905250613fc0565b600160f81b87602001518781518110613fa857613fa8615330565b60200101906001600160f81b031916908160001a9053505b8780613fca575080155b85515188518051929a50909188908110613fe657613fe6615330565b602002602001018181525050818760800151878151811061400957614009615330565b60200260200101906001600160601b031690816001600160601b031681525050846000015160a001518760a00151878151811061404857614048615330565b6020026020010181815250505050505050808061406490615385565b915050613ef5565b5060608301515115614181576000816060015161ffff166001600160401b0381111561409a5761409a614b68565b6040519080825280602002602001820160405280156140cd57816020015b60608152602001906001900390816140b85790505b50905060005b826060015161ffff1681101561413157826040015181815181106140f9576140f9615330565b602002602001015182828151811061411357614113615330565b6020026020010181905250808061412990615385565b9150506140d3565b5081516020830151608084015160a08501516040517f8f79f730779e875ce76c428039cc2052b5b5918c2a55c598fab251c1198aec549461417794909390928792615ead565b60405180910390a1505b509392505050565b815160009080156141a6575060408201516001600160401b031615155b156141fa5761010083015163ffffffff16431080806141e757506101008401516141d69063ffffffff164361535c565b83602001516001600160401b031610155b156141f85750506040810151612f99565b505b503a92915050565b600080600060648560600151606461421a9190615f50565b6142279060ff1689615b0b565b6142319190615e29565b905061423f818787876145bc565b925092505094509492505050565b805160a09081015160009081526008602090815260408083208551948501519151939460609486948594859261428b928e928e929091879101615c4f565b60408051601f19818403018152918152815160209283012084516000908152600c90935291205490915081146142fe5750505460408051808201909152601081526f756e6b6e6f776e2063616c6c6261636b60801b60208201526001955093506001600160601b031691508390506145b1565b50614307614a5c565b600061433c7f00000000000000000000000000000000000000000000000000000000000000006001600160401b038e16615e29565b6040805160808101825263ffffffff909216825262ffffff8d1660208084019190915285015161ffff16828201528401516001600160a01b0316606082015291508990506143d0575050604080518082019091526016815275756e617661696c61626c652072616e646f6d6e65737360501b60208201529054600195509093506001600160601b03169150600090506145b1565b60006143e28360000151838c8f6137ae565b606080840151855191860151604051939450909260009263d21ea8fd60e01b9261441192879190602401615f69565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526004805461ff00191661010017905590506000805a9050600061447c8e60000151608001516001600160601b0316896040015186614630565b9093509050806144b1578d516080015160405163aad1598360e01b8152610a52916001600160601b0316908490600401615758565b506000610bb85a6144c29190615ade565b6004805461ff00191690559050818110156144eb576144eb6144e4828461535c565b8f5161466f565b8854600160601b90046001600160401b031689600c61450983615f94565b82546001600160401b039182166101009390930a92830291909202199091161790555087516000908152600c60205260408120558261457f5760408051808201909152601081526f195e1958dd5d1a5bdb8819985a5b195960821b60208201528954600191906001600160601b0316600061459f565b604080516020810190915260008082528a549091906001600160601b0316825b9c509c509c509c505050505050505050505b945094509450949050565b6000808085156145cc57856145d6565b6145d6858561489b565b90506000816145ed89670de0b6b3a7640000615b0b565b6145f79190615e29565b9050676765c793fa10079d601b1b8111156146245760405162de437160e81b815260040160405180910390fd5b97909650945050505050565b6000805a610bb8811061466657610bb881039050856040820482031115614666576000808551602087016000898bf19250600191505b50935093915050565b80608001516001600160601b0316821115614688575050565b6004546000906064906146a590600160201b900460ff1682615fb7565b60ff168360c001518585608001516001600160601b03166146c6919061535c565b6146d09190615b0b565b6146da9190615b0b565b6146e49190615e29565b60e080840151604080516101408101825260045460ff80821615158352610100808304821615156020808601919091526201000084048316151585870152630100000084048316606080870191909152600160201b80860490941660808088019190915263ffffffff600160281b8704811660a0890152600160481b8704811660c0890152600160681b870481169a88019a909a52600160881b9095048916928601929092526005546001600160601b039081166101208701528651948501875260065498891685526001600160401b03938904841691850191909152600160601b880490921694830194909452600160a01b909504909416918401919091529293506000926147f792859291906145bc565b5060a08401516000908152600860205260408120805492935083929091906148299084906001600160601b0316615abe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600260008282829054906101000a90046001600160601b03166148719190615abe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555050505050565b60a0820151606082015160009190600163ffffffff831611908180156148d7575084516148ce9063ffffffff164261535c565b8363ffffffff16105b156148e457506101208501515b6001600160601b031695945050505050565b604051806080016040528060006001600160401b03168152602001600062ffffff16815260200160008152602001600081525090565b6040518061010001604052806008906020820280368337509192915050565b6001830191839082156149d95791602002820160005b838211156149a857833562ffffff1683826101000a81548162ffffff021916908362ffffff1602179055509260200192600301602081600201049283019260010302614961565b80156149d75782816101000a81549062ffffff02191690556003016020816002010492830192600103026149a8565b505b506149e5929150614a83565b5090565b8280548282559060005260206000209081019282156149d9579160200282015b828111156149d957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614a09565b5080546000825590600052602060002090810190610a5b9190614a83565b60408051608081018252600080825260208201819052918101829052606081019190915290565b5b808211156149e55760008155600101614a84565b6001600160a01b0381168114610a5b57600080fd5b8035614ab881614a98565b919050565b600060208284031215614acf57600080fd5b8135614ada81614a98565b9392505050565b60008060408385031215614af457600080fd5b823591506020830135614b0681614a98565b809150509250929050565b600060208284031215614b2357600080fd5b5035919050565b60006101408284031215614b3d57600080fd5b50919050565b803561ffff81168114614ab857600080fd5b803562ffffff81168114614ab857600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715614ba057614ba0614b68565b60405290565b60405161010081016001600160401b0381118282101715614ba057614ba0614b68565b60405160a081016001600160401b0381118282101715614ba057614ba0614b68565b604051602081016001600160401b0381118282101715614ba057614ba0614b68565b604051601f8201601f191681016001600160401b0381118282101715614c3557614c35614b68565b604052919050565b600082601f830112614c4e57600080fd5b81356001600160401b03811115614c6757614c67614b68565b614c7a601f8201601f1916602001614c0d565b818152846020838601011115614c8f57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215614cc257600080fd5b84359350614cd260208601614b43565b9250614ce060408601614b55565b915060608501356001600160401b03811115614cfb57600080fd5b614d0787828801614c3d565b91505092959194509250565b60008083601f840112614d2557600080fd5b5081356001600160401b03811115614d3c57600080fd5b6020830191508360208260051b850101111561346357600080fd5b60008060008060408587031215614d6d57600080fd5b84356001600160401b0380821115614d8457600080fd5b614d9088838901614d13565b90965094506020870135915080821115614da957600080fd5b50614db687828801614d13565b95989497509550505050565b80356001600160401b0381168114614ab857600080fd5b600080600080600060808688031215614df157600080fd5b85356001600160401b03811115614e0757600080fd5b614e1388828901614d13565b90965094505060208601356001600160c01b0381168114614e3357600080fd5b9250614e4160408701614dc2565b9150614e4f60608701614dc2565b90509295509295909350565b6001600160a01b0391909116815260200190565b6101008101818360005b6008811015614e9d57815162ffffff16835260209283019290910190600101614e79565b50505092915050565b63ffffffff81168114610a5b57600080fd5b8035614ab881614ea6565b600060408284031215614ed557600080fd5b614edd614b7e565b8235614ee881614ea6565b81526020830135614ef881614ea6565b60208201529392505050565b8015158114610a5b57600080fd5b8035614ab881614f04565b600060208284031215614f2f57600080fd5b8135614ada81614f04565b6000610100808385031215614f4e57600080fd5b838184011115614f5d57600080fd5b509092915050565b60008060008060808587031215614f7b57600080fd5b843593506020850135614f8d81614ea6565b925060408501356001600160401b0380821115614fa957600080fd5b614fb588838901614c3d565b93506060870135915080821115614fcb57600080fd5b50614d0787828801614c3d565b60008083601f840112614fea57600080fd5b5081356001600160401b0381111561500157600080fd5b60208301915083602082850101111561346357600080fd5b6000806000806060858703121561502f57600080fd5b843561503a81614a98565b93506020850135925060408501356001600160401b0381111561505c57600080fd5b614db687828801614fd8565b60008060006060848603121561507d57600080fd5b833592506020840135915060408401356001600160401b038111156150a157600080fd5b6150ad86828701614c3d565b9150509250925092565b600081518084526020808501945080840160005b838110156150e7578151875295820195908201906001016150cb565b509495945050505050565b602081526000614ada60208301846150b7565b60008060006040848603121561511a57600080fd5b833561512581614a98565b925060208401356001600160401b0381111561514057600080fd5b61514c86828701614fd8565b9497909650939450505050565b6000806020838503121561516c57600080fd5b82356001600160401b0381111561518257600080fd5b61518e85828601614fd8565b90969095509350505050565b60008060008060008060c087890312156151b357600080fd5b863595506151c360208801614b43565b94506151d160408801614b55565b935060608701356151e181614ea6565b925060808701356001600160401b03808211156151fd57600080fd5b6152098a838b01614c3d565b935060a089013591508082111561521f57600080fd5b5061522c89828a01614c3d565b9150509295509295509295565b600081518084526020808501945080840160005b838110156150e75781516001600160a01b03168752958201959082019060010161524d565b6001600160601b03851681526001600160401b03841660208201526001600160a01b03831660408201526080606082018190526000906152b490830184615239565b9695505050505050565b600080604083850312156152d157600080fd5b82356152dc81614a98565b946020939093013593505050565b600080604083850312156152fd57600080fd5b8235915060208301356001600160401b0381111561531a57600080fd5b61532685828601614c3d565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115612f9957612f99615346565b634e487b7160e01b600052603160045260246000fd5b60006001820161539757615397615346565b5060010190565b6001600160601b038281168282160390808211156153be576153be615346565b5092915050565b6001600160a01b03929092168252602082015260400190565b6000602082840312156153f057600080fd5b8151614ada81614f04565b6001600160a01b039290921682526001600160601b0316602082015260400190565b60ff81168114610a5b57600080fd5b8035614ab88161541d565b60006020828403121561544957600080fd5b8135614ada8161541d565b60008135612f9981614f04565b60008135612f998161541d565b60008135612f9981614ea6565b6001600160601b0381168114610a5b57600080fd5b60008135612f998161547b565b81356154a881614f04565b815490151560ff1660ff19919091161781556154e36154c960208401615454565b82805461ff00191691151560081b61ff0016919091179055565b61550e6154f260408401615454565b82805462ff0000191691151560101b62ff000016919091179055565b61553761551d60608401615461565b825463ff000000191660189190911b63ff00000016178255565b61556461554660808401615461565b82805460ff60201b191660209290921b60ff60201b16919091179055565b61559761557360a0840161546e565b82805463ffffffff60281b191660289290921b63ffffffff60281b16919091179055565b6155ca6155a660c0840161546e565b82805463ffffffff60481b191660489290921b63ffffffff60481b16919091179055565b6155fd6155d960e0840161546e565b82805463ffffffff60681b191660689290921b63ffffffff60681b16919091179055565b61563161560d610100840161546e565b82805463ffffffff60881b191660889290921b63ffffffff60881b16919091179055565b6116786156416101208401615490565b6001830180546001600160601b0319166001600160601b0392909216919091179055565b8035614ab88161547b565b61014081016156888261568285614f12565b15159052565b61569460208401614f12565b151560208301526156a760408401614f12565b151560408301526156ba6060840161542c565b60ff1660608301526156ce6080840161542c565b60ff1660808301526156e260a08401614eb8565b63ffffffff1660a08301526156f960c08401614eb8565b63ffffffff1660c083015261571060e08401614eb8565b63ffffffff1660e0830152610100615729848201614eb8565b63ffffffff1690830152610120615741848201615665565b6001600160601b038116848301525b505092915050565b918252602082015260400190565b6000823560be1983360301811261577c57600080fd5b9190910192915050565b600082601f83011261579757600080fd5b813560206001600160401b03808311156157b3576157b3614b68565b8260051b6157c2838201614c0d565b93845285810183019383810190888611156157dc57600080fd5b84880192505b85831015611dc6578235848111156157f957600080fd5b8801601f196040828c038201121561581057600080fd5b615818614b7e565b878301358781111561582957600080fd5b8301610100818e038401121561583e57600080fd5b615846614ba6565b925088810135835261585a60408201614b43565b8984015261586a60608201614aad565b604084015260808101358881111561588157600080fd5b61588f8e8b83850101614c3d565b6060850152506158a160a08201615665565b608084015260c081013560a084015260e081013560c084015261010081013560e0840152508181526158d560408401615665565b818901528452505091840191908401906157e2565b600081360360c08112156158fd57600080fd5b615905614bc9565b61590e84614dc2565b8152602061591d818601614b55565b828201526040603f198401121561593357600080fd5b61593b614beb565b925036605f86011261594c57600080fd5b615954614b7e565b80608087013681111561596657600080fd5b604088015b81811015615982578035845292840192840161596b565b50908552604084019490945250509035906001600160401b038211156159a757600080fd5b6159b336838601615786565b60608201526159c460a08501614f12565b60808201529392505050565b600061ffff8083168181036159e7576159e7615346565b6001019392505050565b6000608080830160018060401b038089168552602060018060c01b038916818701526040828916818801526060858189015284895180875260a08a019150848b01965060005b81811015615a735787518051881684528681015162ffffff16878501528581015186850152840151848401529685019691880191600101615a37565b50909d9c50505050505050505050505050565b60006001600160401b038281166002600160401b031981016159e7576159e7615346565b61ffff929092168252602082015260400190565b6001600160601b038181168382160190808211156153be576153be615346565b80820180821115612f9957612f99615346565b6001600160a01b0392831681529116602082015260400190565b8082028115828204841417612f9957612f99615346565b600060408284031215615b3457600080fd5b615b3c614b7e565b8235615b478161541d565b81526020928301359281019290925250919050565b600060208284031215615b6e57600080fd5b8151614ada8161541d565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160a06080840152615bbe60c0840182615239565b608094909401516001600160601b031660a093909301929092525090919050565b6000815180845260005b81811015615c0557602081850181015186830182015201615be9565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000614ada6020830184615bdf565b9182526001600160a01b0316602082015260400190565b60018060401b038516815262ffffff84166020820152826040820152608060608201528151608082015261ffff60208301511660a082015260018060a01b0360408301511660c0820152600060608301516101008060e0850152615cb7610180850183615bdf565b91506080850151615cd2828601826001600160601b03169052565b505060a084015161012084015260c084015161014084015260e08401516101608401528091505095945050505050565b6001600160a01b038c1681526001600160401b038b16602082015262ffffff8a1660408201526060810189905261ffff8816608082015263ffffffff871660a082015260c0810186905260e081018590526101606101008201819052600090615d6d83820187615bdf565b61012084019590955250506001600160601b0391909116610140909101529998505050505050505050565b600060208284031215615daa57600080fd5b5051919050565b65ffffffffffff8181168382160190808211156153be576153be615346565b6001600160601b03929092168252602082015260400190565b815160408201908260005b6002811015614e9d578251825260209283019290910190600101615df4565b634e487b7160e01b600052601260045260246000fd5b600082615e3857615e38615e13565b500490565b6001600160401b0381811683821602808216919082811461575057615750615346565b600082615e6f57615e6f615e13565b500690565b600081518084526020808501945080840160005b838110156150e75781516001600160601b031687529582019590820190600101615e88565b60a081526000615ec060a08301886150b7565b602083820381850152615ed38289615bdf565b915083820360408501528187518084528284019150828160051b850101838a0160005b83811015615f2457601f19878403018552615f12838351615bdf565b94860194925090850190600101615ef6565b50508681036060880152615f38818a615e74565b9450505050508281036080840152611dc681856150b7565b60ff8181168382160190811115612f9957612f99615346565b838152606060208201526000615f8260608301856150b7565b82810360408401526152b48185615bdf565b60006001600160401b03821680615fad57615fad615346565b6000190192915050565b60ff8281168282160390811115612f9957612f9961534656fea164736f6c6343000813000a", +} + +var VRFCoordinatorABI = VRFCoordinatorMetaData.ABI + +var VRFCoordinatorBin = VRFCoordinatorMetaData.Bin + +func DeployVRFCoordinator(auth *bind.TransactOpts, backend bind.ContractBackend, beaconPeriodBlocksArg *big.Int, linkToken common.Address) (common.Address, *types.Transaction, *VRFCoordinator, error) { + parsed, err := VRFCoordinatorMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(VRFCoordinatorBin), backend, beaconPeriodBlocksArg, linkToken) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &VRFCoordinator{VRFCoordinatorCaller: VRFCoordinatorCaller{contract: contract}, VRFCoordinatorTransactor: VRFCoordinatorTransactor{contract: contract}, VRFCoordinatorFilterer: VRFCoordinatorFilterer{contract: contract}}, nil +} + +type VRFCoordinator struct { + address common.Address + abi abi.ABI + VRFCoordinatorCaller + VRFCoordinatorTransactor + VRFCoordinatorFilterer +} + +type VRFCoordinatorCaller struct { + contract *bind.BoundContract +} + +type VRFCoordinatorTransactor struct { + contract *bind.BoundContract +} + +type VRFCoordinatorFilterer struct { + contract *bind.BoundContract +} + +type VRFCoordinatorSession struct { + Contract *VRFCoordinator + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type VRFCoordinatorCallerSession struct { + Contract *VRFCoordinatorCaller + CallOpts bind.CallOpts +} + +type VRFCoordinatorTransactorSession struct { + Contract *VRFCoordinatorTransactor + TransactOpts bind.TransactOpts +} + +type VRFCoordinatorRaw struct { + Contract *VRFCoordinator +} + +type VRFCoordinatorCallerRaw struct { + Contract *VRFCoordinatorCaller +} + +type VRFCoordinatorTransactorRaw struct { + Contract *VRFCoordinatorTransactor +} + +func NewVRFCoordinator(address common.Address, backend bind.ContractBackend) (*VRFCoordinator, error) { + abi, err := abi.JSON(strings.NewReader(VRFCoordinatorABI)) + if err != nil { + return nil, err + } + contract, err := bindVRFCoordinator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &VRFCoordinator{address: address, abi: abi, VRFCoordinatorCaller: VRFCoordinatorCaller{contract: contract}, VRFCoordinatorTransactor: VRFCoordinatorTransactor{contract: contract}, VRFCoordinatorFilterer: VRFCoordinatorFilterer{contract: contract}}, nil +} + +func NewVRFCoordinatorCaller(address common.Address, caller bind.ContractCaller) (*VRFCoordinatorCaller, error) { + contract, err := bindVRFCoordinator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VRFCoordinatorCaller{contract: contract}, nil +} + +func NewVRFCoordinatorTransactor(address common.Address, transactor bind.ContractTransactor) (*VRFCoordinatorTransactor, error) { + contract, err := bindVRFCoordinator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VRFCoordinatorTransactor{contract: contract}, nil +} + +func NewVRFCoordinatorFilterer(address common.Address, filterer bind.ContractFilterer) (*VRFCoordinatorFilterer, error) { + contract, err := bindVRFCoordinator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VRFCoordinatorFilterer{contract: contract}, nil +} + +func bindVRFCoordinator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VRFCoordinatorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_VRFCoordinator *VRFCoordinatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFCoordinator.Contract.VRFCoordinatorCaller.contract.Call(opts, result, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.Contract.VRFCoordinatorTransactor.contract.Transfer(opts) +} + +func (_VRFCoordinator *VRFCoordinatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFCoordinator.Contract.VRFCoordinatorTransactor.contract.Transact(opts, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFCoordinator.Contract.contract.Call(opts, result, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.Contract.contract.Transfer(opts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFCoordinator.Contract.contract.Transact(opts, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) MAXCONSUMERS(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "MAX_CONSUMERS") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) MAXCONSUMERS() (uint16, error) { + return _VRFCoordinator.Contract.MAXCONSUMERS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) MAXCONSUMERS() (uint16, error) { + return _VRFCoordinator.Contract.MAXCONSUMERS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) MAXNUMWORDS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "MAX_NUM_WORDS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) MAXNUMWORDS() (*big.Int, error) { + return _VRFCoordinator.Contract.MAXNUMWORDS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) MAXNUMWORDS() (*big.Int, error) { + return _VRFCoordinator.Contract.MAXNUMWORDS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "NUM_CONF_DELAYS") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) NUMCONFDELAYS() (uint8, error) { + return _VRFCoordinator.Contract.NUMCONFDELAYS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) NUMCONFDELAYS() (uint8, error) { + return _VRFCoordinator.Contract.NUMCONFDELAYS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetCallbackMemo(opts *bind.CallOpts, requestId *big.Int) ([32]byte, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getCallbackMemo", requestId) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetCallbackMemo(requestId *big.Int) ([32]byte, error) { + return _VRFCoordinator.Contract.GetCallbackMemo(&_VRFCoordinator.CallOpts, requestId) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetCallbackMemo(requestId *big.Int) ([32]byte, error) { + return _VRFCoordinator.Contract.GetCallbackMemo(&_VRFCoordinator.CallOpts, requestId) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetConfirmationDelays(opts *bind.CallOpts) ([8]*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getConfirmationDelays") + + if err != nil { + return *new([8]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([8]*big.Int)).(*[8]*big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetConfirmationDelays() ([8]*big.Int, error) { + return _VRFCoordinator.Contract.GetConfirmationDelays(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetConfirmationDelays() ([8]*big.Int, error) { + return _VRFCoordinator.Contract.GetConfirmationDelays(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetFee(opts *bind.CallOpts, arg0 *big.Int, arg1 []byte) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getFee", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetFee(arg0 *big.Int, arg1 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFee(&_VRFCoordinator.CallOpts, arg0, arg1) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetFee(arg0 *big.Int, arg1 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFee(&_VRFCoordinator.CallOpts, arg0, arg1) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetFulfillmentFee(opts *bind.CallOpts, arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getFulfillmentFee", arg0, callbackGasLimit, arguments, arg3) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetFulfillmentFee(arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFulfillmentFee(&_VRFCoordinator.CallOpts, arg0, callbackGasLimit, arguments, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetFulfillmentFee(arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFulfillmentFee(&_VRFCoordinator.CallOpts, arg0, callbackGasLimit, arguments, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetSubscription(opts *bind.CallOpts, subId *big.Int) (GetSubscription, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getSubscription", subId) + + outstruct := new(GetSubscription) + if err != nil { + return *outstruct, err + } + + outstruct.Balance = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.PendingFulfillments = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.Owner = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) + outstruct.Consumers = *abi.ConvertType(out[3], new([]common.Address)).(*[]common.Address) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetSubscription(subId *big.Int) (GetSubscription, + + error) { + return _VRFCoordinator.Contract.GetSubscription(&_VRFCoordinator.CallOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetSubscription(subId *big.Int) (GetSubscription, + + error) { + return _VRFCoordinator.Contract.GetSubscription(&_VRFCoordinator.CallOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetSubscriptionLinkBalance(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getSubscriptionLinkBalance") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetSubscriptionLinkBalance() (*big.Int, error) { + return _VRFCoordinator.Contract.GetSubscriptionLinkBalance(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetSubscriptionLinkBalance() (*big.Int, error) { + return _VRFCoordinator.Contract.GetSubscriptionLinkBalance(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "i_beaconPeriodBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _VRFCoordinator.Contract.IBeaconPeriodBlocks(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _VRFCoordinator.Contract.IBeaconPeriodBlocks(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) ILink(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "i_link") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) ILink() (common.Address, error) { + return _VRFCoordinator.Contract.ILink(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) ILink() (common.Address, error) { + return _VRFCoordinator.Contract.ILink(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) MigrationVersion(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "migrationVersion") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) MigrationVersion() (uint8, error) { + return _VRFCoordinator.Contract.MigrationVersion(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) MigrationVersion() (uint8, error) { + return _VRFCoordinator.Contract.MigrationVersion(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) OnMigration(opts *bind.CallOpts, arg0 []byte) error { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "onMigration", arg0) + + if err != nil { + return err + } + + return err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) OnMigration(arg0 []byte) error { + return _VRFCoordinator.Contract.OnMigration(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) OnMigration(arg0 []byte) error { + return _VRFCoordinator.Contract.OnMigration(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) Owner() (common.Address, error) { + return _VRFCoordinator.Contract.Owner(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) Owner() (common.Address, error) { + return _VRFCoordinator.Contract.Owner(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SCallbackConfig(opts *bind.CallOpts) (SCallbackConfig, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_callbackConfig") + + outstruct := new(SCallbackConfig) + if err != nil { + return *outstruct, err + } + + outstruct.MaxCallbackGasLimit = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.MaxCallbackArgumentsLength = *abi.ConvertType(out[1], new(uint32)).(*uint32) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SCallbackConfig() (SCallbackConfig, + + error) { + return _VRFCoordinator.Contract.SCallbackConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SCallbackConfig() (SCallbackConfig, + + error) { + return _VRFCoordinator.Contract.SCallbackConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SCoordinatorConfig(opts *bind.CallOpts) (SCoordinatorConfig, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_coordinatorConfig") + + outstruct := new(SCoordinatorConfig) + if err != nil { + return *outstruct, err + } + + outstruct.UseReasonableGasPrice = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ReentrancyLock = *abi.ConvertType(out[1], new(bool)).(*bool) + outstruct.Paused = *abi.ConvertType(out[2], new(bool)).(*bool) + outstruct.PremiumPercentage = *abi.ConvertType(out[3], new(uint8)).(*uint8) + outstruct.UnusedGasPenaltyPercent = *abi.ConvertType(out[4], new(uint8)).(*uint8) + outstruct.StalenessSeconds = *abi.ConvertType(out[5], new(uint32)).(*uint32) + outstruct.RedeemableRequestGasOverhead = *abi.ConvertType(out[6], new(uint32)).(*uint32) + outstruct.CallbackRequestGasOverhead = *abi.ConvertType(out[7], new(uint32)).(*uint32) + outstruct.ReasonableGasPriceStalenessBlocks = *abi.ConvertType(out[8], new(uint32)).(*uint32) + outstruct.FallbackWeiPerUnitLink = *abi.ConvertType(out[9], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SCoordinatorConfig() (SCoordinatorConfig, + + error) { + return _VRFCoordinator.Contract.SCoordinatorConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SCoordinatorConfig() (SCoordinatorConfig, + + error) { + return _VRFCoordinator.Contract.SCoordinatorConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SPendingRequests(opts *bind.CallOpts, arg0 *big.Int) (SPendingRequests, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_pendingRequests", arg0) + + outstruct := new(SPendingRequests) + if err != nil { + return *outstruct, err + } + + outstruct.SlotNumber = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.ConfirmationDelay = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.NumWords = *abi.ConvertType(out[2], new(uint16)).(*uint16) + outstruct.Requester = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SPendingRequests(arg0 *big.Int) (SPendingRequests, + + error) { + return _VRFCoordinator.Contract.SPendingRequests(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SPendingRequests(arg0 *big.Int) (SPendingRequests, + + error) { + return _VRFCoordinator.Contract.SPendingRequests(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SProducer(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_producer") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SProducer() (common.Address, error) { + return _VRFCoordinator.Contract.SProducer(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SProducer() (common.Address, error) { + return _VRFCoordinator.Contract.SProducer(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "acceptOwnership") +} + +func (_VRFCoordinator *VRFCoordinatorSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptOwnership(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptOwnership(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) AcceptSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "acceptSubscriptionOwnerTransfer", subId) +} + +func (_VRFCoordinator *VRFCoordinatorSession) AcceptSubscriptionOwnerTransfer(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) AcceptSubscriptionOwnerTransfer(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) AddConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "addConsumer", subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorSession) AddConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AddConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) AddConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AddConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) BatchTransferLink(opts *bind.TransactOpts, recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "batchTransferLink", recipients, paymentsInJuels) +} + +func (_VRFCoordinator *VRFCoordinatorSession) BatchTransferLink(recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.BatchTransferLink(&_VRFCoordinator.TransactOpts, recipients, paymentsInJuels) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) BatchTransferLink(recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.BatchTransferLink(&_VRFCoordinator.TransactOpts, recipients, paymentsInJuels) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) CancelSubscription(opts *bind.TransactOpts, subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "cancelSubscription", subId, to) +} + +func (_VRFCoordinator *VRFCoordinatorSession) CancelSubscription(subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.CancelSubscription(&_VRFCoordinator.TransactOpts, subId, to) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) CancelSubscription(subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.CancelSubscription(&_VRFCoordinator.TransactOpts, subId, to) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) CreateSubscription(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "createSubscription") +} + +func (_VRFCoordinator *VRFCoordinatorSession) CreateSubscription() (*types.Transaction, error) { + return _VRFCoordinator.Contract.CreateSubscription(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) CreateSubscription() (*types.Transaction, error) { + return _VRFCoordinator.Contract.CreateSubscription(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) DeregisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "deregisterMigratableCoordinator", target) +} + +func (_VRFCoordinator *VRFCoordinatorSession) DeregisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.DeregisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) DeregisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.DeregisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) Migrate(opts *bind.TransactOpts, newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "migrate", newCoordinator, encodedRequest) +} + +func (_VRFCoordinator *VRFCoordinatorSession) Migrate(newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.Migrate(&_VRFCoordinator.TransactOpts, newCoordinator, encodedRequest) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) Migrate(newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.Migrate(&_VRFCoordinator.TransactOpts, newCoordinator, encodedRequest) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "onTokenTransfer", arg0, amount, data) +} + +func (_VRFCoordinator *VRFCoordinatorSession) OnTokenTransfer(arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.OnTokenTransfer(&_VRFCoordinator.TransactOpts, arg0, amount, data) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) OnTokenTransfer(arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.OnTokenTransfer(&_VRFCoordinator.TransactOpts, arg0, amount, data) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) ProcessVRFOutputs(opts *bind.TransactOpts, vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "processVRFOutputs", vrfOutputs, juelsPerFeeCoin, reasonableGasPrice, blockHeight) +} + +func (_VRFCoordinator *VRFCoordinatorSession) ProcessVRFOutputs(vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) { + return _VRFCoordinator.Contract.ProcessVRFOutputs(&_VRFCoordinator.TransactOpts, vrfOutputs, juelsPerFeeCoin, reasonableGasPrice, blockHeight) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) ProcessVRFOutputs(vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) { + return _VRFCoordinator.Contract.ProcessVRFOutputs(&_VRFCoordinator.TransactOpts, vrfOutputs, juelsPerFeeCoin, reasonableGasPrice, blockHeight) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "redeemRandomness", subID, requestID, arg2) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RedeemRandomness(subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RedeemRandomness(&_VRFCoordinator.TransactOpts, subID, requestID, arg2) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RedeemRandomness(subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RedeemRandomness(&_VRFCoordinator.TransactOpts, subID, requestID, arg2) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "registerMigratableCoordinator", target) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RegisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RegisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RegisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RegisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "removeConsumer", subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RemoveConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RemoveConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RemoveConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RemoveConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RequestRandomness(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "requestRandomness", subID, numWords, confDelay, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RequestRandomness(subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomness(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RequestRandomness(subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomness(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "requestRandomnessFulfillment", subID, numWords, confDelay, callbackGasLimit, arguments, arg5) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomnessFulfillment(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments, arg5) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomnessFulfillment(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments, arg5) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RequestSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "requestSubscriptionOwnerTransfer", subId, newOwner) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RequestSubscriptionOwnerTransfer(subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId, newOwner) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RequestSubscriptionOwnerTransfer(subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId, newOwner) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetCallbackConfig(opts *bind.TransactOpts, config VRFCoordinatorCallbackConfig) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setCallbackConfig", config) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetCallbackConfig(config VRFCoordinatorCallbackConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCallbackConfig(&_VRFCoordinator.TransactOpts, config) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetCallbackConfig(config VRFCoordinatorCallbackConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCallbackConfig(&_VRFCoordinator.TransactOpts, config) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetConfirmationDelays(opts *bind.TransactOpts, confDelays [8]*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setConfirmationDelays", confDelays) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetConfirmationDelays(confDelays [8]*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetConfirmationDelays(&_VRFCoordinator.TransactOpts, confDelays) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetConfirmationDelays(confDelays [8]*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetConfirmationDelays(&_VRFCoordinator.TransactOpts, confDelays) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetCoordinatorConfig(opts *bind.TransactOpts, coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setCoordinatorConfig", coordinatorConfig) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetCoordinatorConfig(coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCoordinatorConfig(&_VRFCoordinator.TransactOpts, coordinatorConfig) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetCoordinatorConfig(coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCoordinatorConfig(&_VRFCoordinator.TransactOpts, coordinatorConfig) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetPauseFlag(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setPauseFlag", pause) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetPauseFlag(pause bool) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetPauseFlag(&_VRFCoordinator.TransactOpts, pause) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetPauseFlag(pause bool) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetPauseFlag(&_VRFCoordinator.TransactOpts, pause) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetProducer(opts *bind.TransactOpts, producer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setProducer", producer) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetProducer(producer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetProducer(&_VRFCoordinator.TransactOpts, producer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetProducer(producer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetProducer(&_VRFCoordinator.TransactOpts, producer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) TransferLink(opts *bind.TransactOpts, recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "transferLink", recipient, juelsAmount) +} + +func (_VRFCoordinator *VRFCoordinatorSession) TransferLink(recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferLink(&_VRFCoordinator.TransactOpts, recipient, juelsAmount) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) TransferLink(recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferLink(&_VRFCoordinator.TransactOpts, recipient, juelsAmount) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "transferOwnership", to) +} + +func (_VRFCoordinator *VRFCoordinatorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferOwnership(&_VRFCoordinator.TransactOpts, to) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferOwnership(&_VRFCoordinator.TransactOpts, to) +} + +type VRFCoordinatorCallbackConfigSetIterator struct { + Event *VRFCoordinatorCallbackConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCallbackConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCallbackConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCallbackConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCallbackConfigSetIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCallbackConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCallbackConfigSet struct { + NewConfig VRFCoordinatorCallbackConfig + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCallbackConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCallbackConfigSetIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CallbackConfigSet") + if err != nil { + return nil, err + } + return &VRFCoordinatorCallbackConfigSetIterator{contract: _VRFCoordinator.contract, event: "CallbackConfigSet", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCallbackConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCallbackConfigSet) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CallbackConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCallbackConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CallbackConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCallbackConfigSet(log types.Log) (*VRFCoordinatorCallbackConfigSet, error) { + event := new(VRFCoordinatorCallbackConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CallbackConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorCoordinatorConfigSetIterator struct { + Event *VRFCoordinatorCoordinatorConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCoordinatorConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCoordinatorConfigSetIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCoordinatorConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCoordinatorConfigSet struct { + CoordinatorConfig VRFBeaconTypesCoordinatorConfig + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCoordinatorConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorConfigSetIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CoordinatorConfigSet") + if err != nil { + return nil, err + } + return &VRFCoordinatorCoordinatorConfigSetIterator{contract: _VRFCoordinator.contract, event: "CoordinatorConfigSet", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCoordinatorConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorConfigSet) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CoordinatorConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCoordinatorConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCoordinatorConfigSet(log types.Log) (*VRFCoordinatorCoordinatorConfigSet, error) { + event := new(VRFCoordinatorCoordinatorConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorCoordinatorDeregisteredIterator struct { + Event *VRFCoordinatorCoordinatorDeregistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCoordinatorDeregisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorDeregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorDeregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCoordinatorDeregisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCoordinatorDeregisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCoordinatorDeregistered struct { + CoordinatorAddress common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCoordinatorDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorDeregisteredIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CoordinatorDeregistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorCoordinatorDeregisteredIterator{contract: _VRFCoordinator.contract, event: "CoordinatorDeregistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCoordinatorDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorDeregistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CoordinatorDeregistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCoordinatorDeregistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorDeregistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCoordinatorDeregistered(log types.Log) (*VRFCoordinatorCoordinatorDeregistered, error) { + event := new(VRFCoordinatorCoordinatorDeregistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorDeregistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorCoordinatorRegisteredIterator struct { + Event *VRFCoordinatorCoordinatorRegistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCoordinatorRegisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCoordinatorRegisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCoordinatorRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCoordinatorRegistered struct { + CoordinatorAddress common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCoordinatorRegistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorRegisteredIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CoordinatorRegistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorCoordinatorRegisteredIterator{contract: _VRFCoordinator.contract, event: "CoordinatorRegistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCoordinatorRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorRegistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CoordinatorRegistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCoordinatorRegistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorRegistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCoordinatorRegistered(log types.Log) (*VRFCoordinatorCoordinatorRegistered, error) { + event := new(VRFCoordinatorCoordinatorRegistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorMigrationCompletedIterator struct { + Event *VRFCoordinatorMigrationCompleted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorMigrationCompletedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorMigrationCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorMigrationCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorMigrationCompletedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorMigrationCompletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorMigrationCompleted struct { + NewVersion uint8 + NewCoordinator common.Address + SubID *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterMigrationCompleted(opts *bind.FilterOpts, newVersion []uint8, subID []*big.Int) (*VRFCoordinatorMigrationCompletedIterator, error) { + + var newVersionRule []interface{} + for _, newVersionItem := range newVersion { + newVersionRule = append(newVersionRule, newVersionItem) + } + + var subIDRule []interface{} + for _, subIDItem := range subID { + subIDRule = append(subIDRule, subIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "MigrationCompleted", newVersionRule, subIDRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorMigrationCompletedIterator{contract: _VRFCoordinator.contract, event: "MigrationCompleted", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchMigrationCompleted(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorMigrationCompleted, newVersion []uint8, subID []*big.Int) (event.Subscription, error) { + + var newVersionRule []interface{} + for _, newVersionItem := range newVersion { + newVersionRule = append(newVersionRule, newVersionItem) + } + + var subIDRule []interface{} + for _, subIDItem := range subID { + subIDRule = append(subIDRule, subIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "MigrationCompleted", newVersionRule, subIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorMigrationCompleted) + if err := _VRFCoordinator.contract.UnpackLog(event, "MigrationCompleted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseMigrationCompleted(log types.Log) (*VRFCoordinatorMigrationCompleted, error) { + event := new(VRFCoordinatorMigrationCompleted) + if err := _VRFCoordinator.contract.UnpackLog(event, "MigrationCompleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorOutputsServedIterator struct { + Event *VRFCoordinatorOutputsServed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorOutputsServedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorOutputsServedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorOutputsServedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorOutputsServed struct { + RecentBlockHeight uint64 + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + OutputsServed []VRFBeaconTypesOutputServed + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterOutputsServed(opts *bind.FilterOpts) (*VRFCoordinatorOutputsServedIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return &VRFCoordinatorOutputsServedIterator{contract: _VRFCoordinator.contract, event: "OutputsServed", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOutputsServed) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorOutputsServed) + if err := _VRFCoordinator.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseOutputsServed(log types.Log) (*VRFCoordinatorOutputsServed, error) { + event := new(VRFCoordinatorOutputsServed) + if err := _VRFCoordinator.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorOwnershipTransferRequestedIterator struct { + Event *VRFCoordinatorOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorOwnershipTransferRequestedIterator{contract: _VRFCoordinator.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorOwnershipTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseOwnershipTransferRequested(log types.Log) (*VRFCoordinatorOwnershipTransferRequested, error) { + event := new(VRFCoordinatorOwnershipTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorOwnershipTransferredIterator struct { + Event *VRFCoordinatorOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorOwnershipTransferredIterator{contract: _VRFCoordinator.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorOwnershipTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorOwnershipTransferred, error) { + event := new(VRFCoordinatorOwnershipTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorPauseFlagChangedIterator struct { + Event *VRFCoordinatorPauseFlagChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorPauseFlagChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorPauseFlagChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorPauseFlagChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorPauseFlagChangedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorPauseFlagChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorPauseFlagChanged struct { + Paused bool + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterPauseFlagChanged(opts *bind.FilterOpts) (*VRFCoordinatorPauseFlagChangedIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "PauseFlagChanged") + if err != nil { + return nil, err + } + return &VRFCoordinatorPauseFlagChangedIterator{contract: _VRFCoordinator.contract, event: "PauseFlagChanged", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchPauseFlagChanged(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorPauseFlagChanged) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "PauseFlagChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorPauseFlagChanged) + if err := _VRFCoordinator.contract.UnpackLog(event, "PauseFlagChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParsePauseFlagChanged(log types.Log) (*VRFCoordinatorPauseFlagChanged, error) { + event := new(VRFCoordinatorPauseFlagChanged) + if err := _VRFCoordinator.contract.UnpackLog(event, "PauseFlagChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomWordsFulfilledIterator struct { + Event *VRFCoordinatorRandomWordsFulfilled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomWordsFulfilledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomWordsFulfilledIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomWordsFulfilledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomWordsFulfilled struct { + RequestIDs []*big.Int + SuccessfulFulfillment []byte + TruncatedErrorData [][]byte + SubBalances []*big.Int + SubIDs []*big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFCoordinatorRandomWordsFulfilledIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomWordsFulfilledIterator{contract: _VRFCoordinator.contract, event: "RandomWordsFulfilled", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomWordsFulfilled) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomWordsFulfilled) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomWordsFulfilled(log types.Log) (*VRFCoordinatorRandomWordsFulfilled, error) { + event := new(VRFCoordinatorRandomWordsFulfilled) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomnessFulfillmentRequestedIterator struct { + Event *VRFCoordinatorRandomnessFulfillmentRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomnessFulfillmentRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomnessFulfillmentRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomnessFulfillmentRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomnessFulfillmentRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + GasAllowance uint32 + GasPrice *big.Int + WeiPerUnitLink *big.Int + Arguments []byte + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessFulfillmentRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomnessFulfillmentRequestedIterator{contract: _VRFCoordinator.contract, event: "RandomnessFulfillmentRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomnessFulfillmentRequested(log types.Log) (*VRFCoordinatorRandomnessFulfillmentRequested, error) { + event := new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomnessRedeemedIterator struct { + Event *VRFCoordinatorRandomnessRedeemed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomnessRedeemedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomnessRedeemedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomnessRedeemedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomnessRedeemed struct { + RequestID *big.Int + Requester common.Address + SubID *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFCoordinatorRandomnessRedeemedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomnessRedeemedIterator{contract: _VRFCoordinator.contract, event: "RandomnessRedeemed", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomnessRedeemed) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomnessRedeemed(log types.Log) (*VRFCoordinatorRandomnessRedeemed, error) { + event := new(VRFCoordinatorRandomnessRedeemed) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomnessRequestedIterator struct { + Event *VRFCoordinatorRandomnessRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomnessRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomnessRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomnessRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomnessRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomnessRequestedIterator{contract: _VRFCoordinator.contract, event: "RandomnessRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomnessRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomnessRequested(log types.Log) (*VRFCoordinatorRandomnessRequested, error) { + event := new(VRFCoordinatorRandomnessRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionCanceledIterator struct { + Event *VRFCoordinatorSubscriptionCanceled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionCanceledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCanceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCanceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionCanceledIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionCanceledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionCanceled struct { + SubId *big.Int + To common.Address + Amount *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionCanceled(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionCanceledIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionCanceled", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionCanceledIterator{contract: _VRFCoordinator.contract, event: "SubscriptionCanceled", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionCanceled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCanceled, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionCanceled", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionCanceled) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCanceled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionCanceled(log types.Log) (*VRFCoordinatorSubscriptionCanceled, error) { + event := new(VRFCoordinatorSubscriptionCanceled) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCanceled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionConsumerAddedIterator struct { + Event *VRFCoordinatorSubscriptionConsumerAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionConsumerAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionConsumerAddedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionConsumerAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionConsumerAdded struct { + SubId *big.Int + Consumer common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionConsumerAdded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerAddedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionConsumerAdded", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionConsumerAddedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionConsumerAdded", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionConsumerAdded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerAdded, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionConsumerAdded", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionConsumerAdded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionConsumerAdded(log types.Log) (*VRFCoordinatorSubscriptionConsumerAdded, error) { + event := new(VRFCoordinatorSubscriptionConsumerAdded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionConsumerRemovedIterator struct { + Event *VRFCoordinatorSubscriptionConsumerRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionConsumerRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionConsumerRemovedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionConsumerRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionConsumerRemoved struct { + SubId *big.Int + Consumer common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionConsumerRemoved(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerRemovedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionConsumerRemoved", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionConsumerRemovedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionConsumerRemoved", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionConsumerRemoved(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerRemoved, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionConsumerRemoved", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionConsumerRemoved(log types.Log) (*VRFCoordinatorSubscriptionConsumerRemoved, error) { + event := new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionCreatedIterator struct { + Event *VRFCoordinatorSubscriptionCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionCreatedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionCreated struct { + SubId *big.Int + Owner common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionCreated(opts *bind.FilterOpts, subId []*big.Int, owner []common.Address) (*VRFCoordinatorSubscriptionCreatedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionCreated", subIdRule, ownerRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionCreatedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionCreated", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionCreated(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCreated, subId []*big.Int, owner []common.Address) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionCreated", subIdRule, ownerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionCreated) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionCreated(log types.Log) (*VRFCoordinatorSubscriptionCreated, error) { + event := new(VRFCoordinatorSubscriptionCreated) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionFundedIterator struct { + Event *VRFCoordinatorSubscriptionFunded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionFundedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionFunded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionFunded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionFundedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionFundedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionFunded struct { + SubId *big.Int + OldBalance *big.Int + NewBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionFunded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionFundedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionFunded", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionFundedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionFunded", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionFunded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionFunded, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionFunded", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionFunded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionFunded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionFunded(log types.Log) (*VRFCoordinatorSubscriptionFunded, error) { + event := new(VRFCoordinatorSubscriptionFunded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionFunded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionOwnerTransferRequestedIterator struct { + Event *VRFCoordinatorSubscriptionOwnerTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionOwnerTransferRequested struct { + SubId *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionOwnerTransferRequested(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferRequestedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionOwnerTransferRequested", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionOwnerTransferRequestedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionOwnerTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionOwnerTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferRequested, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionOwnerTransferRequested", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionOwnerTransferRequested(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferRequested, error) { + event := new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionOwnerTransferredIterator struct { + Event *VRFCoordinatorSubscriptionOwnerTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionOwnerTransferred struct { + SubId *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionOwnerTransferred(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferredIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionOwnerTransferred", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionOwnerTransferredIterator{contract: _VRFCoordinator.contract, event: "SubscriptionOwnerTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionOwnerTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferred, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionOwnerTransferred", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionOwnerTransferred(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferred, error) { + event := new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetSubscription struct { + Balance *big.Int + PendingFulfillments uint64 + Owner common.Address + Consumers []common.Address +} +type SCallbackConfig struct { + MaxCallbackGasLimit uint32 + MaxCallbackArgumentsLength uint32 +} +type SCoordinatorConfig struct { + UseReasonableGasPrice bool + ReentrancyLock bool + Paused bool + PremiumPercentage uint8 + UnusedGasPenaltyPercent uint8 + StalenessSeconds uint32 + RedeemableRequestGasOverhead uint32 + CallbackRequestGasOverhead uint32 + ReasonableGasPriceStalenessBlocks uint32 + FallbackWeiPerUnitLink *big.Int +} +type SPendingRequests struct { + SlotNumber uint32 + ConfirmationDelay *big.Int + NumWords uint16 + Requester common.Address +} + +func (_VRFCoordinator *VRFCoordinator) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _VRFCoordinator.abi.Events["CallbackConfigSet"].ID: + return _VRFCoordinator.ParseCallbackConfigSet(log) + case _VRFCoordinator.abi.Events["CoordinatorConfigSet"].ID: + return _VRFCoordinator.ParseCoordinatorConfigSet(log) + case _VRFCoordinator.abi.Events["CoordinatorDeregistered"].ID: + return _VRFCoordinator.ParseCoordinatorDeregistered(log) + case _VRFCoordinator.abi.Events["CoordinatorRegistered"].ID: + return _VRFCoordinator.ParseCoordinatorRegistered(log) + case _VRFCoordinator.abi.Events["MigrationCompleted"].ID: + return _VRFCoordinator.ParseMigrationCompleted(log) + case _VRFCoordinator.abi.Events["OutputsServed"].ID: + return _VRFCoordinator.ParseOutputsServed(log) + case _VRFCoordinator.abi.Events["OwnershipTransferRequested"].ID: + return _VRFCoordinator.ParseOwnershipTransferRequested(log) + case _VRFCoordinator.abi.Events["OwnershipTransferred"].ID: + return _VRFCoordinator.ParseOwnershipTransferred(log) + case _VRFCoordinator.abi.Events["PauseFlagChanged"].ID: + return _VRFCoordinator.ParsePauseFlagChanged(log) + case _VRFCoordinator.abi.Events["RandomWordsFulfilled"].ID: + return _VRFCoordinator.ParseRandomWordsFulfilled(log) + case _VRFCoordinator.abi.Events["RandomnessFulfillmentRequested"].ID: + return _VRFCoordinator.ParseRandomnessFulfillmentRequested(log) + case _VRFCoordinator.abi.Events["RandomnessRedeemed"].ID: + return _VRFCoordinator.ParseRandomnessRedeemed(log) + case _VRFCoordinator.abi.Events["RandomnessRequested"].ID: + return _VRFCoordinator.ParseRandomnessRequested(log) + case _VRFCoordinator.abi.Events["SubscriptionCanceled"].ID: + return _VRFCoordinator.ParseSubscriptionCanceled(log) + case _VRFCoordinator.abi.Events["SubscriptionConsumerAdded"].ID: + return _VRFCoordinator.ParseSubscriptionConsumerAdded(log) + case _VRFCoordinator.abi.Events["SubscriptionConsumerRemoved"].ID: + return _VRFCoordinator.ParseSubscriptionConsumerRemoved(log) + case _VRFCoordinator.abi.Events["SubscriptionCreated"].ID: + return _VRFCoordinator.ParseSubscriptionCreated(log) + case _VRFCoordinator.abi.Events["SubscriptionFunded"].ID: + return _VRFCoordinator.ParseSubscriptionFunded(log) + case _VRFCoordinator.abi.Events["SubscriptionOwnerTransferRequested"].ID: + return _VRFCoordinator.ParseSubscriptionOwnerTransferRequested(log) + case _VRFCoordinator.abi.Events["SubscriptionOwnerTransferred"].ID: + return _VRFCoordinator.ParseSubscriptionOwnerTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (VRFCoordinatorCallbackConfigSet) Topic() common.Hash { + return common.HexToHash("0x0cc54509a45ab33cd67614d4a2892c083ecf8fb43b9d29f6ea8130b9023e51df") +} + +func (VRFCoordinatorCoordinatorConfigSet) Topic() common.Hash { + return common.HexToHash("0x0028d3a46e95e67def989d41c66eb331add9809460b95b5fb4eb006157728fc5") +} + +func (VRFCoordinatorCoordinatorDeregistered) Topic() common.Hash { + return common.HexToHash("0xf80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af37") +} + +func (VRFCoordinatorCoordinatorRegistered) Topic() common.Hash { + return common.HexToHash("0xb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af01625") +} + +func (VRFCoordinatorMigrationCompleted) Topic() common.Hash { + return common.HexToHash("0xbd89b747474d3fc04664dfbd1d56ae7ffbe46ee097cdb9979c13916bb76269ce") +} + +func (VRFCoordinatorOutputsServed) Topic() common.Hash { + return common.HexToHash("0xf10ea936d00579b4c52035ee33bf46929646b3aa87554c565d8fb2c7aa549c44") +} + +func (VRFCoordinatorOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (VRFCoordinatorOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (VRFCoordinatorPauseFlagChanged) Topic() common.Hash { + return common.HexToHash("0x49ba7c1de2d8853088b6270e43df2118516b217f38b917dd2b80dea360860fbe") +} + +func (VRFCoordinatorRandomWordsFulfilled) Topic() common.Hash { + return common.HexToHash("0x8f79f730779e875ce76c428039cc2052b5b5918c2a55c598fab251c1198aec54") +} + +func (VRFCoordinatorRandomnessFulfillmentRequested) Topic() common.Hash { + return common.HexToHash("0x01872fb9c7d6d68af06a17347935e04412da302a377224c205e672c26e18c37f") +} + +func (VRFCoordinatorRandomnessRedeemed) Topic() common.Hash { + return common.HexToHash("0x16f3f633197fafab10a5df69e6f3f2f7f20092f08d8d47de0a91c0f4b96a1a25") +} + +func (VRFCoordinatorRandomnessRequested) Topic() common.Hash { + return common.HexToHash("0xb7933fba96b6b452eb44f99fdc08052a45dff82363d59abaff0456931c3d2459") +} + +func (VRFCoordinatorSubscriptionCanceled) Topic() common.Hash { + return common.HexToHash("0x3784f77e8e883de95b5d47cd713ced01229fa74d118c0a462224bcb0516d43f1") +} + +func (VRFCoordinatorSubscriptionConsumerAdded) Topic() common.Hash { + return common.HexToHash("0x1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e1") +} + +func (VRFCoordinatorSubscriptionConsumerRemoved) Topic() common.Hash { + return common.HexToHash("0x32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a7") +} + +func (VRFCoordinatorSubscriptionCreated) Topic() common.Hash { + return common.HexToHash("0x1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d") +} + +func (VRFCoordinatorSubscriptionFunded) Topic() common.Hash { + return common.HexToHash("0x1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a") +} + +func (VRFCoordinatorSubscriptionOwnerTransferRequested) Topic() common.Hash { + return common.HexToHash("0x21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a1") +} + +func (VRFCoordinatorSubscriptionOwnerTransferred) Topic() common.Hash { + return common.HexToHash("0xd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c9386") +} + +func (_VRFCoordinator *VRFCoordinator) Address() common.Address { + return _VRFCoordinator.address +} + +type VRFCoordinatorInterface interface { + MAXCONSUMERS(opts *bind.CallOpts) (uint16, error) + + MAXNUMWORDS(opts *bind.CallOpts) (*big.Int, error) + + NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) + + GetCallbackMemo(opts *bind.CallOpts, requestId *big.Int) ([32]byte, error) + + GetConfirmationDelays(opts *bind.CallOpts) ([8]*big.Int, error) + + GetFee(opts *bind.CallOpts, arg0 *big.Int, arg1 []byte) (*big.Int, error) + + GetFulfillmentFee(opts *bind.CallOpts, arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) + + GetSubscription(opts *bind.CallOpts, subId *big.Int) (GetSubscription, + + error) + + GetSubscriptionLinkBalance(opts *bind.CallOpts) (*big.Int, error) + + IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) + + ILink(opts *bind.CallOpts) (common.Address, error) + + MigrationVersion(opts *bind.CallOpts) (uint8, error) + + OnMigration(opts *bind.CallOpts, arg0 []byte) error + + Owner(opts *bind.CallOpts) (common.Address, error) + + SCallbackConfig(opts *bind.CallOpts) (SCallbackConfig, + + error) + + SCoordinatorConfig(opts *bind.CallOpts) (SCoordinatorConfig, + + error) + + SPendingRequests(opts *bind.CallOpts, arg0 *big.Int) (SPendingRequests, + + error) + + SProducer(opts *bind.CallOpts) (common.Address, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AcceptSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) + + AddConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) + + BatchTransferLink(opts *bind.TransactOpts, recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) + + CancelSubscription(opts *bind.TransactOpts, subId *big.Int, to common.Address) (*types.Transaction, error) + + CreateSubscription(opts *bind.TransactOpts) (*types.Transaction, error) + + DeregisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) + + Migrate(opts *bind.TransactOpts, newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) + + OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + ProcessVRFOutputs(opts *bind.TransactOpts, vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) + + RedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) + + RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) + + RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) + + RequestRandomness(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) + + RequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) + + RequestSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int, newOwner common.Address) (*types.Transaction, error) + + SetCallbackConfig(opts *bind.TransactOpts, config VRFCoordinatorCallbackConfig) (*types.Transaction, error) + + SetConfirmationDelays(opts *bind.TransactOpts, confDelays [8]*big.Int) (*types.Transaction, error) + + SetCoordinatorConfig(opts *bind.TransactOpts, coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) + + SetPauseFlag(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) + + SetProducer(opts *bind.TransactOpts, producer common.Address) (*types.Transaction, error) + + TransferLink(opts *bind.TransactOpts, recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCallbackConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCallbackConfigSetIterator, error) + + WatchCallbackConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCallbackConfigSet) (event.Subscription, error) + + ParseCallbackConfigSet(log types.Log) (*VRFCoordinatorCallbackConfigSet, error) + + FilterCoordinatorConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorConfigSetIterator, error) + + WatchCoordinatorConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorConfigSet) (event.Subscription, error) + + ParseCoordinatorConfigSet(log types.Log) (*VRFCoordinatorCoordinatorConfigSet, error) + + FilterCoordinatorDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorDeregisteredIterator, error) + + WatchCoordinatorDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorDeregistered) (event.Subscription, error) + + ParseCoordinatorDeregistered(log types.Log) (*VRFCoordinatorCoordinatorDeregistered, error) + + FilterCoordinatorRegistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorRegisteredIterator, error) + + WatchCoordinatorRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorRegistered) (event.Subscription, error) + + ParseCoordinatorRegistered(log types.Log) (*VRFCoordinatorCoordinatorRegistered, error) + + FilterMigrationCompleted(opts *bind.FilterOpts, newVersion []uint8, subID []*big.Int) (*VRFCoordinatorMigrationCompletedIterator, error) + + WatchMigrationCompleted(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorMigrationCompleted, newVersion []uint8, subID []*big.Int) (event.Subscription, error) + + ParseMigrationCompleted(log types.Log) (*VRFCoordinatorMigrationCompleted, error) + + FilterOutputsServed(opts *bind.FilterOpts) (*VRFCoordinatorOutputsServedIterator, error) + + WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOutputsServed) (event.Subscription, error) + + ParseOutputsServed(log types.Log) (*VRFCoordinatorOutputsServed, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*VRFCoordinatorOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorOwnershipTransferred, error) + + FilterPauseFlagChanged(opts *bind.FilterOpts) (*VRFCoordinatorPauseFlagChangedIterator, error) + + WatchPauseFlagChanged(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorPauseFlagChanged) (event.Subscription, error) + + ParsePauseFlagChanged(log types.Log) (*VRFCoordinatorPauseFlagChanged, error) + + FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFCoordinatorRandomWordsFulfilledIterator, error) + + WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomWordsFulfilled) (event.Subscription, error) + + ParseRandomWordsFulfilled(log types.Log) (*VRFCoordinatorRandomWordsFulfilled, error) + + FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessFulfillmentRequestedIterator, error) + + WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessFulfillmentRequested(log types.Log) (*VRFCoordinatorRandomnessFulfillmentRequested, error) + + FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFCoordinatorRandomnessRedeemedIterator, error) + + WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) + + ParseRandomnessRedeemed(log types.Log) (*VRFCoordinatorRandomnessRedeemed, error) + + FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessRequestedIterator, error) + + WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessRequested(log types.Log) (*VRFCoordinatorRandomnessRequested, error) + + FilterSubscriptionCanceled(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionCanceledIterator, error) + + WatchSubscriptionCanceled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCanceled, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionCanceled(log types.Log) (*VRFCoordinatorSubscriptionCanceled, error) + + FilterSubscriptionConsumerAdded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerAddedIterator, error) + + WatchSubscriptionConsumerAdded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerAdded, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionConsumerAdded(log types.Log) (*VRFCoordinatorSubscriptionConsumerAdded, error) + + FilterSubscriptionConsumerRemoved(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerRemovedIterator, error) + + WatchSubscriptionConsumerRemoved(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerRemoved, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionConsumerRemoved(log types.Log) (*VRFCoordinatorSubscriptionConsumerRemoved, error) + + FilterSubscriptionCreated(opts *bind.FilterOpts, subId []*big.Int, owner []common.Address) (*VRFCoordinatorSubscriptionCreatedIterator, error) + + WatchSubscriptionCreated(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCreated, subId []*big.Int, owner []common.Address) (event.Subscription, error) + + ParseSubscriptionCreated(log types.Log) (*VRFCoordinatorSubscriptionCreated, error) + + FilterSubscriptionFunded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionFundedIterator, error) + + WatchSubscriptionFunded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionFunded, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionFunded(log types.Log) (*VRFCoordinatorSubscriptionFunded, error) + + FilterSubscriptionOwnerTransferRequested(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferRequestedIterator, error) + + WatchSubscriptionOwnerTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferRequested, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionOwnerTransferRequested(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferRequested, error) + + FilterSubscriptionOwnerTransferred(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferredIterator, error) + + WatchSubscriptionOwnerTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferred, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionOwnerTransferred(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ocr2vrf/generation/generated-wrapper-dependency-versions-do-not-edit.txt new file mode 100644 index 00000000000..ce0b1a09702 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -0,0 +1,7 @@ +GETH_VERSION: 1.12.0 +dkg: ../../../contracts/solc/v0.8.19/DKG.abi ../../../contracts/solc/v0.8.19/DKG.bin 02549733c46e50ba393c2521e39d4ec55b6a5d9a66baf4406b1a515b20470425 +load_test_beacon_consumer: ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.bin 7306576bc1db6c0a4f0a8a83dd4c08e3078afa73b72858f7d1eaa410d1128fd2 +vrf_beacon: ../../../contracts/solc/v0.8.19/VRFBeacon.abi ../../../contracts/solc/v0.8.19/VRFBeacon.bin 63107992adf02024afccbe77fdf973777548dcd4d9af1484c8449aca6de30f4c +vrf_beacon_consumer: ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.bin 520f1c24e4d926a4eb6c9504506b55b79a35ae8cc65ee02d28309a7d5b735a53 +vrf_beacon_coordinator: ../../../contracts/solc/v0.8.15/VRFBeaconCoordinator.abi ../../../contracts/solc/v0.8.15/VRFBeaconCoordinator.bin 08da747a3488fcd318ddc0db75fd0df7c07a100b2e19061f0efcb12a7180ecde +vrf_coordinator: ../../../contracts/solc/v0.8.19/VRFCoordinator.abi ../../../contracts/solc/v0.8.19/VRFCoordinator.bin 295bec795ab8c1ef08b6b27a67bab7f06233660e8a2f389211e470cc2b58c5ea diff --git a/core/gethwrappers/ocr2vrf/go_generate.go b/core/gethwrappers/ocr2vrf/go_generate.go new file mode 100644 index 00000000000..475bf7e8f67 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/go_generate.go @@ -0,0 +1,10 @@ +// Package gethwrappers provides tools for wrapping solidity contracts with +// golang packages, using abigen. +package gethwrappers + +// OCR2VRF - remove the _disabled tag to run these locally. +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/DKG.abi ../../../contracts/solc/v0.8.19/DKG.bin DKG dkg +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/VRFCoordinator.abi ../../../contracts/solc/v0.8.19/VRFCoordinator.bin VRFCoordinator vrf_coordinator +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/VRFBeacon.abi ../../../contracts/solc/v0.8.19/VRFBeacon.bin VRFBeacon vrf_beacon +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.bin BeaconVRFConsumer vrf_beacon_consumer +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.bin LoadTestBeaconVRFConsumer load_test_beacon_consumer diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 8123439dafb..58cedbb96e1 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -181,11 +181,11 @@ type JobPipelineConfig interface { MaxSuccessfulRuns() uint64 } -func NewJobPipelineV2(t testing.TB, cfg pipeline.BridgeConfig, jpcfg JobPipelineConfig, dbCfg pg.QConfig, legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, keyStore keystore.Master, restrictedHTTPClient, unrestrictedHTTPClient *http.Client) JobPipelineV2TestHelper { +func NewJobPipelineV2(t testing.TB, cfg pipeline.BridgeConfig, jpcfg JobPipelineConfig, legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, keyStore keystore.Master, restrictedHTTPClient, unrestrictedHTTPClient *http.Client) JobPipelineV2TestHelper { lggr := logger.TestLogger(t) prm := pipeline.NewORM(db, lggr, jpcfg.MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jrm := job.NewORM(db, prm, btORM, keyStore, lggr, dbCfg) + jrm := job.NewORM(db, prm, btORM, keyStore, lggr) pr := pipeline.NewRunner(prm, btORM, jpcfg, cfg, legacyChains, keyStore.Eth(), keyStore.VRF(), lggr, restrictedHTTPClient, unrestrictedHTTPClient) return JobPipelineV2TestHelper{ prm, @@ -323,6 +323,8 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, db.Close()) }) + ds := sqlutil.WrapDataSource(db, lggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout)) + var ethClient evmclient.Client var externalInitiatorManager webhook.ExternalInitiatorManager externalInitiatorManager = &webhook.NullExternalInitiatorManager{} @@ -337,13 +339,13 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn default: switch flag { case UseRealExternalInitiatorManager: - externalInitiatorManager = webhook.NewExternalInitiatorManager(db, clhttptest.NewTestLocalOnlyHTTPClient(), lggr, cfg.Database()) + externalInitiatorManager = webhook.NewExternalInitiatorManager(ds, clhttptest.NewTestLocalOnlyHTTPClient()) } } } - keyStore := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + keyStore := keystore.NewInMemory(ds, utils.FastScryptParams, lggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), lggr.Named("Mailbox")) loopRegistry := plugins.NewLoopRegistry(lggr, nil) @@ -365,10 +367,10 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: mailMon, - SqlxDB: db, - DB: db, + DS: ds, }, - CSAETHKeystore: keyStore, + CSAETHKeystore: keyStore, + MercuryTransmitter: cfg.Mercury().Transmitter(), } if cfg.EVMEnabled() { @@ -392,8 +394,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn cosmosCfg := chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: db, - QConfig: cfg.Database(), + DS: ds, } initOps = append(initOps, chainlink.InitCosmos(testCtx, relayerFactory, cosmosCfg)) } @@ -420,8 +421,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn appInstance, err := chainlink.NewApplication(chainlink.ApplicationOpts{ Config: cfg, MailMon: mailMon, - SqlxDB: db, - DB: db, + DS: ds, KeyStore: keyStore, RelayerChainInteroperators: relayChainInterops, Logger: lggr, @@ -569,9 +569,10 @@ func (ta *TestApplication) Stop() error { } func (ta *TestApplication) MustSeedNewSession(email string) (id string) { + ctx := testutils.Context(ta.t) session := NewSession() ta.Logger.Infof("TestApplication creating session (id: %s, email: %s, last used: %s)", session.ID, email, session.LastUsed.String()) - err := ta.GetSqlxDB().Get(&id, `INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, $3, NOW()) RETURNING id`, session.ID, email, session.LastUsed) + err := ta.GetDB().GetContext(ctx, &id, `INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, $3, NOW()) RETURNING id`, session.ID, email, session.LastUsed) require.NoError(ta.t, err) return id } @@ -903,13 +904,14 @@ const ( // WaitForSpecErrorV2 polls until the passed in jobID has count number // of job spec errors. -func WaitForSpecErrorV2(t *testing.T, db *sqlx.DB, jobID int32, count int) []job.SpecError { +func WaitForSpecErrorV2(t *testing.T, ds sqlutil.DataSource, jobID int32, count int) []job.SpecError { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var jse []job.SpecError g.Eventually(func() []job.SpecError { - err := db.Select(&jse, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jobID) + err := ds.SelectContext(ctx, &jse, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jobID) assert.NoError(t, err) return jse }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.HaveLen(count)) @@ -930,7 +932,7 @@ func WaitForPipeline(t testing.TB, nodeID int, jobID int32, expectedPipelineRuns var pr []pipeline.Run gomega.NewWithT(t).Eventually(func() bool { - prs, _, err := jo.PipelineRuns(&jobID, 0, 1000) + prs, _, err := jo.PipelineRuns(testutils.Context(t), &jobID, 0, 1000) require.NoError(t, err) var matched []pipeline.Run @@ -964,13 +966,14 @@ func WaitForPipeline(t testing.TB, nodeID int, jobID int32, expectedPipelineRuns } // AssertPipelineRunsStays asserts that the number of pipeline runs for a particular job remains at the provided values -func AssertPipelineRunsStays(t testing.TB, pipelineSpecID int32, db *sqlx.DB, want int) []pipeline.Run { +func AssertPipelineRunsStays(t testing.TB, pipelineSpecID int32, db sqlutil.DataSource, want int) []pipeline.Run { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var prs []pipeline.Run g.Consistently(func() []pipeline.Run { - err := db.Select(&prs, `SELECT * FROM pipeline_runs WHERE pipeline_spec_id = $1`, pipelineSpecID) + err := db.SelectContext(ctx, &prs, `SELECT * FROM pipeline_runs WHERE pipeline_spec_id = $1`, pipelineSpecID) assert.NoError(t, err) return prs }, AssertNoActionTimeout, DBPollingInterval).Should(gomega.HaveLen(want)) @@ -1161,11 +1164,12 @@ func NewSession(optionalSessionID ...string) clsessions.Session { return session } -func AllExternalInitiators(t testing.TB, db *sqlx.DB) []bridges.ExternalInitiator { +func AllExternalInitiators(t testing.TB, ds sqlutil.DataSource) []bridges.ExternalInitiator { t.Helper() + ctx := testutils.Context(t) var all []bridges.ExternalInitiator - err := db.Select(&all, `SELECT * FROM external_initiators`) + err := ds.SelectContext(ctx, &all, `SELECT * FROM external_initiators`) require.NoError(t, err) return all } @@ -1518,35 +1522,38 @@ func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected testutils.AssertCount(t, ds, tableName, expected) } -func WaitForCount(t *testing.T, db *sqlx.DB, tableName string, want int64) { +func WaitForCount(t *testing.T, ds sqlutil.DataSource, tableName string, want int64) { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var count int64 var err error g.Eventually(func() int64 { - err = db.Get(&count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) + err = ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) assert.NoError(t, err) return count }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.Equal(want)) } -func AssertCountStays(t testing.TB, db *sqlx.DB, tableName string, want int64) { +func AssertCountStays(t testing.TB, ds sqlutil.DataSource, tableName string, want int64) { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var count int64 var err error g.Consistently(func() int64 { - err = db.Get(&count, fmt.Sprintf(`SELECT count(*) FROM %s`, tableName)) + err = ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s`, tableName)) assert.NoError(t, err) return count }, AssertNoActionTimeout, DBPollingInterval).Should(gomega.Equal(want)) } -func AssertRecordEventually(t *testing.T, db *sqlx.DB, model interface{}, stmt string, check func() bool) { +func AssertRecordEventually(t *testing.T, ds sqlutil.DataSource, model interface{}, stmt string, check func() bool) { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) g.Eventually(func() bool { - err := db.Get(model, stmt) + err := ds.GetContext(ctx, model, stmt) require.NoError(t, err, "unable to find record in DB") return check() }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.BeTrue()) diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index 43cf902ca8a..cd2fa9d9f63 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -98,9 +98,9 @@ func NewBridgeType(t testing.TB, opts BridgeOpts) (*bridges.BridgeTypeAuthentica // MustCreateBridge creates a bridge // Be careful not to specify a name here unless you ABSOLUTELY need to // This is because name is a unique index and identical names used across transactional tests will lock/deadlock -func MustCreateBridge(t testing.TB, db *sqlx.DB, opts BridgeOpts) (bta *bridges.BridgeTypeAuthentication, bt *bridges.BridgeType) { +func MustCreateBridge(t testing.TB, ds sqlutil.DataSource, opts BridgeOpts) (bta *bridges.BridgeTypeAuthentication, bt *bridges.BridgeType) { bta, bt = NewBridgeType(t, opts) - orm := bridges.NewORM(db) + orm := bridges.NewORM(ds) err := orm.CreateBridgeType(testutils.Context(t), bt) require.NoError(t, err) return bta, bt @@ -317,9 +317,9 @@ func MustGenerateRandomKeyState(_ testing.TB) ethkey.State { return ethkey.State{Address: NewEIP55Address()} } -func MustInsertHead(t *testing.T, db sqlutil.DataSource, number int64) evmtypes.Head { +func MustInsertHead(t *testing.T, ds sqlutil.DataSource, number int64) evmtypes.Head { h := evmtypes.NewHead(big.NewInt(number), evmutils.NewHash(), evmutils.NewHash(), 0, ubig.New(&FixtureChainID)) - horm := headtracker.NewORM(FixtureChainID, db) + horm := headtracker.NewORM(FixtureChainID, ds) err := horm.IdempotentInsertHead(testutils.Context(t), &h) require.NoError(t, err) @@ -347,8 +347,8 @@ func MustInsertV2JobSpec(t *testing.T, db *sqlx.DB, transmitterAddress common.Ad PipelineSpecID: pipelineSpec.ID, } - jorm := job.NewORM(db, nil, nil, nil, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - err = jorm.InsertJob(&jb) + jorm := job.NewORM(db, nil, nil, nil, logger.TestLogger(t)) + err = jorm.InsertJob(testutils.Context(t), &jb) require.NoError(t, err) return jb } @@ -404,8 +404,8 @@ func MustInsertKeeperJob(t *testing.T, db *sqlx.DB, korm *keeper.ORM, from evmty tlg := logger.TestLogger(t) prm := pipeline.NewORM(db, tlg, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jrm := job.NewORM(db, prm, btORM, nil, tlg, cfg.Database()) - err = jrm.InsertJob(&jb) + jrm := job.NewORM(db, prm, btORM, nil, tlg) + err = jrm.InsertJob(testutils.Context(t), &jb) require.NoError(t, err) jb.PipelineSpec.JobID = jb.ID return jb diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go index d78440838b2..6ba13f97726 100644 --- a/core/internal/cltest/job_factories.go +++ b/core/internal/cltest/job_factories.go @@ -7,8 +7,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -43,30 +42,30 @@ func MinimalOCRNonBootstrapSpec(contractAddress, transmitterAddress types.EIP55A return fmt.Sprintf(minimalOCRNonBootstrapTemplate, contractAddress, peerID, transmitterAddress.Hex(), keyBundleID) } -func MustInsertWebhookSpec(t *testing.T, db *sqlx.DB) (job.Job, job.WebhookSpec) { +func MustInsertWebhookSpec(t *testing.T, ds sqlutil.DataSource) (job.Job, job.WebhookSpec) { ctx := testutils.Context(t) - jobORM, pipelineORM := getORMs(t, db) + jobORM, pipelineORM := getORMs(t, ds) webhookSpec := job.WebhookSpec{} - require.NoError(t, jobORM.InsertWebhookSpec(&webhookSpec)) + require.NoError(t, jobORM.InsertWebhookSpec(ctx, &webhookSpec)) pSpec := pipeline.Pipeline{} - pipelineSpecID, err := pipelineORM.CreateSpec(ctx, nil, pSpec, 0) + pipelineSpecID, err := pipelineORM.CreateSpec(ctx, pSpec, 0) require.NoError(t, err) createdJob := job.Job{WebhookSpecID: &webhookSpec.ID, WebhookSpec: &webhookSpec, SchemaVersion: 1, Type: "webhook", ExternalJobID: uuid.New(), PipelineSpecID: pipelineSpecID} - require.NoError(t, jobORM.InsertJob(&createdJob)) + require.NoError(t, jobORM.InsertJob(ctx, &createdJob)) return createdJob, webhookSpec } -func getORMs(t *testing.T, db *sqlx.DB) (jobORM job.ORM, pipelineORM pipeline.ORM) { +func getORMs(t *testing.T, ds sqlutil.DataSource) (jobORM job.ORM, pipelineORM pipeline.ORM) { config := configtest.NewTestGeneralConfig(t) - keyStore := NewKeyStore(t, db) + keyStore := NewKeyStore(t, ds) lggr := logger.TestLogger(t) - pipelineORM = pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) - bridgeORM := bridges.NewORM(db) - jobORM = job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, config.Database()) + pipelineORM = pipeline.NewORM(ds, lggr, config.JobPipeline().MaxSuccessfulRuns()) + bridgeORM := bridges.NewORM(ds) + jobORM = job.NewORM(ds, pipelineORM, bridgeORM, keyStore, lggr) t.Cleanup(func() { jobORM.Close() }) return } diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 75ff98d05be..26e7d5eae56 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -82,6 +82,7 @@ var oneETH = assets.Eth(*big.NewInt(1000000000000000000)) func TestIntegration_ExternalInitiatorV2(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -175,7 +176,7 @@ func TestIntegration_ExternalInitiatorV2(t *testing.T) { require.NoError(t, err) })) u, _ := url.Parse(bridgeServer.URL) - err := app.BridgeORM().CreateBridgeType(testutils.Context(t), &bridges.BridgeType{ + err := app.BridgeORM().CreateBridgeType(ctx, &bridges.BridgeType{ Name: bridges.BridgeName("substrate-adapter1"), URL: models.WebURL(*u), }) @@ -205,7 +206,7 @@ observationSource = """ """ `, jobUUID, eiName, cltest.MustJSONMarshal(t, eiSpec)) - _, err := webhook.ValidatedWebhookSpec(tomlSpec, app.GetExternalInitiatorManager()) + _, err := webhook.ValidatedWebhookSpec(ctx, tomlSpec, app.GetExternalInitiatorManager()) require.NoError(t, err) job := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) jobID = job.ID @@ -227,7 +228,7 @@ observationSource = """ defer cleanup() cltest.AssertServerResponse(t, resp, 401) - cltest.AssertCountStays(t, app.GetSqlxDB(), "pipeline_runs", 0) + cltest.AssertCountStays(t, app.GetDB(), "pipeline_runs", 0) }) t.Run("calling webhook_spec with matching external_initiator_id works", func(t *testing.T) { @@ -236,9 +237,9 @@ observationSource = """ _ = cltest.CreateJobRunViaExternalInitiatorV2(t, app, jobUUID, *eia, cltest.MustJSONMarshal(t, eiRequest)) - pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - bridgeORM := bridges.NewORM(app.GetSqlxDB()) - jobORM := job.NewORM(app.GetSqlxDB(), pipelineORM, bridgeORM, app.KeyStore, logger.TestLogger(t), cfg.Database()) + pipelineORM := pipeline.NewORM(app.GetDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) + bridgeORM := bridges.NewORM(app.GetDB()) + jobORM := job.NewORM(app.GetDB(), pipelineORM, bridgeORM, app.KeyStore, logger.TestLogger(t)) runs := cltest.WaitForPipelineComplete(t, 0, jobID, 1, 2, jobORM, 5*time.Second, 300*time.Millisecond) require.Len(t, runs, 1) @@ -992,8 +993,9 @@ observationSource = """ return answer.String() }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal("20")) + ctx := testutils.Context(t) for _, app := range apps { - jobs, _, err := app.JobORM().FindJobs(0, 1000) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) // No spec errors for _, j := range jobs { @@ -1220,8 +1222,9 @@ observationSource = """ return answer.String() }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal("20")) + ctx := testutils.Context(t) for _, app := range apps { - jobs, _, err := app.JobORM().FindJobs(0, 1000) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) // No spec errors for _, j := range jobs { diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index 07e0fc21d9a..fab9d34b4b1 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -519,6 +519,7 @@ updateInterval = "1m" } }() + ctx := testutils.Context(t) for trial := 0; trial < 2; trial++ { var retVal int @@ -537,7 +538,7 @@ updateInterval = "1m" wg.Add(1) go func() { defer wg.Done() - completedRuns, err2 := apps[ic].JobORM().FindPipelineRunIDsByJobID(jids[ic], 0, 1000) + completedRuns, err2 := apps[ic].JobORM().FindPipelineRunIDsByJobID(ctx, jids[ic], 0, 1000) require.NoError(t, err2) // Want at least 2 runs so we see all the metadata. pr := cltest.WaitForPipelineComplete(t, ic, jids[ic], len(completedRuns)+2, 7, apps[ic].JobORM(), 2*time.Minute, 5*time.Second) @@ -558,7 +559,7 @@ updateInterval = "1m" }, 1*time.Minute, 200*time.Millisecond).Should(gomega.Equal(fmt.Sprintf("%d", 2*retVal))) for _, app := range apps { - jobs, _, err2 := app.JobORM().FindJobs(0, 1000) + jobs, _, err2 := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err2) // No spec errors for _, j := range jobs { @@ -758,6 +759,7 @@ chainID = 1337 expectedMeta := map[string]struct{}{ "0": {}, "10": {}, "20": {}, "30": {}, } + ctx := testutils.Context(t) for i := 0; i < 4; i++ { s := i require.NoError(t, apps[i].Start(testutils.Context(t))) @@ -790,7 +792,7 @@ chainID = 1337 servers[s].Close() }) u, _ := url.Parse(servers[i].URL) - require.NoError(t, apps[i].BridgeORM().CreateBridgeType(testutils.Context(t), &bridges.BridgeType{ + require.NoError(t, apps[i].BridgeORM().CreateBridgeType(ctx, &bridges.BridgeType{ Name: bridges.BridgeName(fmt.Sprintf("bridge%d", i)), URL: models.WebURL(*u), })) @@ -882,7 +884,7 @@ updateInterval = "1m" }, 1*time.Minute, 200*time.Millisecond).Should(gomega.Equal("20")) for _, app := range apps { - jobs, _, err := app.JobORM().FindJobs(0, 1000) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) // No spec errors for _, j := range jobs { diff --git a/core/internal/mocks/application.go b/core/internal/mocks/application.go index 2438eb302c0..f845d46ca8d 100644 --- a/core/internal/mocks/application.go +++ b/core/internal/mocks/application.go @@ -23,6 +23,8 @@ import ( logger "github.com/smartcontractkit/chainlink/v2/core/logger" + logpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + mock "github.com/stretchr/testify/mock" pipeline "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" @@ -35,8 +37,6 @@ import ( sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - sqlx "github.com/jmoiron/sqlx" - txmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -149,6 +149,24 @@ func (_m *Application) DeleteJob(ctx context.Context, jobID int32) error { return r0 } +// DeleteLogPollerDataAfter provides a mock function with given fields: ctx, chainID, start +func (_m *Application) DeleteLogPollerDataAfter(ctx context.Context, chainID *big.Int, start int64) error { + ret := _m.Called(ctx, chainID, start) + + if len(ret) == 0 { + panic("no return value specified for DeleteLogPollerDataAfter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, int64) error); ok { + r0 = rf(ctx, chainID, start) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // EVMORM provides a mock function with given fields: func (_m *Application) EVMORM() types.Configs { ret := _m.Called() @@ -169,6 +187,36 @@ func (_m *Application) EVMORM() types.Configs { return r0 } +// FindLCA provides a mock function with given fields: ctx, chainID +func (_m *Application) FindLCA(ctx context.Context, chainID *big.Int) (*logpoller.LogPollerBlock, error) { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for FindLCA") + } + + var r0 *logpoller.LogPollerBlock + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*logpoller.LogPollerBlock, error)); ok { + return rf(ctx, chainID) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *logpoller.LogPollerBlock); ok { + r0 = rf(ctx, chainID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logpoller.LogPollerBlock) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetAuditLogger provides a mock function with given fields: func (_m *Application) GetAuditLogger() audit.AuditLogger { ret := _m.Called() @@ -389,26 +437,6 @@ func (_m *Application) GetRelayers() chainlink.RelayerChainInteroperators { return r0 } -// GetSqlxDB provides a mock function with given fields: -func (_m *Application) GetSqlxDB() *sqlx.DB { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetSqlxDB") - } - - var r0 *sqlx.DB - if rf, ok := ret.Get(0).(func() *sqlx.DB); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*sqlx.DB) - } - } - - return r0 -} - // GetWebAuthnConfiguration provides a mock function with given fields: func (_m *Application) GetWebAuthnConfiguration() sessions.WebAuthnConfiguration { ret := _m.Called() diff --git a/core/internal/mocks/go_generate.go b/core/internal/mocks/go_generate.go index 8402f71158d..f3f5f0ae2ca 100644 --- a/core/internal/mocks/go_generate.go +++ b/core/internal/mocks/go_generate.go @@ -4,5 +4,5 @@ package mocks //go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper --name FlagsInterface --output . --case=underscore --structname Flags --filename flags.go //go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface --name AggregatorV3InterfaceInterface --output ../../services/vrf/mocks/ --case=underscore --structname AggregatorV3Interface --filename aggregator_v3_interface.go //go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2 --name VRFCoordinatorV2Interface --output ../../services/vrf/mocks/ --case=underscore --structname VRFCoordinatorV2Interface --filename vrf_coordinator_v2.go -//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon --name VRFBeaconInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFBeaconInterface --filename vrf_beacon.go -//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator --name VRFCoordinatorInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFCoordinatorInterface --filename vrf_coordinator.go +//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon --name VRFBeaconInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFBeaconInterface --filename vrf_beacon.go +//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator --name VRFCoordinatorInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFCoordinatorInterface --filename vrf_coordinator.go diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index eedc6275928..276dea2ac5d 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -9,13 +9,13 @@ import ( "testing" "github.com/ethereum/go-ethereum" - "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" @@ -62,7 +62,7 @@ type TestChainOpts struct { LogPoller logpoller.LogPoller GeneralConfig legacyevm.AppConfig HeadTracker httypes.HeadTracker - DB *sqlx.DB + DB sqlutil.DataSource TxManager txmgr.TxManager KeyStore keystore.Eth MailMon *mailbox.Monitor @@ -88,8 +88,7 @@ func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainR AppConfig: testopts.GeneralConfig, MailMon: testopts.MailMon, GasEstimator: testopts.GasEstimator, - SqlxDB: testopts.DB, - DB: testopts.DB, + DS: testopts.DB, }, } opts.GenEthClient = func(*big.Int) evmclient.Client { diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index 686483f2d41..8464604b667 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -1,7 +1,6 @@ package pgtest import ( - "database/sql" "testing" "github.com/google/uuid" @@ -10,25 +9,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) -func NewQConfig(logSQL bool) pg.QConfig { - return pg.NewQConfig(logSQL) -} - -func NewSqlDB(t *testing.T) *sql.DB { - testutils.SkipShortDB(t) - db, err := sql.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) - require.NoError(t, err) - t.Cleanup(func() { assert.NoError(t, db.Close()) }) - - return db -} - func NewSqlxDB(t testing.TB) *sqlx.DB { testutils.SkipShortDB(t) db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) @@ -39,12 +25,9 @@ func NewSqlxDB(t testing.TB) *sqlx.DB { return db } -func MustExec(t *testing.T, db *sqlx.DB, stmt string, args ...interface{}) { - require.NoError(t, utils.JustError(db.Exec(stmt, args...))) -} - -func MustSelect(t *testing.T, db *sqlx.DB, dest interface{}, stmt string, args ...interface{}) { - require.NoError(t, db.Select(dest, stmt, args...)) +func MustExec(t *testing.T, ds sqlutil.DataSource, stmt string, args ...interface{}) { + ctx := testutils.Context(t) + require.NoError(t, utils.JustError(ds.ExecContext(ctx, stmt, args...))) } func MustCount(t *testing.T, db *sqlx.DB, stmt string, args ...interface{}) (cnt int) { diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index ba7e697fb62..f4867eda69a 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -420,8 +420,9 @@ func SkipShortDB(tb testing.TB) { func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected int64) { t.Helper() + ctx := Context(t) var count int64 - err := ds.GetContext(Context(t), &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) + err := ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) require.NoError(t, err) require.Equal(t, expected, count) } diff --git a/core/scripts/gateway/run_gateway.go b/core/scripts/gateway/run_gateway.go index 5dbcd02bf56..2daca5190a5 100644 --- a/core/scripts/gateway/run_gateway.go +++ b/core/scripts/gateway/run_gateway.go @@ -48,7 +48,7 @@ func main() { lggr, _ := logger.NewLogger() - handlerFactory := gateway.NewHandlerFactory(nil, nil, nil, lggr) + handlerFactory := gateway.NewHandlerFactory(nil, nil, lggr) gw, err := gateway.NewGatewayFromConfig(&cfg, handlerFactory, lggr) if err != nil { fmt.Println("error creating Gateway object:", err) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 5be5d137696..08050c32167 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -21,7 +21,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c @@ -256,7 +256,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index b26bad1299e..48a66de1ec3 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1185,10 +1185,10 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= diff --git a/core/scripts/ocr2vrf/util.go b/core/scripts/ocr2vrf/util.go index a11c799d9a3..e57f349f1fd 100644 --- a/core/scripts/ocr2vrf/util.go +++ b/core/scripts/ocr2vrf/util.go @@ -27,15 +27,15 @@ import ( "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" - dkgContract "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/load_test_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + dkgContract "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" ) diff --git a/core/scripts/ocr2vrf/verify.go b/core/scripts/ocr2vrf/verify.go index 36ecda83b5a..7d7fb94496a 100644 --- a/core/scripts/ocr2vrf/verify.go +++ b/core/scripts/ocr2vrf/verify.go @@ -16,10 +16,10 @@ import ( "github.com/smartcontractkit/chainlink-vrf/altbn_128" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" - dkgContract "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + dkgContract "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) func getDKGLatestConfigDetails(e helpers.Environment, dkgAddress string) dkgContract.LatestConfigDetails { diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 88a6fadf345..ae3db2e7a73 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -16,15 +16,15 @@ import ( "go.uber.org/multierr" "go.uber.org/zap/zapcore" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -51,9 +51,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" externalp2p "github.com/smartcontractkit/chainlink/v2/core/services/p2p/wrapper" "github.com/smartcontractkit/chainlink/v2/core/services/periodicbackup" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/promreporter" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" @@ -78,7 +78,6 @@ type Application interface { GetLogger() logger.SugaredLogger GetAuditLogger() audit.AuditLogger GetHealthChecker() services.Checker - GetSqlxDB() *sqlx.DB // Deprecated: use GetDB GetDB() sqlutil.DataSource GetConfig() GeneralConfig SetLogLevel(lvl zapcore.Level) error @@ -118,6 +117,11 @@ type Application interface { ID() uuid.UUID SecretGenerator() SecretGenerator + + // FindLCA - finds last common ancestor for LogPoller's chain available in the database and RPC chain + FindLCA(ctx context.Context, chainID *big.Int) (*logpoller.LogPollerBlock, error) + // DeleteLogPollerDataAfter - delete LogPoller state starting from the specified block + DeleteLogPollerDataAfter(ctx context.Context, chainID *big.Int, start int64) error } // ChainlinkApplication contains fields for the JobSubscriber, Scheduler, @@ -146,8 +150,7 @@ type ChainlinkApplication struct { logger logger.SugaredLogger AuditLogger audit.AuditLogger closeLogger func() error - sqlxDB *sqlx.DB // Deprecated: use db instead - db sqlutil.DataSource + ds sqlutil.DataSource secretGenerator SecretGenerator profiler *pyroscope.Profiler loopRegistry *plugins.LoopRegistry @@ -161,8 +164,7 @@ type ApplicationOpts struct { Config GeneralConfig Logger logger.Logger MailMon *mailbox.Monitor - SqlxDB *sqlx.DB // Deprecated: use DB instead - DB sqlutil.DataSource + DS sqlutil.DataSource KeyStore keystore.Master RelayerChainInteroperators *CoreRelayerChainInteroperators AuditLogger audit.AuditLogger @@ -185,7 +187,6 @@ type ApplicationOpts struct { func NewApplication(opts ApplicationOpts) (Application, error) { var srvcs []services.ServiceCtx auditLogger := opts.AuditLogger - sqlxDB := opts.SqlxDB cfg := opts.Config relayerChainInterops := opts.RelayerChainInteroperators mailMon := opts.MailMon @@ -196,9 +197,12 @@ func NewApplication(opts ApplicationOpts) (Application, error) { unrestrictedHTTPClient := opts.UnrestrictedHTTPClient registry := capabilities.NewRegistry(globalLogger) + var externalPeerWrapper p2ptypes.PeerWrapper if cfg.Capabilities().Peering().Enabled() { - externalPeerWrapper := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), globalLogger) - signer := externalPeerWrapper + externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), globalLogger) + signer := externalPeer + externalPeerWrapper = externalPeer + srvcs = append(srvcs, externalPeerWrapper) // NOTE: RegistrySyncer will depend on a Relayer when fully implemented @@ -277,12 +281,12 @@ func NewApplication(opts ApplicationOpts) (Application, error) { srvcs = append(srvcs, mailMon) srvcs = append(srvcs, relayerChainInterops.Services()...) - promReporter := promreporter.NewPromReporter(sqlxDB.DB, legacyEVMChains, globalLogger) + promReporter := promreporter.NewPromReporter(opts.DS, legacyEVMChains, globalLogger) srvcs = append(srvcs, promReporter) // Initialize Local Users ORM and Authentication Provider specified in config // BasicAdminUsersORM is initialized and required regardless of separate Authentication Provider - localAdminUsersORM := localauth.NewORM(opts.DB, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) + localAdminUsersORM := localauth.NewORM(opts.DS, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) // Initialize Sessions ORM based on environment configured authenticator // localDB auth or remote LDAP auth @@ -294,26 +298,26 @@ func NewApplication(opts ApplicationOpts) (Application, error) { case sessions.LDAPAuth: var err error authenticationProvider, err = ldapauth.NewLDAPAuthenticator( - opts.DB, cfg.WebServer().LDAP(), cfg.Insecure().DevWebServer(), globalLogger, auditLogger, + opts.DS, cfg.WebServer().LDAP(), cfg.Insecure().DevWebServer(), globalLogger, auditLogger, ) if err != nil { return nil, errors.Wrap(err, "NewApplication: failed to initialize LDAP Authentication module") } - sessionReaper = ldapauth.NewLDAPServerStateSync(sqlxDB, cfg.Database(), cfg.WebServer().LDAP(), globalLogger) + sessionReaper = ldapauth.NewLDAPServerStateSync(opts.DS, cfg.WebServer().LDAP(), globalLogger) case sessions.LocalAuth: - authenticationProvider = localauth.NewORM(opts.DB, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) - sessionReaper = localauth.NewSessionReaper(sqlxDB.DB, cfg.WebServer(), globalLogger) + authenticationProvider = localauth.NewORM(opts.DS, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) + sessionReaper = localauth.NewSessionReaper(opts.DS, cfg.WebServer(), globalLogger) default: return nil, errors.Errorf("NewApplication: Unexpected 'AuthenticationMethod': %s supported values: %s, %s", authMethod, sessions.LocalAuth, sessions.LDAPAuth) } var ( - pipelineORM = pipeline.NewORM(sqlxDB, globalLogger, cfg.JobPipeline().MaxSuccessfulRuns()) - bridgeORM = bridges.NewORM(sqlxDB) - mercuryORM = mercury.NewORM(opts.DB) + pipelineORM = pipeline.NewORM(opts.DS, globalLogger, cfg.JobPipeline().MaxSuccessfulRuns()) + bridgeORM = bridges.NewORM(opts.DS) + mercuryORM = mercury.NewORM(opts.DS) pipelineRunner = pipeline.NewRunner(pipelineORM, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyEVMChains, keyStore.Eth(), keyStore.VRF(), globalLogger, restrictedHTTPClient, unrestrictedHTTPClient) - jobORM = job.NewORM(sqlxDB, pipelineORM, bridgeORM, keyStore, globalLogger, cfg.Database()) - txmORM = txmgr.NewTxStore(opts.DB, globalLogger) + jobORM = job.NewORM(opts.DS, pipelineORM, bridgeORM, keyStore, globalLogger) + txmORM = txmgr.NewTxStore(opts.DS, globalLogger) streamRegistry = streams.NewRegistry(globalLogger, pipelineRunner) ) @@ -334,14 +338,14 @@ func NewApplication(opts ApplicationOpts) (Application, error) { mailMon), job.Keeper: keeper.NewDelegate( cfg, - sqlxDB, + opts.DS, jobORM, pipelineRunner, globalLogger, legacyEVMChains, mailMon), job.VRF: vrf.NewDelegate( - sqlxDB, + opts.DS, keyStore, pipelineRunner, pipelineORM, @@ -368,23 +372,32 @@ func NewApplication(opts ApplicationOpts) (Application, error) { job.Gateway: gateway.NewDelegate( legacyEVMChains, keyStore.Eth(), - sqlxDB, - cfg.Database(), + opts.DS, globalLogger), job.Stream: streams.NewDelegate( globalLogger, streamRegistry, pipelineRunner, - cfg.JobPipeline()), - job.Workflow: workflows.NewDelegate( - globalLogger, - registry, - legacyEVMChains, + cfg.JobPipeline(), ), } webhookJobRunner = delegates[job.Webhook].(*webhook.Delegate).WebhookJobRunner() ) + delegates[job.Workflow] = workflows.NewDelegate( + globalLogger, + registry, + legacyEVMChains, + func() *p2ptypes.PeerID { + if externalPeerWrapper == nil { + return nil + } + + peerID := externalPeerWrapper.GetPeer().ID() + return &peerID + }, + ) + // Flux monitor requires ethereum just to boot, silence errors with a null delegate if !cfg.EVMRPCEnabled() { delegates[job.FluxMonitor] = &job.NullDelegate{Type: job.FluxMonitor} @@ -395,7 +408,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { jobORM, pipelineORM, pipelineRunner, - sqlxDB, + opts.DS, legacyEVMChains, globalLogger, ) @@ -408,7 +421,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { if err := ocrcommon.ValidatePeerWrapperConfig(cfg.P2P()); err != nil { return nil, err } - peerWrapper = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), sqlxDB, globalLogger) + peerWrapper = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), opts.DS, globalLogger) srvcs = append(srvcs, peerWrapper) } else { return nil, fmt.Errorf("P2P stack required for OCR or OCR2") @@ -416,7 +429,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { if cfg.OCR().Enabled() { delegates[job.OffchainReporting] = ocr.NewDelegate( - sqlxDB, + opts.DS, jobORM, keyStore, pipelineRunner, @@ -436,11 +449,10 @@ func NewApplication(opts ApplicationOpts) (Application, error) { if cfg.OCR2().Enabled() { globalLogger.Debug("Off-chain reporting v2 enabled") - ocr2DelegateConfig := ocr2.NewDelegateConfig(cfg.OCR2(), cfg.Mercury(), cfg.Threshold(), cfg.Insecure(), cfg.JobPipeline(), cfg.Database(), loopRegistrarConfig) + ocr2DelegateConfig := ocr2.NewDelegateConfig(cfg.OCR2(), cfg.Mercury(), cfg.Threshold(), cfg.Insecure(), cfg.JobPipeline(), loopRegistrarConfig) delegates[job.OffchainReporting2] = ocr2.NewDelegate( - sqlxDB, - opts.DB, + opts.DS, jobORM, bridgeORM, mercuryORM, @@ -460,7 +472,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { registry, ) delegates[job.Bootstrap] = ocrbootstrap.NewDelegateBootstrap( - sqlxDB, + opts.DS, jobORM, peerWrapper, globalLogger, @@ -478,7 +490,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { for _, c := range legacyEVMChains.Slice() { lbs = append(lbs, c.LogBroadcaster()) } - jobSpawner := job.NewSpawner(jobORM, cfg.Database(), healthChecker, delegates, sqlxDB, globalLogger, lbs) + jobSpawner := job.NewSpawner(jobORM, cfg.Database(), healthChecker, delegates, globalLogger, lbs) srvcs = append(srvcs, jobSpawner, pipelineRunner) // We start the log poller after the job spawner @@ -491,11 +503,11 @@ func NewApplication(opts ApplicationOpts) (Application, error) { var feedsService feeds.Service if cfg.Feature().FeedsManager() { - feedsORM := feeds.NewORM(sqlxDB, opts.Logger, cfg.Database()) + feedsORM := feeds.NewORM(opts.DS) feedsService = feeds.NewService( feedsORM, jobORM, - sqlxDB, + opts.DS, jobSpawner, keyStore, cfg, @@ -503,7 +515,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { cfg.JobPipeline(), cfg.OCR(), cfg.OCR2(), - cfg.Database(), legacyEVMChains, globalLogger, opts.Version, @@ -548,8 +559,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { loopRegistry: loopRegistry, loopRegistrarConfig: loopRegistrarConfig, - sqlxDB: opts.SqlxDB, - db: opts.DB, + ds: opts.DS, // NOTE: Can keep things clean by putting more things in srvcs instead of manually start/closing srvcs: srvcs, @@ -742,7 +752,7 @@ func (app *ChainlinkApplication) WakeSessionReaper() { } func (app *ChainlinkApplication) AddJobV2(ctx context.Context, j *job.Job) error { - return app.jobSpawner.CreateJob(j, pg.WithParentCtx(ctx)) + return app.jobSpawner.CreateJob(ctx, nil, j) } func (app *ChainlinkApplication) DeleteJob(ctx context.Context, jobID int32) error { @@ -756,7 +766,7 @@ func (app *ChainlinkApplication) DeleteJob(ctx context.Context, jobID int32) err return errors.New("job must be deleted in the feeds manager") } - return app.jobSpawner.DeleteJob(jobID, pg.WithParentCtx(ctx)) + return app.jobSpawner.DeleteJob(ctx, nil, jobID) } func (app *ChainlinkApplication) RunWebhookJobV2(ctx context.Context, jobUUID uuid.UUID, requestBody string, meta jsonserializable.JSONSerializable) (int64, error) { @@ -857,12 +867,8 @@ func (app *ChainlinkApplication) GetRelayers() RelayerChainInteroperators { return app.relayers } -func (app *ChainlinkApplication) GetSqlxDB() *sqlx.DB { - return app.sqlxDB -} - func (app *ChainlinkApplication) GetDB() sqlutil.DataSource { - return app.db + return app.ds } // Returns the configuration to use for creating and authenticating @@ -887,3 +893,39 @@ func (app *ChainlinkApplication) GetWebAuthnConfiguration() sessions.WebAuthnCon func (app *ChainlinkApplication) ID() uuid.UUID { return app.Config.AppID() } + +// FindLCA - finds last common ancestor +func (app *ChainlinkApplication) FindLCA(ctx context.Context, chainID *big.Int) (*logpoller.LogPollerBlock, error) { + chain, err := app.GetRelayers().LegacyEVMChains().Get(chainID.String()) + if err != nil { + return nil, err + } + if !app.Config.Feature().LogPoller() { + return nil, fmt.Errorf("FindLCA is only available if LogPoller is enabled") + } + + lca, err := chain.LogPoller().FindLCA(ctx) + if err != nil { + return nil, fmt.Errorf("failed to find lca: %w", err) + } + + return lca, nil +} + +// DeleteLogPollerDataAfter - delete LogPoller state starting from the specified block +func (app *ChainlinkApplication) DeleteLogPollerDataAfter(ctx context.Context, chainID *big.Int, start int64) error { + chain, err := app.GetRelayers().LegacyEVMChains().Get(chainID.String()) + if err != nil { + return err + } + if !app.Config.Feature().LogPoller() { + return fmt.Errorf("DeleteLogPollerDataAfter is only available if LogPoller is enabled") + } + + err = chain.LogPoller().DeleteLogsAndBlocksAfter(ctx, start) + if err != nil { + return fmt.Errorf("failed to recover LogPoller: %w", err) + } + + return nil +} diff --git a/core/services/chainlink/config_mercury.go b/core/services/chainlink/config_mercury.go index 27303a68899..1b64e0bde45 100644 --- a/core/services/chainlink/config_mercury.go +++ b/core/services/chainlink/config_mercury.go @@ -3,6 +3,7 @@ package chainlink import ( "time" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/config" @@ -25,6 +26,8 @@ func (m *mercuryCacheConfig) LatestReportDeadline() time.Duration { return m.c.LatestReportDeadline.Duration() } +var _ config.MercuryTLS = (*mercuryTLSConfig)(nil) + type mercuryTLSConfig struct { c toml.MercuryTLS } @@ -33,6 +36,20 @@ func (m *mercuryTLSConfig) CertFile() string { return *m.c.CertFile } +var _ config.MercuryTransmitter = (*mercuryTransmitterConfig)(nil) + +type mercuryTransmitterConfig struct { + c toml.MercuryTransmitter +} + +func (m *mercuryTransmitterConfig) TransmitQueueMaxSize() uint32 { + return *m.c.TransmitQueueMaxSize +} + +func (m *mercuryTransmitterConfig) TransmitTimeout() commonconfig.Duration { + return *m.c.TransmitTimeout +} + type mercuryConfig struct { c toml.Mercury s toml.MercurySecrets @@ -60,3 +77,7 @@ func (m *mercuryConfig) Cache() config.MercuryCache { func (m *mercuryConfig) TLS() config.MercuryTLS { return &mercuryTLSConfig{c: m.c.TLS} } + +func (m *mercuryConfig) Transmitter() config.MercuryTransmitter { + return &mercuryTransmitterConfig{c: m.c.Transmitter} +} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index d02948fd07b..0d40697345d 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -710,6 +710,10 @@ func TestConfig_Marshal(t *testing.T) { TLS: toml.MercuryTLS{ CertFile: ptr("/path/to/cert.pem"), }, + Transmitter: toml.MercuryTransmitter{ + TransmitQueueMaxSize: ptr(uint32(123)), + TransmitTimeout: commoncfg.MustNewDuration(234 * time.Second), + }, } for _, tt := range []struct { @@ -1165,6 +1169,10 @@ LatestReportDeadline = '1m42s' [Mercury.TLS] CertFile = '/path/to/cert.pem' + +[Mercury.Transmitter] +TransmitQueueMaxSize = 123 +TransmitTimeout = '3m54s' `}, {"full", full, fullTOML}, {"multi-chain", multiChain, multiChainTOML}, diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 7126c73927c..8111c1f61b4 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -212,8 +212,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, CSAETHKeystore: keyStore, }), @@ -265,8 +264,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: db, - QConfig: cfg.Database()}), + DS: db, + }), }, expectedCosmosChainCnt: 2, expectedCosmosNodeCnt: 2, @@ -287,8 +286,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, CSAETHKeystore: keyStore, }), @@ -298,8 +296,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: db, - QConfig: cfg.Database(), + DS: db, }), }, expectedEVMChainCnt: 2, diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 5902555f79c..31645b7c54d 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml/v2" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" @@ -19,10 +19,10 @@ import ( "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" @@ -39,6 +39,7 @@ type RelayerFactory struct { type EVMFactoryConfig struct { legacyevm.ChainOpts evmrelay.CSAETHKeystore + coreconfig.MercuryTransmitter } func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (map[types.RelayID]evmrelay.LoopRelayAdapter, error) { @@ -68,11 +69,10 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m } relayerOpts := evmrelay.RelayerOpts{ - DB: ccOpts.SqlxDB, - DS: ccOpts.DB, - QConfig: ccOpts.AppConfig.Database(), - CSAETHKeystore: config.CSAETHKeystore, - MercuryPool: r.MercuryPool, + DS: ccOpts.DS, + CSAETHKeystore: config.CSAETHKeystore, + MercuryPool: r.MercuryPool, + TransmitterConfig: config.MercuryTransmitter, } relayer, err2 := evmrelay.NewRelayer(lggr.Named(relayID.ChainID), chain, relayerOpts) if err2 != nil { @@ -239,8 +239,7 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs config.TOML type CosmosFactoryConfig struct { Keystore keystore.Cosmos coscfg.TOMLConfigs - *sqlx.DB - pg.QConfig + DS sqlutil.DataSource } func (c CosmosFactoryConfig) Validate() error { @@ -251,11 +250,8 @@ func (c CosmosFactoryConfig) Validate() error { if len(c.TOMLConfigs) == 0 { err = errors.Join(err, fmt.Errorf("no CosmosConfigs provided")) } - if c.DB == nil { - err = errors.Join(err, fmt.Errorf("nil DB")) - } - if c.QConfig == nil { - err = errors.Join(err, fmt.Errorf("nil QConfig")) + if c.DS == nil { + err = errors.Join(err, fmt.Errorf("nil DataStore")) } if err != nil { @@ -284,7 +280,7 @@ func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayI opts := cosmos.ChainOpts{ Logger: lggr, - DB: config.DB, + DS: config.DS, KeyStore: loopKs, } diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index 759a380d15c..38c3ed62017 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 8a016149e59..b199ae530f5 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -240,6 +240,10 @@ LatestReportDeadline = '1m42s' [Mercury.TLS] CertFile = '/path/to/cert.pem' +[Mercury.Transmitter] +TransmitQueueMaxSize = 123 +TransmitTimeout = '3m54s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 13 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index a6cba2aaac3..7aa3bb50b35 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/core/services/cron/cron_test.go b/core/services/cron/cron_test.go index b31a06a9591..38684e982d9 100644 --- a/core/services/cron/cron_test.go +++ b/core/services/cron/cron_test.go @@ -29,7 +29,7 @@ func TestCronV2Pipeline(t *testing.T) { lggr := logger.TestLogger(t) orm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jobORM := job.NewORM(db, orm, btORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(db, orm, btORM, keyStore, lggr) jb := &job.Job{ Type: job.Cron, @@ -40,7 +40,7 @@ func TestCronV2Pipeline(t *testing.T) { } delegate := cron.NewDelegate(runner, lggr) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), jb)) serviceArray, err := delegate.ServicesForSpec(testutils.Context(t), *jb) require.NoError(t, err) assert.Len(t, serviceArray, 1) diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go index 33a0a7e73da..26f2c5f9c84 100644 --- a/core/services/directrequest/delegate.go +++ b/core/services/directrequest/delegate.go @@ -215,36 +215,37 @@ func (l *listener) HandleLog(ctx context.Context, lb log.Broadcast) { } func (l *listener) processOracleRequests() { + ctx, cancel := l.chStop.NewCtx() + defer cancel() for { select { case <-l.chStop: l.shutdownWaitGroup.Done() return case <-l.mbOracleRequests.Notify(): - l.handleReceivedLogs(l.mbOracleRequests) + l.handleReceivedLogs(ctx, l.mbOracleRequests) } } } func (l *listener) processCancelOracleRequests() { + ctx, cancel := l.chStop.NewCtx() + defer cancel() for { select { case <-l.chStop: l.shutdownWaitGroup.Done() return case <-l.mbOracleCancelRequests.Notify(): - l.handleReceivedLogs(l.mbOracleCancelRequests) + l.handleReceivedLogs(ctx, l.mbOracleCancelRequests) } } } -func (l *listener) handleReceivedLogs(mailbox *mailbox.Mailbox[log.Broadcast]) { - ctx, cancel := l.chStop.NewCtx() - defer cancel() - +func (l *listener) handleReceivedLogs(ctx context.Context, mailbox *mailbox.Mailbox[log.Broadcast]) { for { select { - case <-l.chStop: + case <-ctx.Done(): return default: } @@ -263,7 +264,7 @@ func (l *listener) handleReceivedLogs(mailbox *mailbox.Mailbox[log.Broadcast]) { logJobSpecID := lb.RawLog().Topics[1] if logJobSpecID == (common.Hash{}) || (logJobSpecID != l.job.ExternalIDEncodeStringToTopic() && logJobSpecID != l.job.ExternalIDEncodeBytesToTopic()) { l.logger.Debugw("Skipping Run for Log with wrong Job ID", "logJobSpecID", logJobSpecID) - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, nil, lb) continue } @@ -277,7 +278,7 @@ func (l *listener) handleReceivedLogs(mailbox *mailbox.Mailbox[log.Broadcast]) { case *operator_wrapper.OperatorOracleRequest: l.handleOracleRequest(ctx, log, lb) case *operator_wrapper.OperatorCancelOracleRequest: - l.handleCancelOracleRequest(ctx, log, lb) + l.handleCancelOracleRequest(ctx, nil, log, lb) default: l.logger.Warnf("Unexpected log type %T", log) } @@ -316,7 +317,7 @@ func (l *listener) handleOracleRequest(ctx context.Context, request *operator_wr "requester", request.Requester, "allowedRequesters", l.requesters.ToStrings(), ) - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, nil, lb) return } @@ -333,7 +334,7 @@ func (l *listener) handleOracleRequest(ctx context.Context, request *operator_wr "minContractPayment", minContractPayment.String(), "requestPayment", requestPayment.String(), ) - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, nil, lb) return } } @@ -375,7 +376,7 @@ func (l *listener) handleOracleRequest(ctx context.Context, request *operator_wr }) run := pipeline.NewRun(*l.job.PipelineSpec, vars) _, err := l.pipelineRunner.Run(ctx, run, l.logger, true, func(tx sqlutil.DataSource) error { - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, tx, lb) return nil }) if ctx.Err() != nil { @@ -398,16 +399,16 @@ func (l *listener) allowRequester(requester common.Address) bool { } // Cancels runs that haven't been started yet, with the given request ID -func (l *listener) handleCancelOracleRequest(ctx context.Context, request *operator_wrapper.OperatorCancelOracleRequest, lb log.Broadcast) { +func (l *listener) handleCancelOracleRequest(ctx context.Context, ds sqlutil.DataSource, request *operator_wrapper.OperatorCancelOracleRequest, lb log.Broadcast) { runCloserChannelIf, loaded := l.runs.LoadAndDelete(formatRequestId(request.RequestId)) if loaded { close(runCloserChannelIf.(services.StopChan)) } - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, ds, lb) } -func (l *listener) markLogConsumed(ctx context.Context, lb log.Broadcast) { - if err := l.logBroadcaster.MarkConsumed(ctx, nil, lb); err != nil { +func (l *listener) markLogConsumed(ctx context.Context, ds sqlutil.DataSource, lb log.Broadcast) { + if err := l.logBroadcaster.MarkConsumed(ctx, ds, lb); err != nil { l.logger.Errorw("Unable to mark log consumed", "err", err, "log", lb.String()) } } diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index 08f38865bec..e754713b010 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -90,7 +90,7 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi lggr := logger.TestLogger(t) orm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jobORM := job.NewORM(db, orm, btORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(db, orm, btORM, keyStore, lggr) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) delegate := directrequest.NewDelegate(lggr, runner, orm, legacyChains, mailMon) @@ -99,8 +99,9 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi if specF != nil { specF(jb) } - require.NoError(t, jobORM.CreateJob(jb)) - serviceArray, err := delegate.ServicesForSpec(testutils.Context(t), *jb) + ctx := testutils.Context(t) + require.NoError(t, jobORM.CreateJob(ctx, jb)) + serviceArray, err := delegate.ServicesForSpec(ctx, *jb) require.NoError(t, err) assert.Len(t, serviceArray, 1) service := serviceArray[0] diff --git a/core/services/feeds/mocks/orm.go b/core/services/feeds/mocks/orm.go index f84d80a6eb1..625a0b41d9a 100644 --- a/core/services/feeds/mocks/orm.go +++ b/core/services/feeds/mocks/orm.go @@ -3,10 +3,12 @@ package mocks import ( + context "context" + feeds "github.com/smartcontractkit/chainlink/v2/core/services/feeds" mock "github.com/stretchr/testify/mock" - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" + sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" uuid "github.com/google/uuid" ) @@ -24,24 +26,17 @@ func (_m *ORM) EXPECT() *ORM_Expecter { return &ORM_Expecter{mock: &_m.Mock} } -// ApproveSpec provides a mock function with given fields: id, externalJobID, qopts -func (_m *ORM) ApproveSpec(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id, externalJobID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ApproveSpec provides a mock function with given fields: ctx, id, externalJobID +func (_m *ORM) ApproveSpec(ctx context.Context, id int64, externalJobID uuid.UUID) error { + ret := _m.Called(ctx, id, externalJobID) if len(ret) == 0 { panic("no return value specified for ApproveSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, uuid.UUID, ...pg.QOpt) error); ok { - r0 = rf(id, externalJobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, uuid.UUID) error); ok { + r0 = rf(ctx, id, externalJobID) } else { r0 = ret.Error(0) } @@ -55,23 +50,16 @@ type ORM_ApproveSpec_Call struct { } // ApproveSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 // - externalJobID uuid.UUID -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ApproveSpec(id interface{}, externalJobID interface{}, qopts ...interface{}) *ORM_ApproveSpec_Call { - return &ORM_ApproveSpec_Call{Call: _e.mock.On("ApproveSpec", - append([]interface{}{id, externalJobID}, qopts...)...)} +func (_e *ORM_Expecter) ApproveSpec(ctx interface{}, id interface{}, externalJobID interface{}) *ORM_ApproveSpec_Call { + return &ORM_ApproveSpec_Call{Call: _e.mock.On("ApproveSpec", ctx, id, externalJobID)} } -func (_c *ORM_ApproveSpec_Call) Run(run func(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt)) *ORM_ApproveSpec_Call { +func (_c *ORM_ApproveSpec_Call) Run(run func(ctx context.Context, id int64, externalJobID uuid.UUID)) *ORM_ApproveSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(uuid.UUID), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(uuid.UUID)) }) return _c } @@ -81,29 +69,22 @@ func (_c *ORM_ApproveSpec_Call) Return(_a0 error) *ORM_ApproveSpec_Call { return _c } -func (_c *ORM_ApproveSpec_Call) RunAndReturn(run func(int64, uuid.UUID, ...pg.QOpt) error) *ORM_ApproveSpec_Call { +func (_c *ORM_ApproveSpec_Call) RunAndReturn(run func(context.Context, int64, uuid.UUID) error) *ORM_ApproveSpec_Call { _c.Call.Return(run) return _c } -// CancelSpec provides a mock function with given fields: id, qopts -func (_m *ORM) CancelSpec(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CancelSpec provides a mock function with given fields: ctx, id +func (_m *ORM) CancelSpec(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for CancelSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -117,22 +98,15 @@ type ORM_CancelSpec_Call struct { } // CancelSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CancelSpec(id interface{}, qopts ...interface{}) *ORM_CancelSpec_Call { - return &ORM_CancelSpec_Call{Call: _e.mock.On("CancelSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) CancelSpec(ctx interface{}, id interface{}) *ORM_CancelSpec_Call { + return &ORM_CancelSpec_Call{Call: _e.mock.On("CancelSpec", ctx, id)} } -func (_c *ORM_CancelSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_CancelSpec_Call { +func (_c *ORM_CancelSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_CancelSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -142,14 +116,14 @@ func (_c *ORM_CancelSpec_Call) Return(_a0 error) *ORM_CancelSpec_Call { return _c } -func (_c *ORM_CancelSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_CancelSpec_Call { +func (_c *ORM_CancelSpec_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_CancelSpec_Call { _c.Call.Return(run) return _c } -// CountJobProposals provides a mock function with given fields: -func (_m *ORM) CountJobProposals() (int64, error) { - ret := _m.Called() +// CountJobProposals provides a mock function with given fields: ctx +func (_m *ORM) CountJobProposals(ctx context.Context) (int64, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountJobProposals") @@ -157,17 +131,17 @@ func (_m *ORM) CountJobProposals() (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func() (int64, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -181,13 +155,14 @@ type ORM_CountJobProposals_Call struct { } // CountJobProposals is a helper method to define mock.On call -func (_e *ORM_Expecter) CountJobProposals() *ORM_CountJobProposals_Call { - return &ORM_CountJobProposals_Call{Call: _e.mock.On("CountJobProposals")} +// - ctx context.Context +func (_e *ORM_Expecter) CountJobProposals(ctx interface{}) *ORM_CountJobProposals_Call { + return &ORM_CountJobProposals_Call{Call: _e.mock.On("CountJobProposals", ctx)} } -func (_c *ORM_CountJobProposals_Call) Run(run func()) *ORM_CountJobProposals_Call { +func (_c *ORM_CountJobProposals_Call) Run(run func(ctx context.Context)) *ORM_CountJobProposals_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -197,14 +172,14 @@ func (_c *ORM_CountJobProposals_Call) Return(_a0 int64, _a1 error) *ORM_CountJob return _c } -func (_c *ORM_CountJobProposals_Call) RunAndReturn(run func() (int64, error)) *ORM_CountJobProposals_Call { +func (_c *ORM_CountJobProposals_Call) RunAndReturn(run func(context.Context) (int64, error)) *ORM_CountJobProposals_Call { _c.Call.Return(run) return _c } -// CountJobProposalsByStatus provides a mock function with given fields: -func (_m *ORM) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) { - ret := _m.Called() +// CountJobProposalsByStatus provides a mock function with given fields: ctx +func (_m *ORM) CountJobProposalsByStatus(ctx context.Context) (*feeds.JobProposalCounts, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountJobProposalsByStatus") @@ -212,19 +187,19 @@ func (_m *ORM) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) { var r0 *feeds.JobProposalCounts var r1 error - if rf, ok := ret.Get(0).(func() (*feeds.JobProposalCounts, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (*feeds.JobProposalCounts, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() *feeds.JobProposalCounts); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) *feeds.JobProposalCounts); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalCounts) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -238,13 +213,14 @@ type ORM_CountJobProposalsByStatus_Call struct { } // CountJobProposalsByStatus is a helper method to define mock.On call -func (_e *ORM_Expecter) CountJobProposalsByStatus() *ORM_CountJobProposalsByStatus_Call { - return &ORM_CountJobProposalsByStatus_Call{Call: _e.mock.On("CountJobProposalsByStatus")} +// - ctx context.Context +func (_e *ORM_Expecter) CountJobProposalsByStatus(ctx interface{}) *ORM_CountJobProposalsByStatus_Call { + return &ORM_CountJobProposalsByStatus_Call{Call: _e.mock.On("CountJobProposalsByStatus", ctx)} } -func (_c *ORM_CountJobProposalsByStatus_Call) Run(run func()) *ORM_CountJobProposalsByStatus_Call { +func (_c *ORM_CountJobProposalsByStatus_Call) Run(run func(ctx context.Context)) *ORM_CountJobProposalsByStatus_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -254,14 +230,14 @@ func (_c *ORM_CountJobProposalsByStatus_Call) Return(counts *feeds.JobProposalCo return _c } -func (_c *ORM_CountJobProposalsByStatus_Call) RunAndReturn(run func() (*feeds.JobProposalCounts, error)) *ORM_CountJobProposalsByStatus_Call { +func (_c *ORM_CountJobProposalsByStatus_Call) RunAndReturn(run func(context.Context) (*feeds.JobProposalCounts, error)) *ORM_CountJobProposalsByStatus_Call { _c.Call.Return(run) return _c } -// CountManagers provides a mock function with given fields: -func (_m *ORM) CountManagers() (int64, error) { - ret := _m.Called() +// CountManagers provides a mock function with given fields: ctx +func (_m *ORM) CountManagers(ctx context.Context) (int64, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountManagers") @@ -269,17 +245,17 @@ func (_m *ORM) CountManagers() (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func() (int64, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -293,13 +269,14 @@ type ORM_CountManagers_Call struct { } // CountManagers is a helper method to define mock.On call -func (_e *ORM_Expecter) CountManagers() *ORM_CountManagers_Call { - return &ORM_CountManagers_Call{Call: _e.mock.On("CountManagers")} +// - ctx context.Context +func (_e *ORM_Expecter) CountManagers(ctx interface{}) *ORM_CountManagers_Call { + return &ORM_CountManagers_Call{Call: _e.mock.On("CountManagers", ctx)} } -func (_c *ORM_CountManagers_Call) Run(run func()) *ORM_CountManagers_Call { +func (_c *ORM_CountManagers_Call) Run(run func(ctx context.Context)) *ORM_CountManagers_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -309,21 +286,14 @@ func (_c *ORM_CountManagers_Call) Return(_a0 int64, _a1 error) *ORM_CountManager return _c } -func (_c *ORM_CountManagers_Call) RunAndReturn(run func() (int64, error)) *ORM_CountManagers_Call { +func (_c *ORM_CountManagers_Call) RunAndReturn(run func(context.Context) (int64, error)) *ORM_CountManagers_Call { _c.Call.Return(run) return _c } -// CreateBatchChainConfig provides a mock function with given fields: cfgs, qopts -func (_m *ORM) CreateBatchChainConfig(cfgs []feeds.ChainConfig, qopts ...pg.QOpt) ([]int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, cfgs) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateBatchChainConfig provides a mock function with given fields: ctx, cfgs +func (_m *ORM) CreateBatchChainConfig(ctx context.Context, cfgs []feeds.ChainConfig) ([]int64, error) { + ret := _m.Called(ctx, cfgs) if len(ret) == 0 { panic("no return value specified for CreateBatchChainConfig") @@ -331,19 +301,19 @@ func (_m *ORM) CreateBatchChainConfig(cfgs []feeds.ChainConfig, qopts ...pg.QOpt var r0 []int64 var r1 error - if rf, ok := ret.Get(0).(func([]feeds.ChainConfig, ...pg.QOpt) ([]int64, error)); ok { - return rf(cfgs, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []feeds.ChainConfig) ([]int64, error)); ok { + return rf(ctx, cfgs) } - if rf, ok := ret.Get(0).(func([]feeds.ChainConfig, ...pg.QOpt) []int64); ok { - r0 = rf(cfgs, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []feeds.ChainConfig) []int64); ok { + r0 = rf(ctx, cfgs) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]int64) } } - if rf, ok := ret.Get(1).(func([]feeds.ChainConfig, ...pg.QOpt) error); ok { - r1 = rf(cfgs, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []feeds.ChainConfig) error); ok { + r1 = rf(ctx, cfgs) } else { r1 = ret.Error(1) } @@ -357,22 +327,15 @@ type ORM_CreateBatchChainConfig_Call struct { } // CreateBatchChainConfig is a helper method to define mock.On call +// - ctx context.Context // - cfgs []feeds.ChainConfig -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateBatchChainConfig(cfgs interface{}, qopts ...interface{}) *ORM_CreateBatchChainConfig_Call { - return &ORM_CreateBatchChainConfig_Call{Call: _e.mock.On("CreateBatchChainConfig", - append([]interface{}{cfgs}, qopts...)...)} +func (_e *ORM_Expecter) CreateBatchChainConfig(ctx interface{}, cfgs interface{}) *ORM_CreateBatchChainConfig_Call { + return &ORM_CreateBatchChainConfig_Call{Call: _e.mock.On("CreateBatchChainConfig", ctx, cfgs)} } -func (_c *ORM_CreateBatchChainConfig_Call) Run(run func(cfgs []feeds.ChainConfig, qopts ...pg.QOpt)) *ORM_CreateBatchChainConfig_Call { +func (_c *ORM_CreateBatchChainConfig_Call) Run(run func(ctx context.Context, cfgs []feeds.ChainConfig)) *ORM_CreateBatchChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].([]feeds.ChainConfig), variadicArgs...) + run(args[0].(context.Context), args[1].([]feeds.ChainConfig)) }) return _c } @@ -382,21 +345,14 @@ func (_c *ORM_CreateBatchChainConfig_Call) Return(_a0 []int64, _a1 error) *ORM_C return _c } -func (_c *ORM_CreateBatchChainConfig_Call) RunAndReturn(run func([]feeds.ChainConfig, ...pg.QOpt) ([]int64, error)) *ORM_CreateBatchChainConfig_Call { +func (_c *ORM_CreateBatchChainConfig_Call) RunAndReturn(run func(context.Context, []feeds.ChainConfig) ([]int64, error)) *ORM_CreateBatchChainConfig_Call { _c.Call.Return(run) return _c } -// CreateChainConfig provides a mock function with given fields: cfg, qopts -func (_m *ORM) CreateChainConfig(cfg feeds.ChainConfig, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, cfg) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateChainConfig provides a mock function with given fields: ctx, cfg +func (_m *ORM) CreateChainConfig(ctx context.Context, cfg feeds.ChainConfig) (int64, error) { + ret := _m.Called(ctx, cfg) if len(ret) == 0 { panic("no return value specified for CreateChainConfig") @@ -404,17 +360,17 @@ func (_m *ORM) CreateChainConfig(cfg feeds.ChainConfig, qopts ...pg.QOpt) (int64 var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(feeds.ChainConfig, ...pg.QOpt) (int64, error)); ok { - return rf(cfg, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) (int64, error)); ok { + return rf(ctx, cfg) } - if rf, ok := ret.Get(0).(func(feeds.ChainConfig, ...pg.QOpt) int64); ok { - r0 = rf(cfg, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) int64); ok { + r0 = rf(ctx, cfg) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(feeds.ChainConfig, ...pg.QOpt) error); ok { - r1 = rf(cfg, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, feeds.ChainConfig) error); ok { + r1 = rf(ctx, cfg) } else { r1 = ret.Error(1) } @@ -428,22 +384,15 @@ type ORM_CreateChainConfig_Call struct { } // CreateChainConfig is a helper method to define mock.On call +// - ctx context.Context // - cfg feeds.ChainConfig -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateChainConfig(cfg interface{}, qopts ...interface{}) *ORM_CreateChainConfig_Call { - return &ORM_CreateChainConfig_Call{Call: _e.mock.On("CreateChainConfig", - append([]interface{}{cfg}, qopts...)...)} +func (_e *ORM_Expecter) CreateChainConfig(ctx interface{}, cfg interface{}) *ORM_CreateChainConfig_Call { + return &ORM_CreateChainConfig_Call{Call: _e.mock.On("CreateChainConfig", ctx, cfg)} } -func (_c *ORM_CreateChainConfig_Call) Run(run func(cfg feeds.ChainConfig, qopts ...pg.QOpt)) *ORM_CreateChainConfig_Call { +func (_c *ORM_CreateChainConfig_Call) Run(run func(ctx context.Context, cfg feeds.ChainConfig)) *ORM_CreateChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(feeds.ChainConfig), variadicArgs...) + run(args[0].(context.Context), args[1].(feeds.ChainConfig)) }) return _c } @@ -453,14 +402,14 @@ func (_c *ORM_CreateChainConfig_Call) Return(_a0 int64, _a1 error) *ORM_CreateCh return _c } -func (_c *ORM_CreateChainConfig_Call) RunAndReturn(run func(feeds.ChainConfig, ...pg.QOpt) (int64, error)) *ORM_CreateChainConfig_Call { +func (_c *ORM_CreateChainConfig_Call) RunAndReturn(run func(context.Context, feeds.ChainConfig) (int64, error)) *ORM_CreateChainConfig_Call { _c.Call.Return(run) return _c } -// CreateJobProposal provides a mock function with given fields: jp -func (_m *ORM) CreateJobProposal(jp *feeds.JobProposal) (int64, error) { - ret := _m.Called(jp) +// CreateJobProposal provides a mock function with given fields: ctx, jp +func (_m *ORM) CreateJobProposal(ctx context.Context, jp *feeds.JobProposal) (int64, error) { + ret := _m.Called(ctx, jp) if len(ret) == 0 { panic("no return value specified for CreateJobProposal") @@ -468,17 +417,17 @@ func (_m *ORM) CreateJobProposal(jp *feeds.JobProposal) (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(*feeds.JobProposal) (int64, error)); ok { - return rf(jp) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) (int64, error)); ok { + return rf(ctx, jp) } - if rf, ok := ret.Get(0).(func(*feeds.JobProposal) int64); ok { - r0 = rf(jp) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) int64); ok { + r0 = rf(ctx, jp) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(*feeds.JobProposal) error); ok { - r1 = rf(jp) + if rf, ok := ret.Get(1).(func(context.Context, *feeds.JobProposal) error); ok { + r1 = rf(ctx, jp) } else { r1 = ret.Error(1) } @@ -492,14 +441,15 @@ type ORM_CreateJobProposal_Call struct { } // CreateJobProposal is a helper method to define mock.On call +// - ctx context.Context // - jp *feeds.JobProposal -func (_e *ORM_Expecter) CreateJobProposal(jp interface{}) *ORM_CreateJobProposal_Call { - return &ORM_CreateJobProposal_Call{Call: _e.mock.On("CreateJobProposal", jp)} +func (_e *ORM_Expecter) CreateJobProposal(ctx interface{}, jp interface{}) *ORM_CreateJobProposal_Call { + return &ORM_CreateJobProposal_Call{Call: _e.mock.On("CreateJobProposal", ctx, jp)} } -func (_c *ORM_CreateJobProposal_Call) Run(run func(jp *feeds.JobProposal)) *ORM_CreateJobProposal_Call { +func (_c *ORM_CreateJobProposal_Call) Run(run func(ctx context.Context, jp *feeds.JobProposal)) *ORM_CreateJobProposal_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*feeds.JobProposal)) + run(args[0].(context.Context), args[1].(*feeds.JobProposal)) }) return _c } @@ -509,21 +459,14 @@ func (_c *ORM_CreateJobProposal_Call) Return(_a0 int64, _a1 error) *ORM_CreateJo return _c } -func (_c *ORM_CreateJobProposal_Call) RunAndReturn(run func(*feeds.JobProposal) (int64, error)) *ORM_CreateJobProposal_Call { +func (_c *ORM_CreateJobProposal_Call) RunAndReturn(run func(context.Context, *feeds.JobProposal) (int64, error)) *ORM_CreateJobProposal_Call { _c.Call.Return(run) return _c } -// CreateManager provides a mock function with given fields: ms, qopts -func (_m *ORM) CreateManager(ms *feeds.FeedsManager, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ms) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateManager provides a mock function with given fields: ctx, ms +func (_m *ORM) CreateManager(ctx context.Context, ms *feeds.FeedsManager) (int64, error) { + ret := _m.Called(ctx, ms) if len(ret) == 0 { panic("no return value specified for CreateManager") @@ -531,17 +474,17 @@ func (_m *ORM) CreateManager(ms *feeds.FeedsManager, qopts ...pg.QOpt) (int64, e var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(*feeds.FeedsManager, ...pg.QOpt) (int64, error)); ok { - return rf(ms, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.FeedsManager) (int64, error)); ok { + return rf(ctx, ms) } - if rf, ok := ret.Get(0).(func(*feeds.FeedsManager, ...pg.QOpt) int64); ok { - r0 = rf(ms, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.FeedsManager) int64); ok { + r0 = rf(ctx, ms) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(*feeds.FeedsManager, ...pg.QOpt) error); ok { - r1 = rf(ms, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, *feeds.FeedsManager) error); ok { + r1 = rf(ctx, ms) } else { r1 = ret.Error(1) } @@ -555,22 +498,15 @@ type ORM_CreateManager_Call struct { } // CreateManager is a helper method to define mock.On call +// - ctx context.Context // - ms *feeds.FeedsManager -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateManager(ms interface{}, qopts ...interface{}) *ORM_CreateManager_Call { - return &ORM_CreateManager_Call{Call: _e.mock.On("CreateManager", - append([]interface{}{ms}, qopts...)...)} +func (_e *ORM_Expecter) CreateManager(ctx interface{}, ms interface{}) *ORM_CreateManager_Call { + return &ORM_CreateManager_Call{Call: _e.mock.On("CreateManager", ctx, ms)} } -func (_c *ORM_CreateManager_Call) Run(run func(ms *feeds.FeedsManager, qopts ...pg.QOpt)) *ORM_CreateManager_Call { +func (_c *ORM_CreateManager_Call) Run(run func(ctx context.Context, ms *feeds.FeedsManager)) *ORM_CreateManager_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(*feeds.FeedsManager), variadicArgs...) + run(args[0].(context.Context), args[1].(*feeds.FeedsManager)) }) return _c } @@ -580,21 +516,14 @@ func (_c *ORM_CreateManager_Call) Return(_a0 int64, _a1 error) *ORM_CreateManage return _c } -func (_c *ORM_CreateManager_Call) RunAndReturn(run func(*feeds.FeedsManager, ...pg.QOpt) (int64, error)) *ORM_CreateManager_Call { +func (_c *ORM_CreateManager_Call) RunAndReturn(run func(context.Context, *feeds.FeedsManager) (int64, error)) *ORM_CreateManager_Call { _c.Call.Return(run) return _c } -// CreateSpec provides a mock function with given fields: spec, qopts -func (_m *ORM) CreateSpec(spec feeds.JobProposalSpec, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, spec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateSpec provides a mock function with given fields: ctx, spec +func (_m *ORM) CreateSpec(ctx context.Context, spec feeds.JobProposalSpec) (int64, error) { + ret := _m.Called(ctx, spec) if len(ret) == 0 { panic("no return value specified for CreateSpec") @@ -602,17 +531,17 @@ func (_m *ORM) CreateSpec(spec feeds.JobProposalSpec, qopts ...pg.QOpt) (int64, var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(feeds.JobProposalSpec, ...pg.QOpt) (int64, error)); ok { - return rf(spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.JobProposalSpec) (int64, error)); ok { + return rf(ctx, spec) } - if rf, ok := ret.Get(0).(func(feeds.JobProposalSpec, ...pg.QOpt) int64); ok { - r0 = rf(spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.JobProposalSpec) int64); ok { + r0 = rf(ctx, spec) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(feeds.JobProposalSpec, ...pg.QOpt) error); ok { - r1 = rf(spec, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, feeds.JobProposalSpec) error); ok { + r1 = rf(ctx, spec) } else { r1 = ret.Error(1) } @@ -626,22 +555,15 @@ type ORM_CreateSpec_Call struct { } // CreateSpec is a helper method to define mock.On call +// - ctx context.Context // - spec feeds.JobProposalSpec -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateSpec(spec interface{}, qopts ...interface{}) *ORM_CreateSpec_Call { - return &ORM_CreateSpec_Call{Call: _e.mock.On("CreateSpec", - append([]interface{}{spec}, qopts...)...)} +func (_e *ORM_Expecter) CreateSpec(ctx interface{}, spec interface{}) *ORM_CreateSpec_Call { + return &ORM_CreateSpec_Call{Call: _e.mock.On("CreateSpec", ctx, spec)} } -func (_c *ORM_CreateSpec_Call) Run(run func(spec feeds.JobProposalSpec, qopts ...pg.QOpt)) *ORM_CreateSpec_Call { +func (_c *ORM_CreateSpec_Call) Run(run func(ctx context.Context, spec feeds.JobProposalSpec)) *ORM_CreateSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(feeds.JobProposalSpec), variadicArgs...) + run(args[0].(context.Context), args[1].(feeds.JobProposalSpec)) }) return _c } @@ -651,14 +573,14 @@ func (_c *ORM_CreateSpec_Call) Return(_a0 int64, _a1 error) *ORM_CreateSpec_Call return _c } -func (_c *ORM_CreateSpec_Call) RunAndReturn(run func(feeds.JobProposalSpec, ...pg.QOpt) (int64, error)) *ORM_CreateSpec_Call { +func (_c *ORM_CreateSpec_Call) RunAndReturn(run func(context.Context, feeds.JobProposalSpec) (int64, error)) *ORM_CreateSpec_Call { _c.Call.Return(run) return _c } -// DeleteChainConfig provides a mock function with given fields: id -func (_m *ORM) DeleteChainConfig(id int64) (int64, error) { - ret := _m.Called(id) +// DeleteChainConfig provides a mock function with given fields: ctx, id +func (_m *ORM) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for DeleteChainConfig") @@ -666,17 +588,17 @@ func (_m *ORM) DeleteChainConfig(id int64) (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(int64) (int64, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (int64, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) int64); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) int64); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -690,14 +612,15 @@ type ORM_DeleteChainConfig_Call struct { } // DeleteChainConfig is a helper method to define mock.On call +// - ctx context.Context // - id int64 -func (_e *ORM_Expecter) DeleteChainConfig(id interface{}) *ORM_DeleteChainConfig_Call { - return &ORM_DeleteChainConfig_Call{Call: _e.mock.On("DeleteChainConfig", id)} +func (_e *ORM_Expecter) DeleteChainConfig(ctx interface{}, id interface{}) *ORM_DeleteChainConfig_Call { + return &ORM_DeleteChainConfig_Call{Call: _e.mock.On("DeleteChainConfig", ctx, id)} } -func (_c *ORM_DeleteChainConfig_Call) Run(run func(id int64)) *ORM_DeleteChainConfig_Call { +func (_c *ORM_DeleteChainConfig_Call) Run(run func(ctx context.Context, id int64)) *ORM_DeleteChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -707,29 +630,22 @@ func (_c *ORM_DeleteChainConfig_Call) Return(_a0 int64, _a1 error) *ORM_DeleteCh return _c } -func (_c *ORM_DeleteChainConfig_Call) RunAndReturn(run func(int64) (int64, error)) *ORM_DeleteChainConfig_Call { +func (_c *ORM_DeleteChainConfig_Call) RunAndReturn(run func(context.Context, int64) (int64, error)) *ORM_DeleteChainConfig_Call { _c.Call.Return(run) return _c } -// DeleteProposal provides a mock function with given fields: id, qopts -func (_m *ORM) DeleteProposal(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// DeleteProposal provides a mock function with given fields: ctx, id +func (_m *ORM) DeleteProposal(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for DeleteProposal") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -743,22 +659,15 @@ type ORM_DeleteProposal_Call struct { } // DeleteProposal is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) DeleteProposal(id interface{}, qopts ...interface{}) *ORM_DeleteProposal_Call { - return &ORM_DeleteProposal_Call{Call: _e.mock.On("DeleteProposal", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) DeleteProposal(ctx interface{}, id interface{}) *ORM_DeleteProposal_Call { + return &ORM_DeleteProposal_Call{Call: _e.mock.On("DeleteProposal", ctx, id)} } -func (_c *ORM_DeleteProposal_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_DeleteProposal_Call { +func (_c *ORM_DeleteProposal_Call) Run(run func(ctx context.Context, id int64)) *ORM_DeleteProposal_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -768,21 +677,14 @@ func (_c *ORM_DeleteProposal_Call) Return(_a0 error) *ORM_DeleteProposal_Call { return _c } -func (_c *ORM_DeleteProposal_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_DeleteProposal_Call { +func (_c *ORM_DeleteProposal_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_DeleteProposal_Call { _c.Call.Return(run) return _c } -// ExistsSpecByJobProposalIDAndVersion provides a mock function with given fields: jpID, version, qopts -func (_m *ORM) ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qopts ...pg.QOpt) (bool, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jpID, version) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ExistsSpecByJobProposalIDAndVersion provides a mock function with given fields: ctx, jpID, version +func (_m *ORM) ExistsSpecByJobProposalIDAndVersion(ctx context.Context, jpID int64, version int32) (bool, error) { + ret := _m.Called(ctx, jpID, version) if len(ret) == 0 { panic("no return value specified for ExistsSpecByJobProposalIDAndVersion") @@ -790,17 +692,17 @@ func (_m *ORM) ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qo var r0 bool var r1 error - if rf, ok := ret.Get(0).(func(int64, int32, ...pg.QOpt) (bool, error)); ok { - return rf(jpID, version, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, int32) (bool, error)); ok { + return rf(ctx, jpID, version) } - if rf, ok := ret.Get(0).(func(int64, int32, ...pg.QOpt) bool); ok { - r0 = rf(jpID, version, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, int32) bool); ok { + r0 = rf(ctx, jpID, version) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func(int64, int32, ...pg.QOpt) error); ok { - r1 = rf(jpID, version, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64, int32) error); ok { + r1 = rf(ctx, jpID, version) } else { r1 = ret.Error(1) } @@ -814,23 +716,16 @@ type ORM_ExistsSpecByJobProposalIDAndVersion_Call struct { } // ExistsSpecByJobProposalIDAndVersion is a helper method to define mock.On call +// - ctx context.Context // - jpID int64 // - version int32 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ExistsSpecByJobProposalIDAndVersion(jpID interface{}, version interface{}, qopts ...interface{}) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { - return &ORM_ExistsSpecByJobProposalIDAndVersion_Call{Call: _e.mock.On("ExistsSpecByJobProposalIDAndVersion", - append([]interface{}{jpID, version}, qopts...)...)} +func (_e *ORM_Expecter) ExistsSpecByJobProposalIDAndVersion(ctx interface{}, jpID interface{}, version interface{}) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { + return &ORM_ExistsSpecByJobProposalIDAndVersion_Call{Call: _e.mock.On("ExistsSpecByJobProposalIDAndVersion", ctx, jpID, version)} } -func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) Run(run func(jpID int64, version int32, qopts ...pg.QOpt)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { +func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) Run(run func(ctx context.Context, jpID int64, version int32)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(int32), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(int32)) }) return _c } @@ -840,21 +735,14 @@ func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) Return(exists bool, err return _c } -func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) RunAndReturn(run func(int64, int32, ...pg.QOpt) (bool, error)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { +func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) RunAndReturn(run func(context.Context, int64, int32) (bool, error)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { _c.Call.Return(run) return _c } -// GetApprovedSpec provides a mock function with given fields: jpID, qopts -func (_m *ORM) GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*feeds.JobProposalSpec, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jpID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// GetApprovedSpec provides a mock function with given fields: ctx, jpID +func (_m *ORM) GetApprovedSpec(ctx context.Context, jpID int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, jpID) if len(ret) == 0 { panic("no return value specified for GetApprovedSpec") @@ -862,19 +750,19 @@ func (_m *ORM) GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*feeds.JobProposal var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)); ok { - return rf(jpID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, jpID) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) *feeds.JobProposalSpec); ok { - r0 = rf(jpID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, jpID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(jpID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, jpID) } else { r1 = ret.Error(1) } @@ -888,22 +776,15 @@ type ORM_GetApprovedSpec_Call struct { } // GetApprovedSpec is a helper method to define mock.On call +// - ctx context.Context // - jpID int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) GetApprovedSpec(jpID interface{}, qopts ...interface{}) *ORM_GetApprovedSpec_Call { - return &ORM_GetApprovedSpec_Call{Call: _e.mock.On("GetApprovedSpec", - append([]interface{}{jpID}, qopts...)...)} +func (_e *ORM_Expecter) GetApprovedSpec(ctx interface{}, jpID interface{}) *ORM_GetApprovedSpec_Call { + return &ORM_GetApprovedSpec_Call{Call: _e.mock.On("GetApprovedSpec", ctx, jpID)} } -func (_c *ORM_GetApprovedSpec_Call) Run(run func(jpID int64, qopts ...pg.QOpt)) *ORM_GetApprovedSpec_Call { +func (_c *ORM_GetApprovedSpec_Call) Run(run func(ctx context.Context, jpID int64)) *ORM_GetApprovedSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -913,14 +794,14 @@ func (_c *ORM_GetApprovedSpec_Call) Return(_a0 *feeds.JobProposalSpec, _a1 error return _c } -func (_c *ORM_GetApprovedSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)) *ORM_GetApprovedSpec_Call { +func (_c *ORM_GetApprovedSpec_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposalSpec, error)) *ORM_GetApprovedSpec_Call { _c.Call.Return(run) return _c } -// GetChainConfig provides a mock function with given fields: id -func (_m *ORM) GetChainConfig(id int64) (*feeds.ChainConfig, error) { - ret := _m.Called(id) +// GetChainConfig provides a mock function with given fields: ctx, id +func (_m *ORM) GetChainConfig(ctx context.Context, id int64) (*feeds.ChainConfig, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetChainConfig") @@ -928,19 +809,19 @@ func (_m *ORM) GetChainConfig(id int64) (*feeds.ChainConfig, error) { var r0 *feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.ChainConfig, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.ChainConfig, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.ChainConfig); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.ChainConfig); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -954,14 +835,15 @@ type ORM_GetChainConfig_Call struct { } // GetChainConfig is a helper method to define mock.On call +// - ctx context.Context // - id int64 -func (_e *ORM_Expecter) GetChainConfig(id interface{}) *ORM_GetChainConfig_Call { - return &ORM_GetChainConfig_Call{Call: _e.mock.On("GetChainConfig", id)} +func (_e *ORM_Expecter) GetChainConfig(ctx interface{}, id interface{}) *ORM_GetChainConfig_Call { + return &ORM_GetChainConfig_Call{Call: _e.mock.On("GetChainConfig", ctx, id)} } -func (_c *ORM_GetChainConfig_Call) Run(run func(id int64)) *ORM_GetChainConfig_Call { +func (_c *ORM_GetChainConfig_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -971,21 +853,14 @@ func (_c *ORM_GetChainConfig_Call) Return(_a0 *feeds.ChainConfig, _a1 error) *OR return _c } -func (_c *ORM_GetChainConfig_Call) RunAndReturn(run func(int64) (*feeds.ChainConfig, error)) *ORM_GetChainConfig_Call { +func (_c *ORM_GetChainConfig_Call) RunAndReturn(run func(context.Context, int64) (*feeds.ChainConfig, error)) *ORM_GetChainConfig_Call { _c.Call.Return(run) return _c } -// GetJobProposal provides a mock function with given fields: id, qopts -func (_m *ORM) GetJobProposal(id int64, qopts ...pg.QOpt) (*feeds.JobProposal, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// GetJobProposal provides a mock function with given fields: ctx, id +func (_m *ORM) GetJobProposal(ctx context.Context, id int64) (*feeds.JobProposal, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetJobProposal") @@ -993,19 +868,19 @@ func (_m *ORM) GetJobProposal(id int64, qopts ...pg.QOpt) (*feeds.JobProposal, e var r0 *feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (*feeds.JobProposal, error)); ok { - return rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposal, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) *feeds.JobProposal); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposal); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(id, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -1019,22 +894,15 @@ type ORM_GetJobProposal_Call struct { } // GetJobProposal is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) GetJobProposal(id interface{}, qopts ...interface{}) *ORM_GetJobProposal_Call { - return &ORM_GetJobProposal_Call{Call: _e.mock.On("GetJobProposal", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) GetJobProposal(ctx interface{}, id interface{}) *ORM_GetJobProposal_Call { + return &ORM_GetJobProposal_Call{Call: _e.mock.On("GetJobProposal", ctx, id)} } -func (_c *ORM_GetJobProposal_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_GetJobProposal_Call { +func (_c *ORM_GetJobProposal_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetJobProposal_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1044,14 +912,14 @@ func (_c *ORM_GetJobProposal_Call) Return(_a0 *feeds.JobProposal, _a1 error) *OR return _c } -func (_c *ORM_GetJobProposal_Call) RunAndReturn(run func(int64, ...pg.QOpt) (*feeds.JobProposal, error)) *ORM_GetJobProposal_Call { +func (_c *ORM_GetJobProposal_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposal, error)) *ORM_GetJobProposal_Call { _c.Call.Return(run) return _c } -// GetJobProposalByRemoteUUID provides a mock function with given fields: _a0 -func (_m *ORM) GetJobProposalByRemoteUUID(_a0 uuid.UUID) (*feeds.JobProposal, error) { - ret := _m.Called(_a0) +// GetJobProposalByRemoteUUID provides a mock function with given fields: ctx, _a1 +func (_m *ORM) GetJobProposalByRemoteUUID(ctx context.Context, _a1 uuid.UUID) (*feeds.JobProposal, error) { + ret := _m.Called(ctx, _a1) if len(ret) == 0 { panic("no return value specified for GetJobProposalByRemoteUUID") @@ -1059,19 +927,19 @@ func (_m *ORM) GetJobProposalByRemoteUUID(_a0 uuid.UUID) (*feeds.JobProposal, er var r0 *feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func(uuid.UUID) (*feeds.JobProposal, error)); ok { - return rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) (*feeds.JobProposal, error)); ok { + return rf(ctx, _a1) } - if rf, ok := ret.Get(0).(func(uuid.UUID) *feeds.JobProposal); ok { - r0 = rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) *feeds.JobProposal); ok { + r0 = rf(ctx, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func(uuid.UUID) error); ok { - r1 = rf(_a0) + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, _a1) } else { r1 = ret.Error(1) } @@ -1085,14 +953,15 @@ type ORM_GetJobProposalByRemoteUUID_Call struct { } // GetJobProposalByRemoteUUID is a helper method to define mock.On call -// - _a0 uuid.UUID -func (_e *ORM_Expecter) GetJobProposalByRemoteUUID(_a0 interface{}) *ORM_GetJobProposalByRemoteUUID_Call { - return &ORM_GetJobProposalByRemoteUUID_Call{Call: _e.mock.On("GetJobProposalByRemoteUUID", _a0)} +// - ctx context.Context +// - _a1 uuid.UUID +func (_e *ORM_Expecter) GetJobProposalByRemoteUUID(ctx interface{}, _a1 interface{}) *ORM_GetJobProposalByRemoteUUID_Call { + return &ORM_GetJobProposalByRemoteUUID_Call{Call: _e.mock.On("GetJobProposalByRemoteUUID", ctx, _a1)} } -func (_c *ORM_GetJobProposalByRemoteUUID_Call) Run(run func(_a0 uuid.UUID)) *ORM_GetJobProposalByRemoteUUID_Call { +func (_c *ORM_GetJobProposalByRemoteUUID_Call) Run(run func(ctx context.Context, _a1 uuid.UUID)) *ORM_GetJobProposalByRemoteUUID_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(uuid.UUID)) + run(args[0].(context.Context), args[1].(uuid.UUID)) }) return _c } @@ -1102,14 +971,14 @@ func (_c *ORM_GetJobProposalByRemoteUUID_Call) Return(_a0 *feeds.JobProposal, _a return _c } -func (_c *ORM_GetJobProposalByRemoteUUID_Call) RunAndReturn(run func(uuid.UUID) (*feeds.JobProposal, error)) *ORM_GetJobProposalByRemoteUUID_Call { +func (_c *ORM_GetJobProposalByRemoteUUID_Call) RunAndReturn(run func(context.Context, uuid.UUID) (*feeds.JobProposal, error)) *ORM_GetJobProposalByRemoteUUID_Call { _c.Call.Return(run) return _c } -// GetLatestSpec provides a mock function with given fields: jpID -func (_m *ORM) GetLatestSpec(jpID int64) (*feeds.JobProposalSpec, error) { - ret := _m.Called(jpID) +// GetLatestSpec provides a mock function with given fields: ctx, jpID +func (_m *ORM) GetLatestSpec(ctx context.Context, jpID int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, jpID) if len(ret) == 0 { panic("no return value specified for GetLatestSpec") @@ -1117,19 +986,19 @@ func (_m *ORM) GetLatestSpec(jpID int64) (*feeds.JobProposalSpec, error) { var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.JobProposalSpec, error)); ok { - return rf(jpID) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, jpID) } - if rf, ok := ret.Get(0).(func(int64) *feeds.JobProposalSpec); ok { - r0 = rf(jpID) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, jpID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(jpID) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, jpID) } else { r1 = ret.Error(1) } @@ -1143,14 +1012,15 @@ type ORM_GetLatestSpec_Call struct { } // GetLatestSpec is a helper method to define mock.On call +// - ctx context.Context // - jpID int64 -func (_e *ORM_Expecter) GetLatestSpec(jpID interface{}) *ORM_GetLatestSpec_Call { - return &ORM_GetLatestSpec_Call{Call: _e.mock.On("GetLatestSpec", jpID)} +func (_e *ORM_Expecter) GetLatestSpec(ctx interface{}, jpID interface{}) *ORM_GetLatestSpec_Call { + return &ORM_GetLatestSpec_Call{Call: _e.mock.On("GetLatestSpec", ctx, jpID)} } -func (_c *ORM_GetLatestSpec_Call) Run(run func(jpID int64)) *ORM_GetLatestSpec_Call { +func (_c *ORM_GetLatestSpec_Call) Run(run func(ctx context.Context, jpID int64)) *ORM_GetLatestSpec_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1160,14 +1030,14 @@ func (_c *ORM_GetLatestSpec_Call) Return(_a0 *feeds.JobProposalSpec, _a1 error) return _c } -func (_c *ORM_GetLatestSpec_Call) RunAndReturn(run func(int64) (*feeds.JobProposalSpec, error)) *ORM_GetLatestSpec_Call { +func (_c *ORM_GetLatestSpec_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposalSpec, error)) *ORM_GetLatestSpec_Call { _c.Call.Return(run) return _c } -// GetManager provides a mock function with given fields: id -func (_m *ORM) GetManager(id int64) (*feeds.FeedsManager, error) { - ret := _m.Called(id) +// GetManager provides a mock function with given fields: ctx, id +func (_m *ORM) GetManager(ctx context.Context, id int64) (*feeds.FeedsManager, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetManager") @@ -1175,19 +1045,19 @@ func (_m *ORM) GetManager(id int64) (*feeds.FeedsManager, error) { var r0 *feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.FeedsManager, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.FeedsManager, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.FeedsManager); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.FeedsManager); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -1201,14 +1071,15 @@ type ORM_GetManager_Call struct { } // GetManager is a helper method to define mock.On call +// - ctx context.Context // - id int64 -func (_e *ORM_Expecter) GetManager(id interface{}) *ORM_GetManager_Call { - return &ORM_GetManager_Call{Call: _e.mock.On("GetManager", id)} +func (_e *ORM_Expecter) GetManager(ctx interface{}, id interface{}) *ORM_GetManager_Call { + return &ORM_GetManager_Call{Call: _e.mock.On("GetManager", ctx, id)} } -func (_c *ORM_GetManager_Call) Run(run func(id int64)) *ORM_GetManager_Call { +func (_c *ORM_GetManager_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetManager_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1218,21 +1089,14 @@ func (_c *ORM_GetManager_Call) Return(_a0 *feeds.FeedsManager, _a1 error) *ORM_G return _c } -func (_c *ORM_GetManager_Call) RunAndReturn(run func(int64) (*feeds.FeedsManager, error)) *ORM_GetManager_Call { +func (_c *ORM_GetManager_Call) RunAndReturn(run func(context.Context, int64) (*feeds.FeedsManager, error)) *ORM_GetManager_Call { _c.Call.Return(run) return _c } -// GetSpec provides a mock function with given fields: id, qopts -func (_m *ORM) GetSpec(id int64, qopts ...pg.QOpt) (*feeds.JobProposalSpec, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// GetSpec provides a mock function with given fields: ctx, id +func (_m *ORM) GetSpec(ctx context.Context, id int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetSpec") @@ -1240,19 +1104,19 @@ func (_m *ORM) GetSpec(id int64, qopts ...pg.QOpt) (*feeds.JobProposalSpec, erro var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)); ok { - return rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) *feeds.JobProposalSpec); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(id, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -1266,22 +1130,15 @@ type ORM_GetSpec_Call struct { } // GetSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) GetSpec(id interface{}, qopts ...interface{}) *ORM_GetSpec_Call { - return &ORM_GetSpec_Call{Call: _e.mock.On("GetSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) GetSpec(ctx interface{}, id interface{}) *ORM_GetSpec_Call { + return &ORM_GetSpec_Call{Call: _e.mock.On("GetSpec", ctx, id)} } -func (_c *ORM_GetSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_GetSpec_Call { +func (_c *ORM_GetSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1291,21 +1148,14 @@ func (_c *ORM_GetSpec_Call) Return(_a0 *feeds.JobProposalSpec, _a1 error) *ORM_G return _c } -func (_c *ORM_GetSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)) *ORM_GetSpec_Call { +func (_c *ORM_GetSpec_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposalSpec, error)) *ORM_GetSpec_Call { _c.Call.Return(run) return _c } -// IsJobManaged provides a mock function with given fields: jobID, qopts -func (_m *ORM) IsJobManaged(jobID int64, qopts ...pg.QOpt) (bool, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jobID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// IsJobManaged provides a mock function with given fields: ctx, jobID +func (_m *ORM) IsJobManaged(ctx context.Context, jobID int64) (bool, error) { + ret := _m.Called(ctx, jobID) if len(ret) == 0 { panic("no return value specified for IsJobManaged") @@ -1313,17 +1163,17 @@ func (_m *ORM) IsJobManaged(jobID int64, qopts ...pg.QOpt) (bool, error) { var r0 bool var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (bool, error)); ok { - return rf(jobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (bool, error)); ok { + return rf(ctx, jobID) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) bool); ok { - r0 = rf(jobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) bool); ok { + r0 = rf(ctx, jobID) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(jobID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, jobID) } else { r1 = ret.Error(1) } @@ -1337,22 +1187,15 @@ type ORM_IsJobManaged_Call struct { } // IsJobManaged is a helper method to define mock.On call +// - ctx context.Context // - jobID int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) IsJobManaged(jobID interface{}, qopts ...interface{}) *ORM_IsJobManaged_Call { - return &ORM_IsJobManaged_Call{Call: _e.mock.On("IsJobManaged", - append([]interface{}{jobID}, qopts...)...)} +func (_e *ORM_Expecter) IsJobManaged(ctx interface{}, jobID interface{}) *ORM_IsJobManaged_Call { + return &ORM_IsJobManaged_Call{Call: _e.mock.On("IsJobManaged", ctx, jobID)} } -func (_c *ORM_IsJobManaged_Call) Run(run func(jobID int64, qopts ...pg.QOpt)) *ORM_IsJobManaged_Call { +func (_c *ORM_IsJobManaged_Call) Run(run func(ctx context.Context, jobID int64)) *ORM_IsJobManaged_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1362,14 +1205,14 @@ func (_c *ORM_IsJobManaged_Call) Return(_a0 bool, _a1 error) *ORM_IsJobManaged_C return _c } -func (_c *ORM_IsJobManaged_Call) RunAndReturn(run func(int64, ...pg.QOpt) (bool, error)) *ORM_IsJobManaged_Call { +func (_c *ORM_IsJobManaged_Call) RunAndReturn(run func(context.Context, int64) (bool, error)) *ORM_IsJobManaged_Call { _c.Call.Return(run) return _c } -// ListChainConfigsByManagerIDs provides a mock function with given fields: mgrIDs -func (_m *ORM) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainConfig, error) { - ret := _m.Called(mgrIDs) +// ListChainConfigsByManagerIDs provides a mock function with given fields: ctx, mgrIDs +func (_m *ORM) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]feeds.ChainConfig, error) { + ret := _m.Called(ctx, mgrIDs) if len(ret) == 0 { panic("no return value specified for ListChainConfigsByManagerIDs") @@ -1377,19 +1220,19 @@ func (_m *ORM) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainConfig var r0 []feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.ChainConfig, error)); ok { - return rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.ChainConfig, error)); ok { + return rf(ctx, mgrIDs) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.ChainConfig); ok { - r0 = rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.ChainConfig); ok { + r0 = rf(ctx, mgrIDs) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(mgrIDs) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, mgrIDs) } else { r1 = ret.Error(1) } @@ -1403,14 +1246,15 @@ type ORM_ListChainConfigsByManagerIDs_Call struct { } // ListChainConfigsByManagerIDs is a helper method to define mock.On call +// - ctx context.Context // - mgrIDs []int64 -func (_e *ORM_Expecter) ListChainConfigsByManagerIDs(mgrIDs interface{}) *ORM_ListChainConfigsByManagerIDs_Call { - return &ORM_ListChainConfigsByManagerIDs_Call{Call: _e.mock.On("ListChainConfigsByManagerIDs", mgrIDs)} +func (_e *ORM_Expecter) ListChainConfigsByManagerIDs(ctx interface{}, mgrIDs interface{}) *ORM_ListChainConfigsByManagerIDs_Call { + return &ORM_ListChainConfigsByManagerIDs_Call{Call: _e.mock.On("ListChainConfigsByManagerIDs", ctx, mgrIDs)} } -func (_c *ORM_ListChainConfigsByManagerIDs_Call) Run(run func(mgrIDs []int64)) *ORM_ListChainConfigsByManagerIDs_Call { +func (_c *ORM_ListChainConfigsByManagerIDs_Call) Run(run func(ctx context.Context, mgrIDs []int64)) *ORM_ListChainConfigsByManagerIDs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]int64)) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1420,14 +1264,14 @@ func (_c *ORM_ListChainConfigsByManagerIDs_Call) Return(_a0 []feeds.ChainConfig, return _c } -func (_c *ORM_ListChainConfigsByManagerIDs_Call) RunAndReturn(run func([]int64) ([]feeds.ChainConfig, error)) *ORM_ListChainConfigsByManagerIDs_Call { +func (_c *ORM_ListChainConfigsByManagerIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.ChainConfig, error)) *ORM_ListChainConfigsByManagerIDs_Call { _c.Call.Return(run) return _c } -// ListJobProposals provides a mock function with given fields: -func (_m *ORM) ListJobProposals() ([]feeds.JobProposal, error) { - ret := _m.Called() +// ListJobProposals provides a mock function with given fields: ctx +func (_m *ORM) ListJobProposals(ctx context.Context) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListJobProposals") @@ -1435,19 +1279,19 @@ func (_m *ORM) ListJobProposals() ([]feeds.JobProposal, error) { var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.JobProposal, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.JobProposal, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.JobProposal); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.JobProposal); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -1461,13 +1305,14 @@ type ORM_ListJobProposals_Call struct { } // ListJobProposals is a helper method to define mock.On call -func (_e *ORM_Expecter) ListJobProposals() *ORM_ListJobProposals_Call { - return &ORM_ListJobProposals_Call{Call: _e.mock.On("ListJobProposals")} +// - ctx context.Context +func (_e *ORM_Expecter) ListJobProposals(ctx interface{}) *ORM_ListJobProposals_Call { + return &ORM_ListJobProposals_Call{Call: _e.mock.On("ListJobProposals", ctx)} } -func (_c *ORM_ListJobProposals_Call) Run(run func()) *ORM_ListJobProposals_Call { +func (_c *ORM_ListJobProposals_Call) Run(run func(ctx context.Context)) *ORM_ListJobProposals_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -1477,21 +1322,14 @@ func (_c *ORM_ListJobProposals_Call) Return(jps []feeds.JobProposal, err error) return _c } -func (_c *ORM_ListJobProposals_Call) RunAndReturn(run func() ([]feeds.JobProposal, error)) *ORM_ListJobProposals_Call { +func (_c *ORM_ListJobProposals_Call) RunAndReturn(run func(context.Context) ([]feeds.JobProposal, error)) *ORM_ListJobProposals_Call { _c.Call.Return(run) return _c } -// ListJobProposalsByManagersIDs provides a mock function with given fields: ids, qopts -func (_m *ORM) ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]feeds.JobProposal, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ids) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ListJobProposalsByManagersIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListJobProposalsByManagersIDs") @@ -1499,19 +1337,19 @@ func (_m *ORM) ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]f var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) ([]feeds.JobProposal, error)); ok { - return rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposal, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) []feeds.JobProposal); ok { - r0 = rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposal); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func([]int64, ...pg.QOpt) error); ok { - r1 = rf(ids, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -1525,22 +1363,15 @@ type ORM_ListJobProposalsByManagersIDs_Call struct { } // ListJobProposalsByManagersIDs is a helper method to define mock.On call +// - ctx context.Context // - ids []int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ListJobProposalsByManagersIDs(ids interface{}, qopts ...interface{}) *ORM_ListJobProposalsByManagersIDs_Call { - return &ORM_ListJobProposalsByManagersIDs_Call{Call: _e.mock.On("ListJobProposalsByManagersIDs", - append([]interface{}{ids}, qopts...)...)} +func (_e *ORM_Expecter) ListJobProposalsByManagersIDs(ctx interface{}, ids interface{}) *ORM_ListJobProposalsByManagersIDs_Call { + return &ORM_ListJobProposalsByManagersIDs_Call{Call: _e.mock.On("ListJobProposalsByManagersIDs", ctx, ids)} } -func (_c *ORM_ListJobProposalsByManagersIDs_Call) Run(run func(ids []int64, qopts ...pg.QOpt)) *ORM_ListJobProposalsByManagersIDs_Call { +func (_c *ORM_ListJobProposalsByManagersIDs_Call) Run(run func(ctx context.Context, ids []int64)) *ORM_ListJobProposalsByManagersIDs_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].([]int64), variadicArgs...) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1550,14 +1381,14 @@ func (_c *ORM_ListJobProposalsByManagersIDs_Call) Return(_a0 []feeds.JobProposal return _c } -func (_c *ORM_ListJobProposalsByManagersIDs_Call) RunAndReturn(run func([]int64, ...pg.QOpt) ([]feeds.JobProposal, error)) *ORM_ListJobProposalsByManagersIDs_Call { +func (_c *ORM_ListJobProposalsByManagersIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.JobProposal, error)) *ORM_ListJobProposalsByManagersIDs_Call { _c.Call.Return(run) return _c } -// ListManagers provides a mock function with given fields: -func (_m *ORM) ListManagers() ([]feeds.FeedsManager, error) { - ret := _m.Called() +// ListManagers provides a mock function with given fields: ctx +func (_m *ORM) ListManagers(ctx context.Context) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListManagers") @@ -1565,19 +1396,19 @@ func (_m *ORM) ListManagers() ([]feeds.FeedsManager, error) { var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.FeedsManager, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.FeedsManager, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.FeedsManager); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.FeedsManager); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -1591,13 +1422,14 @@ type ORM_ListManagers_Call struct { } // ListManagers is a helper method to define mock.On call -func (_e *ORM_Expecter) ListManagers() *ORM_ListManagers_Call { - return &ORM_ListManagers_Call{Call: _e.mock.On("ListManagers")} +// - ctx context.Context +func (_e *ORM_Expecter) ListManagers(ctx interface{}) *ORM_ListManagers_Call { + return &ORM_ListManagers_Call{Call: _e.mock.On("ListManagers", ctx)} } -func (_c *ORM_ListManagers_Call) Run(run func()) *ORM_ListManagers_Call { +func (_c *ORM_ListManagers_Call) Run(run func(ctx context.Context)) *ORM_ListManagers_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -1607,14 +1439,14 @@ func (_c *ORM_ListManagers_Call) Return(mgrs []feeds.FeedsManager, err error) *O return _c } -func (_c *ORM_ListManagers_Call) RunAndReturn(run func() ([]feeds.FeedsManager, error)) *ORM_ListManagers_Call { +func (_c *ORM_ListManagers_Call) RunAndReturn(run func(context.Context) ([]feeds.FeedsManager, error)) *ORM_ListManagers_Call { _c.Call.Return(run) return _c } -// ListManagersByIDs provides a mock function with given fields: ids -func (_m *ORM) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) { - ret := _m.Called(ids) +// ListManagersByIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) ListManagersByIDs(ctx context.Context, ids []int64) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListManagersByIDs") @@ -1622,19 +1454,19 @@ func (_m *ORM) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) { var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.FeedsManager, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.FeedsManager, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.FeedsManager); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.FeedsManager); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -1648,14 +1480,15 @@ type ORM_ListManagersByIDs_Call struct { } // ListManagersByIDs is a helper method to define mock.On call +// - ctx context.Context // - ids []int64 -func (_e *ORM_Expecter) ListManagersByIDs(ids interface{}) *ORM_ListManagersByIDs_Call { - return &ORM_ListManagersByIDs_Call{Call: _e.mock.On("ListManagersByIDs", ids)} +func (_e *ORM_Expecter) ListManagersByIDs(ctx interface{}, ids interface{}) *ORM_ListManagersByIDs_Call { + return &ORM_ListManagersByIDs_Call{Call: _e.mock.On("ListManagersByIDs", ctx, ids)} } -func (_c *ORM_ListManagersByIDs_Call) Run(run func(ids []int64)) *ORM_ListManagersByIDs_Call { +func (_c *ORM_ListManagersByIDs_Call) Run(run func(ctx context.Context, ids []int64)) *ORM_ListManagersByIDs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]int64)) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1665,21 +1498,14 @@ func (_c *ORM_ListManagersByIDs_Call) Return(_a0 []feeds.FeedsManager, _a1 error return _c } -func (_c *ORM_ListManagersByIDs_Call) RunAndReturn(run func([]int64) ([]feeds.FeedsManager, error)) *ORM_ListManagersByIDs_Call { +func (_c *ORM_ListManagersByIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.FeedsManager, error)) *ORM_ListManagersByIDs_Call { _c.Call.Return(run) return _c } -// ListSpecsByJobProposalIDs provides a mock function with given fields: ids, qopts -func (_m *ORM) ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]feeds.JobProposalSpec, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ids) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ListSpecsByJobProposalIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListSpecsByJobProposalIDs") @@ -1687,19 +1513,19 @@ func (_m *ORM) ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]feeds var r0 []feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) ([]feeds.JobProposalSpec, error)); ok { - return rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposalSpec, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) []feeds.JobProposalSpec); ok { - r0 = rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposalSpec); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func([]int64, ...pg.QOpt) error); ok { - r1 = rf(ids, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -1713,22 +1539,15 @@ type ORM_ListSpecsByJobProposalIDs_Call struct { } // ListSpecsByJobProposalIDs is a helper method to define mock.On call +// - ctx context.Context // - ids []int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ListSpecsByJobProposalIDs(ids interface{}, qopts ...interface{}) *ORM_ListSpecsByJobProposalIDs_Call { - return &ORM_ListSpecsByJobProposalIDs_Call{Call: _e.mock.On("ListSpecsByJobProposalIDs", - append([]interface{}{ids}, qopts...)...)} +func (_e *ORM_Expecter) ListSpecsByJobProposalIDs(ctx interface{}, ids interface{}) *ORM_ListSpecsByJobProposalIDs_Call { + return &ORM_ListSpecsByJobProposalIDs_Call{Call: _e.mock.On("ListSpecsByJobProposalIDs", ctx, ids)} } -func (_c *ORM_ListSpecsByJobProposalIDs_Call) Run(run func(ids []int64, qopts ...pg.QOpt)) *ORM_ListSpecsByJobProposalIDs_Call { +func (_c *ORM_ListSpecsByJobProposalIDs_Call) Run(run func(ctx context.Context, ids []int64)) *ORM_ListSpecsByJobProposalIDs_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].([]int64), variadicArgs...) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1738,29 +1557,22 @@ func (_c *ORM_ListSpecsByJobProposalIDs_Call) Return(_a0 []feeds.JobProposalSpec return _c } -func (_c *ORM_ListSpecsByJobProposalIDs_Call) RunAndReturn(run func([]int64, ...pg.QOpt) ([]feeds.JobProposalSpec, error)) *ORM_ListSpecsByJobProposalIDs_Call { +func (_c *ORM_ListSpecsByJobProposalIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.JobProposalSpec, error)) *ORM_ListSpecsByJobProposalIDs_Call { _c.Call.Return(run) return _c } -// RejectSpec provides a mock function with given fields: id, qopts -func (_m *ORM) RejectSpec(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// RejectSpec provides a mock function with given fields: ctx, id +func (_m *ORM) RejectSpec(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for RejectSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -1774,22 +1586,15 @@ type ORM_RejectSpec_Call struct { } // RejectSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) RejectSpec(id interface{}, qopts ...interface{}) *ORM_RejectSpec_Call { - return &ORM_RejectSpec_Call{Call: _e.mock.On("RejectSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) RejectSpec(ctx interface{}, id interface{}) *ORM_RejectSpec_Call { + return &ORM_RejectSpec_Call{Call: _e.mock.On("RejectSpec", ctx, id)} } -func (_c *ORM_RejectSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_RejectSpec_Call { +func (_c *ORM_RejectSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_RejectSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1799,29 +1604,22 @@ func (_c *ORM_RejectSpec_Call) Return(_a0 error) *ORM_RejectSpec_Call { return _c } -func (_c *ORM_RejectSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_RejectSpec_Call { +func (_c *ORM_RejectSpec_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_RejectSpec_Call { _c.Call.Return(run) return _c } -// RevokeSpec provides a mock function with given fields: id, qopts -func (_m *ORM) RevokeSpec(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// RevokeSpec provides a mock function with given fields: ctx, id +func (_m *ORM) RevokeSpec(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for RevokeSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -1835,22 +1633,15 @@ type ORM_RevokeSpec_Call struct { } // RevokeSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) RevokeSpec(id interface{}, qopts ...interface{}) *ORM_RevokeSpec_Call { - return &ORM_RevokeSpec_Call{Call: _e.mock.On("RevokeSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) RevokeSpec(ctx interface{}, id interface{}) *ORM_RevokeSpec_Call { + return &ORM_RevokeSpec_Call{Call: _e.mock.On("RevokeSpec", ctx, id)} } -func (_c *ORM_RevokeSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_RevokeSpec_Call { +func (_c *ORM_RevokeSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_RevokeSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1860,14 +1651,61 @@ func (_c *ORM_RevokeSpec_Call) Return(_a0 error) *ORM_RevokeSpec_Call { return _c } -func (_c *ORM_RevokeSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_RevokeSpec_Call { +func (_c *ORM_RevokeSpec_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_RevokeSpec_Call { _c.Call.Return(run) return _c } -// UpdateChainConfig provides a mock function with given fields: cfg -func (_m *ORM) UpdateChainConfig(cfg feeds.ChainConfig) (int64, error) { - ret := _m.Called(cfg) +// Transact provides a mock function with given fields: _a0, _a1 +func (_m *ORM) Transact(_a0 context.Context, _a1 func(feeds.ORM) error) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Transact") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, func(feeds.ORM) error) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ORM_Transact_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Transact' +type ORM_Transact_Call struct { + *mock.Call +} + +// Transact is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 func(feeds.ORM) error +func (_e *ORM_Expecter) Transact(_a0 interface{}, _a1 interface{}) *ORM_Transact_Call { + return &ORM_Transact_Call{Call: _e.mock.On("Transact", _a0, _a1)} +} + +func (_c *ORM_Transact_Call) Run(run func(_a0 context.Context, _a1 func(feeds.ORM) error)) *ORM_Transact_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(func(feeds.ORM) error)) + }) + return _c +} + +func (_c *ORM_Transact_Call) Return(_a0 error) *ORM_Transact_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ORM_Transact_Call) RunAndReturn(run func(context.Context, func(feeds.ORM) error) error) *ORM_Transact_Call { + _c.Call.Return(run) + return _c +} + +// UpdateChainConfig provides a mock function with given fields: ctx, cfg +func (_m *ORM) UpdateChainConfig(ctx context.Context, cfg feeds.ChainConfig) (int64, error) { + ret := _m.Called(ctx, cfg) if len(ret) == 0 { panic("no return value specified for UpdateChainConfig") @@ -1875,17 +1713,17 @@ func (_m *ORM) UpdateChainConfig(cfg feeds.ChainConfig) (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(feeds.ChainConfig) (int64, error)); ok { - return rf(cfg) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) (int64, error)); ok { + return rf(ctx, cfg) } - if rf, ok := ret.Get(0).(func(feeds.ChainConfig) int64); ok { - r0 = rf(cfg) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) int64); ok { + r0 = rf(ctx, cfg) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(feeds.ChainConfig) error); ok { - r1 = rf(cfg) + if rf, ok := ret.Get(1).(func(context.Context, feeds.ChainConfig) error); ok { + r1 = rf(ctx, cfg) } else { r1 = ret.Error(1) } @@ -1899,14 +1737,15 @@ type ORM_UpdateChainConfig_Call struct { } // UpdateChainConfig is a helper method to define mock.On call +// - ctx context.Context // - cfg feeds.ChainConfig -func (_e *ORM_Expecter) UpdateChainConfig(cfg interface{}) *ORM_UpdateChainConfig_Call { - return &ORM_UpdateChainConfig_Call{Call: _e.mock.On("UpdateChainConfig", cfg)} +func (_e *ORM_Expecter) UpdateChainConfig(ctx interface{}, cfg interface{}) *ORM_UpdateChainConfig_Call { + return &ORM_UpdateChainConfig_Call{Call: _e.mock.On("UpdateChainConfig", ctx, cfg)} } -func (_c *ORM_UpdateChainConfig_Call) Run(run func(cfg feeds.ChainConfig)) *ORM_UpdateChainConfig_Call { +func (_c *ORM_UpdateChainConfig_Call) Run(run func(ctx context.Context, cfg feeds.ChainConfig)) *ORM_UpdateChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(feeds.ChainConfig)) + run(args[0].(context.Context), args[1].(feeds.ChainConfig)) }) return _c } @@ -1916,29 +1755,22 @@ func (_c *ORM_UpdateChainConfig_Call) Return(_a0 int64, _a1 error) *ORM_UpdateCh return _c } -func (_c *ORM_UpdateChainConfig_Call) RunAndReturn(run func(feeds.ChainConfig) (int64, error)) *ORM_UpdateChainConfig_Call { +func (_c *ORM_UpdateChainConfig_Call) RunAndReturn(run func(context.Context, feeds.ChainConfig) (int64, error)) *ORM_UpdateChainConfig_Call { _c.Call.Return(run) return _c } -// UpdateJobProposalStatus provides a mock function with given fields: id, status, qopts -func (_m *ORM) UpdateJobProposalStatus(id int64, status feeds.JobProposalStatus, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id, status) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpdateJobProposalStatus provides a mock function with given fields: ctx, id, status +func (_m *ORM) UpdateJobProposalStatus(ctx context.Context, id int64, status feeds.JobProposalStatus) error { + ret := _m.Called(ctx, id, status) if len(ret) == 0 { panic("no return value specified for UpdateJobProposalStatus") } var r0 error - if rf, ok := ret.Get(0).(func(int64, feeds.JobProposalStatus, ...pg.QOpt) error); ok { - r0 = rf(id, status, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, feeds.JobProposalStatus) error); ok { + r0 = rf(ctx, id, status) } else { r0 = ret.Error(0) } @@ -1952,23 +1784,16 @@ type ORM_UpdateJobProposalStatus_Call struct { } // UpdateJobProposalStatus is a helper method to define mock.On call +// - ctx context.Context // - id int64 // - status feeds.JobProposalStatus -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpdateJobProposalStatus(id interface{}, status interface{}, qopts ...interface{}) *ORM_UpdateJobProposalStatus_Call { - return &ORM_UpdateJobProposalStatus_Call{Call: _e.mock.On("UpdateJobProposalStatus", - append([]interface{}{id, status}, qopts...)...)} +func (_e *ORM_Expecter) UpdateJobProposalStatus(ctx interface{}, id interface{}, status interface{}) *ORM_UpdateJobProposalStatus_Call { + return &ORM_UpdateJobProposalStatus_Call{Call: _e.mock.On("UpdateJobProposalStatus", ctx, id, status)} } -func (_c *ORM_UpdateJobProposalStatus_Call) Run(run func(id int64, status feeds.JobProposalStatus, qopts ...pg.QOpt)) *ORM_UpdateJobProposalStatus_Call { +func (_c *ORM_UpdateJobProposalStatus_Call) Run(run func(ctx context.Context, id int64, status feeds.JobProposalStatus)) *ORM_UpdateJobProposalStatus_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(feeds.JobProposalStatus), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(feeds.JobProposalStatus)) }) return _c } @@ -1978,29 +1803,22 @@ func (_c *ORM_UpdateJobProposalStatus_Call) Return(_a0 error) *ORM_UpdateJobProp return _c } -func (_c *ORM_UpdateJobProposalStatus_Call) RunAndReturn(run func(int64, feeds.JobProposalStatus, ...pg.QOpt) error) *ORM_UpdateJobProposalStatus_Call { +func (_c *ORM_UpdateJobProposalStatus_Call) RunAndReturn(run func(context.Context, int64, feeds.JobProposalStatus) error) *ORM_UpdateJobProposalStatus_Call { _c.Call.Return(run) return _c } -// UpdateManager provides a mock function with given fields: mgr, qopts -func (_m *ORM) UpdateManager(mgr feeds.FeedsManager, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, mgr) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpdateManager provides a mock function with given fields: ctx, mgr +func (_m *ORM) UpdateManager(ctx context.Context, mgr feeds.FeedsManager) error { + ret := _m.Called(ctx, mgr) if len(ret) == 0 { panic("no return value specified for UpdateManager") } var r0 error - if rf, ok := ret.Get(0).(func(feeds.FeedsManager, ...pg.QOpt) error); ok { - r0 = rf(mgr, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.FeedsManager) error); ok { + r0 = rf(ctx, mgr) } else { r0 = ret.Error(0) } @@ -2014,22 +1832,15 @@ type ORM_UpdateManager_Call struct { } // UpdateManager is a helper method to define mock.On call +// - ctx context.Context // - mgr feeds.FeedsManager -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpdateManager(mgr interface{}, qopts ...interface{}) *ORM_UpdateManager_Call { - return &ORM_UpdateManager_Call{Call: _e.mock.On("UpdateManager", - append([]interface{}{mgr}, qopts...)...)} +func (_e *ORM_Expecter) UpdateManager(ctx interface{}, mgr interface{}) *ORM_UpdateManager_Call { + return &ORM_UpdateManager_Call{Call: _e.mock.On("UpdateManager", ctx, mgr)} } -func (_c *ORM_UpdateManager_Call) Run(run func(mgr feeds.FeedsManager, qopts ...pg.QOpt)) *ORM_UpdateManager_Call { +func (_c *ORM_UpdateManager_Call) Run(run func(ctx context.Context, mgr feeds.FeedsManager)) *ORM_UpdateManager_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(feeds.FeedsManager), variadicArgs...) + run(args[0].(context.Context), args[1].(feeds.FeedsManager)) }) return _c } @@ -2039,29 +1850,22 @@ func (_c *ORM_UpdateManager_Call) Return(_a0 error) *ORM_UpdateManager_Call { return _c } -func (_c *ORM_UpdateManager_Call) RunAndReturn(run func(feeds.FeedsManager, ...pg.QOpt) error) *ORM_UpdateManager_Call { +func (_c *ORM_UpdateManager_Call) RunAndReturn(run func(context.Context, feeds.FeedsManager) error) *ORM_UpdateManager_Call { _c.Call.Return(run) return _c } -// UpdateSpecDefinition provides a mock function with given fields: id, spec, qopts -func (_m *ORM) UpdateSpecDefinition(id int64, spec string, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id, spec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpdateSpecDefinition provides a mock function with given fields: ctx, id, spec +func (_m *ORM) UpdateSpecDefinition(ctx context.Context, id int64, spec string) error { + ret := _m.Called(ctx, id, spec) if len(ret) == 0 { panic("no return value specified for UpdateSpecDefinition") } var r0 error - if rf, ok := ret.Get(0).(func(int64, string, ...pg.QOpt) error); ok { - r0 = rf(id, spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok { + r0 = rf(ctx, id, spec) } else { r0 = ret.Error(0) } @@ -2075,23 +1879,16 @@ type ORM_UpdateSpecDefinition_Call struct { } // UpdateSpecDefinition is a helper method to define mock.On call +// - ctx context.Context // - id int64 // - spec string -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpdateSpecDefinition(id interface{}, spec interface{}, qopts ...interface{}) *ORM_UpdateSpecDefinition_Call { - return &ORM_UpdateSpecDefinition_Call{Call: _e.mock.On("UpdateSpecDefinition", - append([]interface{}{id, spec}, qopts...)...)} +func (_e *ORM_Expecter) UpdateSpecDefinition(ctx interface{}, id interface{}, spec interface{}) *ORM_UpdateSpecDefinition_Call { + return &ORM_UpdateSpecDefinition_Call{Call: _e.mock.On("UpdateSpecDefinition", ctx, id, spec)} } -func (_c *ORM_UpdateSpecDefinition_Call) Run(run func(id int64, spec string, qopts ...pg.QOpt)) *ORM_UpdateSpecDefinition_Call { +func (_c *ORM_UpdateSpecDefinition_Call) Run(run func(ctx context.Context, id int64, spec string)) *ORM_UpdateSpecDefinition_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(string), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(string)) }) return _c } @@ -2101,21 +1898,14 @@ func (_c *ORM_UpdateSpecDefinition_Call) Return(_a0 error) *ORM_UpdateSpecDefini return _c } -func (_c *ORM_UpdateSpecDefinition_Call) RunAndReturn(run func(int64, string, ...pg.QOpt) error) *ORM_UpdateSpecDefinition_Call { +func (_c *ORM_UpdateSpecDefinition_Call) RunAndReturn(run func(context.Context, int64, string) error) *ORM_UpdateSpecDefinition_Call { _c.Call.Return(run) return _c } -// UpsertJobProposal provides a mock function with given fields: jp, qopts -func (_m *ORM) UpsertJobProposal(jp *feeds.JobProposal, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jp) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpsertJobProposal provides a mock function with given fields: ctx, jp +func (_m *ORM) UpsertJobProposal(ctx context.Context, jp *feeds.JobProposal) (int64, error) { + ret := _m.Called(ctx, jp) if len(ret) == 0 { panic("no return value specified for UpsertJobProposal") @@ -2123,17 +1913,17 @@ func (_m *ORM) UpsertJobProposal(jp *feeds.JobProposal, qopts ...pg.QOpt) (int64 var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(*feeds.JobProposal, ...pg.QOpt) (int64, error)); ok { - return rf(jp, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) (int64, error)); ok { + return rf(ctx, jp) } - if rf, ok := ret.Get(0).(func(*feeds.JobProposal, ...pg.QOpt) int64); ok { - r0 = rf(jp, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) int64); ok { + r0 = rf(ctx, jp) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(*feeds.JobProposal, ...pg.QOpt) error); ok { - r1 = rf(jp, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, *feeds.JobProposal) error); ok { + r1 = rf(ctx, jp) } else { r1 = ret.Error(1) } @@ -2147,22 +1937,15 @@ type ORM_UpsertJobProposal_Call struct { } // UpsertJobProposal is a helper method to define mock.On call +// - ctx context.Context // - jp *feeds.JobProposal -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpsertJobProposal(jp interface{}, qopts ...interface{}) *ORM_UpsertJobProposal_Call { - return &ORM_UpsertJobProposal_Call{Call: _e.mock.On("UpsertJobProposal", - append([]interface{}{jp}, qopts...)...)} +func (_e *ORM_Expecter) UpsertJobProposal(ctx interface{}, jp interface{}) *ORM_UpsertJobProposal_Call { + return &ORM_UpsertJobProposal_Call{Call: _e.mock.On("UpsertJobProposal", ctx, jp)} } -func (_c *ORM_UpsertJobProposal_Call) Run(run func(jp *feeds.JobProposal, qopts ...pg.QOpt)) *ORM_UpsertJobProposal_Call { +func (_c *ORM_UpsertJobProposal_Call) Run(run func(ctx context.Context, jp *feeds.JobProposal)) *ORM_UpsertJobProposal_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(*feeds.JobProposal), variadicArgs...) + run(args[0].(context.Context), args[1].(*feeds.JobProposal)) }) return _c } @@ -2172,7 +1955,55 @@ func (_c *ORM_UpsertJobProposal_Call) Return(_a0 int64, _a1 error) *ORM_UpsertJo return _c } -func (_c *ORM_UpsertJobProposal_Call) RunAndReturn(run func(*feeds.JobProposal, ...pg.QOpt) (int64, error)) *ORM_UpsertJobProposal_Call { +func (_c *ORM_UpsertJobProposal_Call) RunAndReturn(run func(context.Context, *feeds.JobProposal) (int64, error)) *ORM_UpsertJobProposal_Call { + _c.Call.Return(run) + return _c +} + +// WithDataSource provides a mock function with given fields: _a0 +func (_m *ORM) WithDataSource(_a0 sqlutil.DataSource) feeds.ORM { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for WithDataSource") + } + + var r0 feeds.ORM + if rf, ok := ret.Get(0).(func(sqlutil.DataSource) feeds.ORM); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(feeds.ORM) + } + } + + return r0 +} + +// ORM_WithDataSource_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithDataSource' +type ORM_WithDataSource_Call struct { + *mock.Call +} + +// WithDataSource is a helper method to define mock.On call +// - _a0 sqlutil.DataSource +func (_e *ORM_Expecter) WithDataSource(_a0 interface{}) *ORM_WithDataSource_Call { + return &ORM_WithDataSource_Call{Call: _e.mock.On("WithDataSource", _a0)} +} + +func (_c *ORM_WithDataSource_Call) Run(run func(_a0 sqlutil.DataSource)) *ORM_WithDataSource_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(sqlutil.DataSource)) + }) + return _c +} + +func (_c *ORM_WithDataSource_Call) Return(_a0 feeds.ORM) *ORM_WithDataSource_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ORM_WithDataSource_Call) RunAndReturn(run func(sqlutil.DataSource) feeds.ORM) *ORM_WithDataSource_Call { _c.Call.Return(run) return _c } diff --git a/core/services/feeds/mocks/service.go b/core/services/feeds/mocks/service.go index 05ede181f44..1e2e6393276 100644 --- a/core/services/feeds/mocks/service.go +++ b/core/services/feeds/mocks/service.go @@ -68,9 +68,9 @@ func (_m *Service) Close() error { return r0 } -// CountJobProposalsByStatus provides a mock function with given fields: -func (_m *Service) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) { - ret := _m.Called() +// CountJobProposalsByStatus provides a mock function with given fields: ctx +func (_m *Service) CountJobProposalsByStatus(ctx context.Context) (*feeds.JobProposalCounts, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountJobProposalsByStatus") @@ -78,19 +78,19 @@ func (_m *Service) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) var r0 *feeds.JobProposalCounts var r1 error - if rf, ok := ret.Get(0).(func() (*feeds.JobProposalCounts, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (*feeds.JobProposalCounts, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() *feeds.JobProposalCounts); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) *feeds.JobProposalCounts); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalCounts) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -98,9 +98,9 @@ func (_m *Service) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) return r0, r1 } -// CountManagers provides a mock function with given fields: -func (_m *Service) CountManagers() (int64, error) { - ret := _m.Called() +// CountManagers provides a mock function with given fields: ctx +func (_m *Service) CountManagers(ctx context.Context) (int64, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountManagers") @@ -108,17 +108,17 @@ func (_m *Service) CountManagers() (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func() (int64, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -210,9 +210,9 @@ func (_m *Service) DeleteJob(ctx context.Context, args *feeds.DeleteJobArgs) (in return r0, r1 } -// GetChainConfig provides a mock function with given fields: id -func (_m *Service) GetChainConfig(id int64) (*feeds.ChainConfig, error) { - ret := _m.Called(id) +// GetChainConfig provides a mock function with given fields: ctx, id +func (_m *Service) GetChainConfig(ctx context.Context, id int64) (*feeds.ChainConfig, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetChainConfig") @@ -220,19 +220,19 @@ func (_m *Service) GetChainConfig(id int64) (*feeds.ChainConfig, error) { var r0 *feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.ChainConfig, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.ChainConfig, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.ChainConfig); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.ChainConfig); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -240,9 +240,9 @@ func (_m *Service) GetChainConfig(id int64) (*feeds.ChainConfig, error) { return r0, r1 } -// GetJobProposal provides a mock function with given fields: id -func (_m *Service) GetJobProposal(id int64) (*feeds.JobProposal, error) { - ret := _m.Called(id) +// GetJobProposal provides a mock function with given fields: ctx, id +func (_m *Service) GetJobProposal(ctx context.Context, id int64) (*feeds.JobProposal, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetJobProposal") @@ -250,19 +250,19 @@ func (_m *Service) GetJobProposal(id int64) (*feeds.JobProposal, error) { var r0 *feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.JobProposal, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposal, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.JobProposal); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposal); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -270,9 +270,9 @@ func (_m *Service) GetJobProposal(id int64) (*feeds.JobProposal, error) { return r0, r1 } -// GetManager provides a mock function with given fields: id -func (_m *Service) GetManager(id int64) (*feeds.FeedsManager, error) { - ret := _m.Called(id) +// GetManager provides a mock function with given fields: ctx, id +func (_m *Service) GetManager(ctx context.Context, id int64) (*feeds.FeedsManager, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetManager") @@ -280,19 +280,19 @@ func (_m *Service) GetManager(id int64) (*feeds.FeedsManager, error) { var r0 *feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.FeedsManager, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.FeedsManager, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.FeedsManager); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.FeedsManager); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -300,9 +300,9 @@ func (_m *Service) GetManager(id int64) (*feeds.FeedsManager, error) { return r0, r1 } -// GetSpec provides a mock function with given fields: id -func (_m *Service) GetSpec(id int64) (*feeds.JobProposalSpec, error) { - ret := _m.Called(id) +// GetSpec provides a mock function with given fields: ctx, id +func (_m *Service) GetSpec(ctx context.Context, id int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetSpec") @@ -310,19 +310,19 @@ func (_m *Service) GetSpec(id int64) (*feeds.JobProposalSpec, error) { var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.JobProposalSpec, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.JobProposalSpec); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -358,9 +358,9 @@ func (_m *Service) IsJobManaged(ctx context.Context, jobID int64) (bool, error) return r0, r1 } -// ListChainConfigsByManagerIDs provides a mock function with given fields: mgrIDs -func (_m *Service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainConfig, error) { - ret := _m.Called(mgrIDs) +// ListChainConfigsByManagerIDs provides a mock function with given fields: ctx, mgrIDs +func (_m *Service) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]feeds.ChainConfig, error) { + ret := _m.Called(ctx, mgrIDs) if len(ret) == 0 { panic("no return value specified for ListChainConfigsByManagerIDs") @@ -368,19 +368,19 @@ func (_m *Service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainCo var r0 []feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.ChainConfig, error)); ok { - return rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.ChainConfig, error)); ok { + return rf(ctx, mgrIDs) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.ChainConfig); ok { - r0 = rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.ChainConfig); ok { + r0 = rf(ctx, mgrIDs) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(mgrIDs) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, mgrIDs) } else { r1 = ret.Error(1) } @@ -388,9 +388,9 @@ func (_m *Service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainCo return r0, r1 } -// ListJobProposals provides a mock function with given fields: -func (_m *Service) ListJobProposals() ([]feeds.JobProposal, error) { - ret := _m.Called() +// ListJobProposals provides a mock function with given fields: ctx +func (_m *Service) ListJobProposals(ctx context.Context) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListJobProposals") @@ -398,19 +398,19 @@ func (_m *Service) ListJobProposals() ([]feeds.JobProposal, error) { var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.JobProposal, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.JobProposal, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.JobProposal); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.JobProposal); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -418,9 +418,9 @@ func (_m *Service) ListJobProposals() ([]feeds.JobProposal, error) { return r0, r1 } -// ListJobProposalsByManagersIDs provides a mock function with given fields: ids -func (_m *Service) ListJobProposalsByManagersIDs(ids []int64) ([]feeds.JobProposal, error) { - ret := _m.Called(ids) +// ListJobProposalsByManagersIDs provides a mock function with given fields: ctx, ids +func (_m *Service) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListJobProposalsByManagersIDs") @@ -428,19 +428,19 @@ func (_m *Service) ListJobProposalsByManagersIDs(ids []int64) ([]feeds.JobPropos var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.JobProposal, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposal, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.JobProposal); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposal); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -448,9 +448,9 @@ func (_m *Service) ListJobProposalsByManagersIDs(ids []int64) ([]feeds.JobPropos return r0, r1 } -// ListManagers provides a mock function with given fields: -func (_m *Service) ListManagers() ([]feeds.FeedsManager, error) { - ret := _m.Called() +// ListManagers provides a mock function with given fields: ctx +func (_m *Service) ListManagers(ctx context.Context) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListManagers") @@ -458,19 +458,19 @@ func (_m *Service) ListManagers() ([]feeds.FeedsManager, error) { var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.FeedsManager, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.FeedsManager, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.FeedsManager); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.FeedsManager); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -478,9 +478,9 @@ func (_m *Service) ListManagers() ([]feeds.FeedsManager, error) { return r0, r1 } -// ListManagersByIDs provides a mock function with given fields: ids -func (_m *Service) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) { - ret := _m.Called(ids) +// ListManagersByIDs provides a mock function with given fields: ctx, ids +func (_m *Service) ListManagersByIDs(ctx context.Context, ids []int64) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListManagersByIDs") @@ -488,19 +488,19 @@ func (_m *Service) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.FeedsManager, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.FeedsManager, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.FeedsManager); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.FeedsManager); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -508,9 +508,9 @@ func (_m *Service) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) return r0, r1 } -// ListSpecsByJobProposalIDs provides a mock function with given fields: ids -func (_m *Service) ListSpecsByJobProposalIDs(ids []int64) ([]feeds.JobProposalSpec, error) { - ret := _m.Called(ids) +// ListSpecsByJobProposalIDs provides a mock function with given fields: ctx, ids +func (_m *Service) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListSpecsByJobProposalIDs") @@ -518,19 +518,19 @@ func (_m *Service) ListSpecsByJobProposalIDs(ids []int64) ([]feeds.JobProposalSp var r0 []feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.JobProposalSpec, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposalSpec, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.JobProposalSpec); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposalSpec); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -676,11 +676,6 @@ func (_m *Service) SyncNodeInfo(ctx context.Context, id int64) error { return r0 } -// Unsafe_SetConnectionsManager provides a mock function with given fields: _a0 -func (_m *Service) Unsafe_SetConnectionsManager(_a0 feeds.ConnectionsManager) { - _m.Called(_a0) -} - // UpdateChainConfig provides a mock function with given fields: ctx, cfg func (_m *Service) UpdateChainConfig(ctx context.Context, cfg feeds.ChainConfig) (int64, error) { ret := _m.Called(ctx, cfg) diff --git a/core/services/feeds/orm.go b/core/services/feeds/orm.go index 24ed7b8b369..bf77051dad7 100644 --- a/core/services/feeds/orm.go +++ b/core/services/feeds/orm.go @@ -1,6 +1,7 @@ package feeds import ( + "context" "database/sql" "fmt" "strings" @@ -9,99 +10,104 @@ import ( "github.com/lib/pq" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) //go:generate mockery --with-expecter=true --quiet --name ORM --output ./mocks/ --case=underscore type ORM interface { - CountManagers() (int64, error) - CreateManager(ms *FeedsManager, qopts ...pg.QOpt) (int64, error) - GetManager(id int64) (*FeedsManager, error) - ListManagers() (mgrs []FeedsManager, err error) - ListManagersByIDs(ids []int64) ([]FeedsManager, error) - UpdateManager(mgr FeedsManager, qopts ...pg.QOpt) error - - CreateBatchChainConfig(cfgs []ChainConfig, qopts ...pg.QOpt) ([]int64, error) - CreateChainConfig(cfg ChainConfig, qopts ...pg.QOpt) (int64, error) - DeleteChainConfig(id int64) (int64, error) - GetChainConfig(id int64) (*ChainConfig, error) - ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) - UpdateChainConfig(cfg ChainConfig) (int64, error) - - CountJobProposals() (int64, error) - CountJobProposalsByStatus() (counts *JobProposalCounts, err error) - CreateJobProposal(jp *JobProposal) (int64, error) - DeleteProposal(id int64, qopts ...pg.QOpt) error - GetJobProposal(id int64, qopts ...pg.QOpt) (*JobProposal, error) - GetJobProposalByRemoteUUID(uuid uuid.UUID) (*JobProposal, error) - ListJobProposals() (jps []JobProposal, err error) - ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposal, error) - UpdateJobProposalStatus(id int64, status JobProposalStatus, qopts ...pg.QOpt) error // NEEDED? - UpsertJobProposal(jp *JobProposal, qopts ...pg.QOpt) (int64, error) - - ApproveSpec(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt) error - CancelSpec(id int64, qopts ...pg.QOpt) error - CreateSpec(spec JobProposalSpec, qopts ...pg.QOpt) (int64, error) - ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qopts ...pg.QOpt) (exists bool, err error) - GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*JobProposalSpec, error) - GetLatestSpec(jpID int64) (*JobProposalSpec, error) - GetSpec(id int64, qopts ...pg.QOpt) (*JobProposalSpec, error) - ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposalSpec, error) - RejectSpec(id int64, qopts ...pg.QOpt) error - RevokeSpec(id int64, qopts ...pg.QOpt) error - UpdateSpecDefinition(id int64, spec string, qopts ...pg.QOpt) error - - IsJobManaged(jobID int64, qopts ...pg.QOpt) (bool, error) + CountManagers(ctx context.Context) (int64, error) + CreateManager(ctx context.Context, ms *FeedsManager) (int64, error) + GetManager(ctx context.Context, id int64) (*FeedsManager, error) + ListManagers(ctx context.Context) (mgrs []FeedsManager, err error) + ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) + UpdateManager(ctx context.Context, mgr FeedsManager) error + + CreateBatchChainConfig(ctx context.Context, cfgs []ChainConfig) ([]int64, error) + CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) + DeleteChainConfig(ctx context.Context, id int64) (int64, error) + GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) + ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) + UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) + + CountJobProposals(ctx context.Context) (int64, error) + CountJobProposalsByStatus(ctx context.Context) (counts *JobProposalCounts, err error) + CreateJobProposal(ctx context.Context, jp *JobProposal) (int64, error) + DeleteProposal(ctx context.Context, id int64) error + GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) + GetJobProposalByRemoteUUID(ctx context.Context, uuid uuid.UUID) (*JobProposal, error) + ListJobProposals(ctx context.Context) (jps []JobProposal, err error) + ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) + UpdateJobProposalStatus(ctx context.Context, id int64, status JobProposalStatus) error // NEEDED? + UpsertJobProposal(ctx context.Context, jp *JobProposal) (int64, error) + + ApproveSpec(ctx context.Context, id int64, externalJobID uuid.UUID) error + CancelSpec(ctx context.Context, id int64) error + CreateSpec(ctx context.Context, spec JobProposalSpec) (int64, error) + ExistsSpecByJobProposalIDAndVersion(ctx context.Context, jpID int64, version int32) (exists bool, err error) + GetApprovedSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) + GetLatestSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) + GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) + ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) + RejectSpec(ctx context.Context, id int64) error + RevokeSpec(ctx context.Context, id int64) error + UpdateSpecDefinition(ctx context.Context, id int64, spec string) error + + IsJobManaged(ctx context.Context, jobID int64) (bool, error) + + Transact(context.Context, func(ORM) error) error + WithDataSource(sqlutil.DataSource) ORM } var _ ORM = &orm{} type orm struct { - q pg.Q + ds sqlutil.DataSource } -func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *orm { - return &orm{ - q: pg.NewQ(db, lggr, cfg), - } +func NewORM(ds sqlutil.DataSource) *orm { + return &orm{ds: ds} } +func (o *orm) Transact(ctx context.Context, fn func(ORM) error) error { + return sqlutil.Transact(ctx, o.WithDataSource, o.ds, nil, fn) +} + +func (o *orm) WithDataSource(ds sqlutil.DataSource) ORM { return &orm{ds} } + // Count counts the number of feeds manager records. -func (o *orm) CountManagers() (count int64, err error) { +func (o *orm) CountManagers(ctx context.Context) (count int64, err error) { stmt := ` SELECT COUNT(*) FROM feeds_managers ` - err = o.q.Get(&count, stmt) + err = o.ds.GetContext(ctx, &count, stmt) return count, errors.Wrap(err, "CountManagers failed") } // CreateManager creates a feeds manager. -func (o *orm) CreateManager(ms *FeedsManager, qopts ...pg.QOpt) (id int64, err error) { +func (o *orm) CreateManager(ctx context.Context, ms *FeedsManager) (id int64, err error) { stmt := ` INSERT INTO feeds_managers (name, uri, public_key, created_at, updated_at) VALUES ($1,$2,$3,NOW(),NOW()) RETURNING id; ` - err = o.q.WithOpts(qopts...).Get(&id, stmt, ms.Name, ms.URI, ms.PublicKey) + err = o.ds.GetContext(ctx, &id, stmt, ms.Name, ms.URI, ms.PublicKey) return id, errors.Wrap(err, "CreateManager failed") } // CreateChainConfig creates a new chain config. -func (o *orm) CreateChainConfig(cfg ChainConfig, qopts ...pg.QOpt) (id int64, err error) { +func (o *orm) CreateChainConfig(ctx context.Context, cfg ChainConfig) (id int64, err error) { stmt := ` INSERT INTO feeds_manager_chain_configs (feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,NOW(),NOW()) RETURNING id; ` - err = o.q.WithOpts(qopts...).Get(&id, + err = o.ds.GetContext(ctx, + &id, stmt, cfg.FeedsManagerID, cfg.ChainID, @@ -117,7 +123,7 @@ RETURNING id; } // CreateBatchChainConfig creates multiple chain configs. -func (o *orm) CreateBatchChainConfig(cfgs []ChainConfig, qopts ...pg.QOpt) (ids []int64, err error) { +func (o *orm) CreateBatchChainConfig(ctx context.Context, cfgs []ChainConfig) (ids []int64, err error) { if len(cfgs) == 0 { return } @@ -160,7 +166,8 @@ RETURNING id; ) } - err = o.q.WithOpts(qopts...).Select(&ids, + err = o.ds.SelectContext(ctx, + &ids, fmt.Sprintf(stmt, strings.Join(vStrs, ",")), vArgs..., ) @@ -169,7 +176,7 @@ RETURNING id; } // DeleteChainConfig deletes a chain config. -func (o *orm) DeleteChainConfig(id int64) (int64, error) { +func (o *orm) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { stmt := ` DELETE FROM feeds_manager_chain_configs WHERE id = $1 @@ -177,13 +184,13 @@ RETURNING id; ` var ccid int64 - err := o.q.Get(&ccid, stmt, id) + err := o.ds.GetContext(ctx, &ccid, stmt, id) return ccid, errors.Wrap(err, "DeleteChainConfig failed") } // GetChainConfig fetches a chain config. -func (o *orm) GetChainConfig(id int64) (*ChainConfig, error) { +func (o *orm) GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) { stmt := ` SELECT id, feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at FROM feeds_manager_chain_configs @@ -191,14 +198,14 @@ WHERE id = $1; ` var cfg ChainConfig - err := o.q.Get(&cfg, stmt, id) + err := o.ds.GetContext(ctx, &cfg, stmt, id) return &cfg, errors.Wrap(err, "GetChainConfig failed") } // ListChainConfigsByManagerIDs fetches the chain configs matching all manager // ids. -func (o *orm) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) { +func (o *orm) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) { stmt := ` SELECT id, feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at FROM feeds_manager_chain_configs @@ -206,13 +213,13 @@ WHERE feeds_manager_id = ANY($1) ` var cfgs []ChainConfig - err := o.q.Select(&cfgs, stmt, mgrIDs) + err := o.ds.SelectContext(ctx, &cfgs, stmt, mgrIDs) return cfgs, errors.Wrap(err, "ListJobProposalsByManagersIDs failed") } // UpdateChainConfig updates a chain config. -func (o *orm) UpdateChainConfig(cfg ChainConfig) (int64, error) { +func (o *orm) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) { stmt := ` UPDATE feeds_manager_chain_configs SET account_address = $1, @@ -226,7 +233,7 @@ RETURNING id; ` var cfgID int64 - err := o.q.Get(&cfgID, stmt, + err := o.ds.GetContext(ctx, &cfgID, stmt, cfg.AccountAddress, cfg.AdminAddress, cfg.FluxMonitorConfig, @@ -239,7 +246,7 @@ RETURNING id; } // GetManager gets a feeds manager by id. -func (o *orm) GetManager(id int64) (mgr *FeedsManager, err error) { +func (o *orm) GetManager(ctx context.Context, id int64) (mgr *FeedsManager, err error) { stmt := ` SELECT id, name, uri, public_key, created_at, updated_at FROM feeds_managers @@ -247,23 +254,23 @@ WHERE id = $1 ` mgr = new(FeedsManager) - err = o.q.Get(mgr, stmt, id) + err = o.ds.GetContext(ctx, mgr, stmt, id) return mgr, errors.Wrap(err, "GetManager failed") } // ListManager lists all feeds managers. -func (o *orm) ListManagers() (mgrs []FeedsManager, err error) { +func (o *orm) ListManagers(ctx context.Context) (mgrs []FeedsManager, err error) { stmt := ` SELECT id, name, uri, public_key, created_at, updated_at FROM feeds_managers; ` - err = o.q.Select(&mgrs, stmt) + err = o.ds.SelectContext(ctx, &mgrs, stmt) return mgrs, errors.Wrap(err, "ListManagers failed") } // ListManagersByIDs gets feeds managers by ids. -func (o *orm) ListManagersByIDs(ids []int64) (managers []FeedsManager, err error) { +func (o *orm) ListManagersByIDs(ctx context.Context, ids []int64) (managers []FeedsManager, err error) { stmt := ` SELECT id, name, uri, public_key, created_at, updated_at FROM feeds_managers @@ -271,20 +278,20 @@ WHERE id = ANY($1) ORDER BY created_at, id;` mgrIds := pq.Array(ids) - err = o.q.Select(&managers, stmt, mgrIds) + err = o.ds.SelectContext(ctx, &managers, stmt, mgrIds) return managers, errors.Wrap(err, "GetManagers failed") } // UpdateManager updates the manager details. -func (o *orm) UpdateManager(mgr FeedsManager, qopts ...pg.QOpt) (err error) { +func (o *orm) UpdateManager(ctx context.Context, mgr FeedsManager) (err error) { stmt := ` UPDATE feeds_managers SET name = $1, uri = $2, public_key = $3, updated_at = NOW() WHERE id = $4; ` - res, err := o.q.WithOpts(qopts...).Exec(stmt, mgr.Name, mgr.URI, mgr.PublicKey, mgr.ID) + res, err := o.ds.ExecContext(ctx, stmt, mgr.Name, mgr.URI, mgr.PublicKey, mgr.ID) if err != nil { return errors.Wrap(err, "UpdateManager failed to update feeds_managers") } @@ -299,27 +306,27 @@ WHERE id = $4; } // CreateJobProposal creates a job proposal. -func (o *orm) CreateJobProposal(jp *JobProposal) (id int64, err error) { +func (o *orm) CreateJobProposal(ctx context.Context, jp *JobProposal) (id int64, err error) { stmt := ` INSERT INTO job_proposals (name, remote_uuid, status, feeds_manager_id, multiaddrs, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, NOW(), NOW()) RETURNING id; ` - err = o.q.Get(&id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) + err = o.ds.GetContext(ctx, &id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) return id, errors.Wrap(err, "CreateJobProposal failed") } // CountJobProposals counts the number of job proposal records. -func (o *orm) CountJobProposals() (count int64, err error) { +func (o *orm) CountJobProposals(ctx context.Context) (count int64, err error) { stmt := `SELECT COUNT(*) FROM job_proposals` - err = o.q.Get(&count, stmt) + err = o.ds.GetContext(ctx, &count, stmt) return count, errors.Wrap(err, "CountJobProposals failed") } // CountJobProposals counts the number of job proposal records. -func (o *orm) CountJobProposalsByStatus() (counts *JobProposalCounts, err error) { +func (o *orm) CountJobProposalsByStatus(ctx context.Context) (counts *JobProposalCounts, err error) { stmt := ` SELECT COUNT(*) filter (where job_proposals.status = 'pending' OR job_proposals.pending_update = TRUE) as pending, @@ -332,26 +339,26 @@ FROM job_proposals; ` counts = new(JobProposalCounts) - err = o.q.Get(counts, stmt) + err = o.ds.GetContext(ctx, counts, stmt) return counts, errors.Wrap(err, "CountJobProposalsByStatus failed") } // GetJobProposal gets a job proposal by id. -func (o *orm) GetJobProposal(id int64, qopts ...pg.QOpt) (jp *JobProposal, err error) { +func (o *orm) GetJobProposal(ctx context.Context, id int64) (jp *JobProposal, err error) { stmt := ` SELECT * FROM job_proposals WHERE id = $1 ` jp = new(JobProposal) - err = o.q.WithOpts(qopts...).Get(jp, stmt, id) + err = o.ds.GetContext(ctx, jp, stmt, id) return jp, errors.Wrap(err, "GetJobProposal failed") } // GetJobProposalByRemoteUUID gets a job proposal by the remote FMS uuid. This // method will filter out the deleted job proposals. To get all job proposals, // use the GetJobProposal get by id method. -func (o *orm) GetJobProposalByRemoteUUID(id uuid.UUID) (jp *JobProposal, err error) { +func (o *orm) GetJobProposalByRemoteUUID(ctx context.Context, id uuid.UUID) (jp *JobProposal, err error) { stmt := ` SELECT * FROM job_proposals @@ -360,35 +367,35 @@ AND status <> $2; ` jp = new(JobProposal) - err = o.q.Get(jp, stmt, id, JobProposalStatusDeleted) + err = o.ds.GetContext(ctx, jp, stmt, id, JobProposalStatusDeleted) return jp, errors.Wrap(err, "GetJobProposalByRemoteUUID failed") } // ListJobProposals lists all job proposals. -func (o *orm) ListJobProposals() (jps []JobProposal, err error) { +func (o *orm) ListJobProposals(ctx context.Context) (jps []JobProposal, err error) { stmt := ` SELECT * FROM job_proposals; ` - err = o.q.Select(&jps, stmt) + err = o.ds.SelectContext(ctx, &jps, stmt) return jps, errors.Wrap(err, "ListJobProposals failed") } // ListJobProposalsByManagersIDs gets job proposals by feeds managers IDs. -func (o *orm) ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposal, error) { +func (o *orm) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { stmt := ` SELECT * FROM job_proposals WHERE feeds_manager_id = ANY($1) ` var jps []JobProposal - err := o.q.WithOpts(qopts...).Select(&jps, stmt, ids) + err := o.ds.SelectContext(ctx, &jps, stmt, ids) return jps, errors.Wrap(err, "ListJobProposalsByManagersIDs failed") } // UpdateJobProposalStatus updates the status of a job proposal by id. -func (o *orm) UpdateJobProposalStatus(id int64, status JobProposalStatus, qopts ...pg.QOpt) error { +func (o *orm) UpdateJobProposalStatus(ctx context.Context, id int64, status JobProposalStatus) error { stmt := ` UPDATE job_proposals SET status = $1, @@ -396,7 +403,7 @@ SET status = $1, WHERE id = $2; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, status, id) + result, err := o.ds.ExecContext(ctx, stmt, status, id) if err != nil { return err } @@ -415,7 +422,7 @@ WHERE id = $2; // UpsertJobProposal creates a job proposal if it does not exist. If it does exist, // then we update the details of the existing job proposal only if the provided // feeds manager id exists. -func (o *orm) UpsertJobProposal(jp *JobProposal, qopts ...pg.QOpt) (id int64, err error) { +func (o *orm) UpsertJobProposal(ctx context.Context, jp *JobProposal) (id int64, err error) { stmt := ` INSERT INTO job_proposals (name, remote_uuid, status, feeds_manager_id, multiaddrs, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, NOW(), NOW()) @@ -436,13 +443,13 @@ DO RETURNING id; ` - err = o.q.WithOpts(qopts...).Get(&id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) + err = o.ds.GetContext(ctx, &id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) return id, errors.Wrap(err, "UpsertJobProposal") } // ApproveSpec approves the spec and sets the external job ID on the associated // job proposal. -func (o *orm) ApproveSpec(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt) error { +func (o *orm) ApproveSpec(ctx context.Context, id int64, externalJobID uuid.UUID) error { // Update the status of the approval stmt := ` UPDATE job_proposal_specs @@ -454,7 +461,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, JobProposalStatusApproved, id); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, JobProposalStatusApproved, id); err != nil { return err } @@ -468,7 +475,7 @@ SET status = $1, WHERE id = $3; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, JobProposalStatusApproved, externalJobID, jpID) + result, err := o.ds.ExecContext(ctx, stmt, JobProposalStatusApproved, externalJobID, jpID) if err != nil { return err } @@ -487,7 +494,7 @@ WHERE id = $3; // CancelSpec cancels the spec and removes the external job id from the associated job proposal. It // sets the status of the spec and the proposal to cancelled, except in the case of deleted // proposals. -func (o *orm) CancelSpec(id int64, qopts ...pg.QOpt) error { +func (o *orm) CancelSpec(ctx context.Context, id int64) error { // Update the status of the approval stmt := ` UPDATE job_proposal_specs @@ -499,7 +506,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, SpecStatusCancelled, id); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, SpecStatusCancelled, id); err != nil { return err } @@ -516,7 +523,7 @@ SET status = ( updated_at = NOW() WHERE id = $1; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, jpID, nil) + result, err := o.ds.ExecContext(ctx, stmt, jpID, nil) if err != nil { return err } @@ -533,7 +540,7 @@ WHERE id = $1; } // CreateSpec creates a new job proposal spec -func (o *orm) CreateSpec(spec JobProposalSpec, qopts ...pg.QOpt) (int64, error) { +func (o *orm) CreateSpec(ctx context.Context, spec JobProposalSpec) (int64, error) { stmt := ` INSERT INTO job_proposal_specs (definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at) VALUES ($1, $2, $3, $4, NOW(), NOW(), NOW()) @@ -541,14 +548,14 @@ RETURNING id; ` var id int64 - err := o.q.WithOpts(qopts...).Get(&id, stmt, spec.Definition, spec.Version, spec.Status, spec.JobProposalID) + err := o.ds.GetContext(ctx, &id, stmt, spec.Definition, spec.Version, spec.Status, spec.JobProposalID) return id, errors.Wrap(err, "CreateJobProposalSpec failed") } // ExistsSpecByJobProposalIDAndVersion checks if a job proposal spec exists for a specific job // proposal and version. -func (o *orm) ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qopts ...pg.QOpt) (exists bool, err error) { +func (o *orm) ExistsSpecByJobProposalIDAndVersion(ctx context.Context, jpID int64, version int32) (exists bool, err error) { stmt := ` SELECT exists ( SELECT 1 @@ -557,12 +564,12 @@ SELECT exists ( ); ` - err = o.q.WithOpts(qopts...).Get(&exists, stmt, jpID, version) + err = o.ds.GetContext(ctx, &exists, stmt, jpID, version) return exists, errors.Wrap(err, "JobProposalSpecVersionExists failed") } // DeleteProposal performs a soft delete of the job proposal by setting the status to deleted -func (o *orm) DeleteProposal(id int64, qopts ...pg.QOpt) error { +func (o *orm) DeleteProposal(ctx context.Context, id int64) error { // Get the latest spec for the proposal. stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at @@ -577,7 +584,7 @@ AND job_proposal_id = $1 ` var spec JobProposalSpec - err := o.q.WithOpts(qopts...).Get(&spec, stmt, id) + err := o.ds.GetContext(ctx, &spec, stmt, id) if err != nil { return err } @@ -593,7 +600,7 @@ SET status = $1, WHERE id = $2; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, JobProposalStatusDeleted, id, pendingUpdate) + result, err := o.ds.ExecContext(ctx, stmt, JobProposalStatusDeleted, id, pendingUpdate) if err != nil { return err } @@ -610,20 +617,20 @@ WHERE id = $2; } // GetSpec fetches the job proposal spec by id -func (o *orm) GetSpec(id int64, qopts ...pg.QOpt) (*JobProposalSpec, error) { +func (o *orm) GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs WHERE id = $1; ` var spec JobProposalSpec - err := o.q.WithOpts(qopts...).Get(&spec, stmt, id) + err := o.ds.GetContext(ctx, &spec, stmt, id) return &spec, errors.Wrap(err, "CreateJobProposalSpec failed") } // GetApprovedSpec gets the approved spec for a job proposal -func (o *orm) GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*JobProposalSpec, error) { +func (o *orm) GetApprovedSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs @@ -632,13 +639,13 @@ AND job_proposal_id = $2 ` var spec JobProposalSpec - err := o.q.WithOpts(qopts...).Get(&spec, stmt, SpecStatusApproved, jpID) + err := o.ds.GetContext(ctx, &spec, stmt, SpecStatusApproved, jpID) return &spec, errors.Wrap(err, "GetApprovedSpec failed") } // GetLatestSpec gets the latest spec for a job proposal. -func (o *orm) GetLatestSpec(jpID int64) (*JobProposalSpec, error) { +func (o *orm) GetLatestSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs @@ -652,26 +659,26 @@ AND job_proposal_id = $1 ` var spec JobProposalSpec - err := o.q.Get(&spec, stmt, jpID) + err := o.ds.GetContext(ctx, &spec, stmt, jpID) return &spec, errors.Wrap(err, "GetLatestSpec failed") } // ListSpecsByJobProposalIDs lists the specs which belong to any of job proposal // ids. -func (o *orm) ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposalSpec, error) { +func (o *orm) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs WHERE job_proposal_id = ANY($1) ` var specs []JobProposalSpec - err := o.q.WithOpts(qopts...).Select(&specs, stmt, ids) + err := o.ds.SelectContext(ctx, &specs, stmt, ids) return specs, errors.Wrap(err, "GetJobProposalsByManagersIDs failed") } // RejectSpec rejects the spec and updates the job proposal -func (o *orm) RejectSpec(id int64, qopts ...pg.QOpt) error { +func (o *orm) RejectSpec(ctx context.Context, id int64) error { stmt := ` UPDATE job_proposal_specs SET status = $1, @@ -682,7 +689,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, SpecStatusRejected, id); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, SpecStatusRejected, id); err != nil { return err } @@ -700,7 +707,7 @@ SET status = ( WHERE id = $1 ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, jpID) + result, err := o.ds.ExecContext(ctx, stmt, jpID) if err != nil { return err } @@ -719,7 +726,7 @@ WHERE id = $1 // RevokeSpec revokes a job proposal with a pending job spec. An approved // proposal cannot be revoked. A revoked proposal's job spec cannot be approved // or edited, but the job can be reproposed by FMS. -func (o *orm) RevokeSpec(id int64, qopts ...pg.QOpt) error { +func (o *orm) RevokeSpec(ctx context.Context, id int64) error { // Update the status of the spec stmt := ` UPDATE job_proposal_specs @@ -736,7 +743,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, id, SpecStatusRevoked); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, id, SpecStatusRevoked); err != nil { return err } @@ -760,7 +767,7 @@ SET status = ( WHERE id = $1 ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, jpID, nil, JobProposalStatusRevoked) + result, err := o.ds.ExecContext(ctx, stmt, jpID, nil, JobProposalStatusRevoked) if err != nil { return err } @@ -777,7 +784,7 @@ WHERE id = $1 } // UpdateSpecDefinition updates the definition of a job proposal spec by id. -func (o *orm) UpdateSpecDefinition(id int64, spec string, qopts ...pg.QOpt) error { +func (o *orm) UpdateSpecDefinition(ctx context.Context, id int64, spec string) error { stmt := ` UPDATE job_proposal_specs SET definition = $1, @@ -785,7 +792,7 @@ SET definition = $1, WHERE id = $2; ` - res, err := o.q.WithOpts(qopts...).Exec(stmt, spec, id) + res, err := o.ds.ExecContext(ctx, stmt, spec, id) if err != nil { return errors.Wrap(err, "UpdateSpecDefinition failed to update definition") } @@ -803,7 +810,7 @@ WHERE id = $2; } // IsJobManaged determines if a job is managed by the feeds manager. -func (o *orm) IsJobManaged(jobID int64, qopts ...pg.QOpt) (exists bool, err error) { +func (o *orm) IsJobManaged(ctx context.Context, jobID int64) (exists bool, err error) { stmt := ` SELECT exists ( SELECT 1 @@ -813,6 +820,6 @@ SELECT exists ( ); ` - err = o.q.WithOpts(qopts...).Get(&exists, stmt, jobID) + err = o.ds.GetContext(ctx, &exists, stmt, jobID) return exists, errors.Wrap(err, "IsJobManaged failed") } diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go index 3a0a17c99e0..df2624319f5 100644 --- a/core/services/feeds/orm_test.go +++ b/core/services/feeds/orm_test.go @@ -5,13 +5,12 @@ import ( "testing" "github.com/google/uuid" + "github.com/jmoiron/sqlx" "github.com/lib/pq" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -45,9 +44,8 @@ func setupORM(t *testing.T) *TestORM { t.Helper() var ( - db = pgtest.NewSqlxDB(t) - lggr = logger.TestLogger(t) - orm = feeds.NewORM(db, lggr, pgtest.NewQConfig(true)) + db = pgtest.NewSqlxDB(t) + orm = feeds.NewORM(db) ) return &TestORM{ORM: orm, db: db} @@ -57,6 +55,7 @@ func setupORM(t *testing.T) *TestORM { func Test_ORM_CreateManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -67,14 +66,14 @@ func Test_ORM_CreateManager(t *testing.T) { } ) - count, err := orm.CountManagers() + count, err := orm.CountManagers(ctx) require.NoError(t, err) require.Equal(t, int64(0), count) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - count, err = orm.CountManagers() + count, err = orm.CountManagers(ctx) require.NoError(t, err) require.Equal(t, int64(1), count) @@ -83,6 +82,7 @@ func Test_ORM_CreateManager(t *testing.T) { func Test_ORM_GetManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -93,10 +93,10 @@ func Test_ORM_GetManager(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - actual, err := orm.GetManager(id) + actual, err := orm.GetManager(ctx, id) require.NoError(t, err) assert.Equal(t, id, actual.ID) @@ -104,12 +104,13 @@ func Test_ORM_GetManager(t *testing.T) { assert.Equal(t, name, actual.Name) assert.Equal(t, publicKey, actual.PublicKey) - _, err = orm.GetManager(-1) + _, err = orm.GetManager(ctx, -1) require.Error(t, err) } func Test_ORM_ListManagers(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -120,10 +121,10 @@ func Test_ORM_ListManagers(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - mgrs, err := orm.ListManagers() + mgrs, err := orm.ListManagers(ctx) require.NoError(t, err) require.Len(t, mgrs, 1) @@ -136,6 +137,7 @@ func Test_ORM_ListManagers(t *testing.T) { func Test_ORM_ListManagersByIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -146,10 +148,10 @@ func Test_ORM_ListManagersByIDs(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - mgrs, err := orm.ListManagersByIDs([]int64{id}) + mgrs, err := orm.ListManagersByIDs(ctx, []int64{id}) require.NoError(t, err) require.Equal(t, 1, len(mgrs)) @@ -162,6 +164,7 @@ func Test_ORM_ListManagersByIDs(t *testing.T) { func Test_ORM_UpdateManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -172,7 +175,7 @@ func Test_ORM_UpdateManager(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) updatedMgr := feeds.FeedsManager{ @@ -182,10 +185,10 @@ func Test_ORM_UpdateManager(t *testing.T) { PublicKey: crypto.PublicKey([]byte("22222222222222222222222222222222")), } - err = orm.UpdateManager(updatedMgr) + err = orm.UpdateManager(ctx, updatedMgr) require.NoError(t, err) - actual, err := orm.GetManager(id) + actual, err := orm.GetManager(ctx, id) require.NoError(t, err) assert.Equal(t, updatedMgr.URI, actual.URI) @@ -197,6 +200,7 @@ func Test_ORM_UpdateManager(t *testing.T) { func Test_ORM_CreateChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -224,10 +228,10 @@ func Test_ORM_CreateChainConfig(t *testing.T) { } ) - id, err := orm.CreateChainConfig(cfg1) + id, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) - actual, err := orm.GetChainConfig(id) + actual, err := orm.GetChainConfig(ctx, id) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -244,6 +248,7 @@ func Test_ORM_CreateChainConfig(t *testing.T) { func Test_ORM_CreateBatchChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -264,12 +269,12 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { } ) - ids, err := orm.CreateBatchChainConfig([]feeds.ChainConfig{cfg1, cfg2}) + ids, err := orm.CreateBatchChainConfig(ctx, []feeds.ChainConfig{cfg1, cfg2}) require.NoError(t, err) assert.Len(t, ids, 2) - actual, err := orm.GetChainConfig(ids[0]) + actual, err := orm.GetChainConfig(ctx, ids[0]) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -283,7 +288,7 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { "ocr2Config": cfg1.OCR2Config, }, *actual) - actual, err = orm.GetChainConfig(ids[1]) + actual, err = orm.GetChainConfig(ctx, ids[1]) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -298,13 +303,14 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { }, *actual) // Test empty configs - ids, err = orm.CreateBatchChainConfig([]feeds.ChainConfig{}) + ids, err = orm.CreateBatchChainConfig(ctx, []feeds.ChainConfig{}) require.NoError(t, err) require.Empty(t, ids) } func Test_ORM_DeleteChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -318,22 +324,23 @@ func Test_ORM_DeleteChainConfig(t *testing.T) { } ) - id, err := orm.CreateChainConfig(cfg1) + id, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) - _, err = orm.GetChainConfig(id) + _, err = orm.GetChainConfig(ctx, id) require.NoError(t, err) - actual, err := orm.DeleteChainConfig(id) + actual, err := orm.DeleteChainConfig(ctx, id) require.NoError(t, err) require.Equal(t, id, actual) - _, err = orm.GetChainConfig(id) + _, err = orm.GetChainConfig(ctx, id) require.Error(t, err) } func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -361,10 +368,10 @@ func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { } ) - _, err := orm.CreateChainConfig(cfg1) + _, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) - actual, err := orm.ListChainConfigsByManagerIDs([]int64{fmID}) + actual, err := orm.ListChainConfigsByManagerIDs(ctx, []int64{fmID}) require.NoError(t, err) require.Len(t, actual, 1) @@ -382,6 +389,7 @@ func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { func Test_ORM_UpdateChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -414,15 +422,15 @@ func Test_ORM_UpdateChainConfig(t *testing.T) { } ) - id, err := orm.CreateChainConfig(cfg1) + id, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) updateCfg.ID = id - id, err = orm.UpdateChainConfig(updateCfg) + id, err = orm.UpdateChainConfig(ctx, updateCfg) require.NoError(t, err) - actual, err := orm.GetChainConfig(id) + actual, err := orm.GetChainConfig(ctx, id) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -441,6 +449,7 @@ func Test_ORM_UpdateChainConfig(t *testing.T) { func Test_ORM_CreateJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -452,14 +461,14 @@ func Test_ORM_CreateJobProposal(t *testing.T) { FeedsManagerID: fmID, } - count, err := orm.CountJobProposals() + count, err := orm.CountJobProposals(ctx) require.NoError(t, err) require.Equal(t, int64(0), count) - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - actual, err := orm.GetJobProposal(id) + actual, err := orm.GetJobProposal(ctx, id) require.NoError(t, err) require.Equal(t, jp.Name, actual.Name) require.Equal(t, jp.RemoteUUID, actual.RemoteUUID) @@ -474,6 +483,7 @@ func Test_ORM_CreateJobProposal(t *testing.T) { func Test_ORM_GetJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -495,10 +505,10 @@ func Test_ORM_GetJobProposal(t *testing.T) { FeedsManagerID: fmID, } - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - _, err = orm.CreateJobProposal(deletedJp) + _, err = orm.CreateJobProposal(ctx, deletedJp) require.NoError(t, err) assertJobEquals := func(actual *feeds.JobProposal) { @@ -512,32 +522,33 @@ func Test_ORM_GetJobProposal(t *testing.T) { } t.Run("by id", func(t *testing.T) { - actual, err := orm.GetJobProposal(id) + actual, err := orm.GetJobProposal(ctx, id) require.NoError(t, err) assert.Equal(t, id, actual.ID) assertJobEquals(actual) - _, err = orm.GetJobProposal(int64(0)) + _, err = orm.GetJobProposal(ctx, int64(0)) require.Error(t, err) }) t.Run("by remote uuid", func(t *testing.T) { - actual, err := orm.GetJobProposalByRemoteUUID(remoteUUID) + actual, err := orm.GetJobProposalByRemoteUUID(ctx, remoteUUID) require.NoError(t, err) assertJobEquals(actual) - _, err = orm.GetJobProposalByRemoteUUID(deletedUUID) + _, err = orm.GetJobProposalByRemoteUUID(ctx, deletedUUID) require.Error(t, err) - _, err = orm.GetJobProposalByRemoteUUID(uuid.New()) + _, err = orm.GetJobProposalByRemoteUUID(ctx, uuid.New()) require.Error(t, err) }) } func Test_ORM_ListJobProposals(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -551,10 +562,10 @@ func Test_ORM_ListJobProposals(t *testing.T) { FeedsManagerID: fmID, } - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - jps, err := orm.ListJobProposals() + jps, err := orm.ListJobProposals(ctx) require.NoError(t, err) require.Len(t, jps, 1) @@ -573,13 +584,14 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) *feeds.JobProposalCounts + before func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts wantApproved, wantRejected, wantDeleted, wantRevoked, wantPending, wantCancelled int64 }{ { name: "correctly counts when there are no job proposals", - before: func(orm *TestORM) *feeds.JobProposalCounts { - counts, err := orm.CountJobProposalsByStatus() + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -587,12 +599,13 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts a pending and cancelled job proposal by status", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -604,12 +617,13 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { // Verify that the counts are correct even if the proposal status is not pending. A // spec is considered pending if its status is pending OR pending_update is TRUE name: "correctly counts the pending specs when pending_update is true but the status itself is not pending", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) // Create a pending job proposal. jUUID := uuid.New() - jpID, err := orm.CreateJobProposal(&feeds.JobProposal{ + jpID, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jUUID, Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, @@ -617,7 +631,7 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { require.NoError(t, err) // Upsert the proposal and change its status to rejected - _, err = orm.UpsertJobProposal(&feeds.JobProposal{ + _, err = orm.UpsertJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jUUID, Status: feeds.JobProposalStatusRejected, FeedsManagerID: fmID, @@ -625,11 +639,11 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { require.NoError(t, err) // Assert that the upserted job proposal is now pending update. - jp, err := orm.GetJobProposal(jpID) + jp, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, true, jp.PendingUpdate) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -638,7 +652,8 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when approving a job proposal", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) // Create a pending job proposal. @@ -649,15 +664,15 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal to be approved - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) // Approve the pending job proposal. - err := orm.ApproveSpec(specID, jUUID) + err := orm.ApproveSpec(ctx, specID, jUUID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -666,16 +681,17 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when revoking a job proposal", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) // Revoke the pending job proposal. - err := orm.RevokeSpec(specID) + err := orm.RevokeSpec(ctx, specID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -684,16 +700,17 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when deleting a job proposal", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) createJobSpec(t, orm, jpID) // Delete the pending job proposal. - err := orm.DeleteProposal(jpID) + err := orm.DeleteProposal(ctx, jpID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -702,12 +719,13 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when deleting a job proposal with an approved spec", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) // Create a pending job proposal. jUUID := uuid.New() - jpID, err := orm.CreateJobProposal(&feeds.JobProposal{ + jpID, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jUUID, Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, @@ -719,18 +737,18 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal to be approved - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err = orm.ApproveSpec(specID, jUUID) + err = orm.ApproveSpec(ctx, specID, jUUID) require.NoError(t, err) // Delete the pending job proposal. - err = orm.DeleteProposal(jpID) + err = orm.DeleteProposal(ctx, jpID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -745,7 +763,7 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { t.Run(tc.name, func(t *testing.T) { orm := setupORM(t) - counts := tc.before(orm) + counts := tc.before(t, orm) assert.Equal(t, tc.wantPending, counts.Pending) assert.Equal(t, tc.wantApproved, counts.Approved) @@ -759,6 +777,7 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { func Test_ORM_ListJobProposalByManagersIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -772,10 +791,10 @@ func Test_ORM_ListJobProposalByManagersIDs(t *testing.T) { FeedsManagerID: fmID, } - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - jps, err := orm.ListJobProposalsByManagersIDs([]int64{fmID}) + jps, err := orm.ListJobProposalsByManagersIDs(ctx, []int64{fmID}) require.NoError(t, err) require.Len(t, jps, 1) @@ -791,18 +810,19 @@ func Test_ORM_ListJobProposalByManagersIDs(t *testing.T) { func Test_ORM_UpdateJobProposalStatus(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) - actualCreated, err := orm.GetJobProposal(jpID) + actualCreated, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) - err = orm.UpdateJobProposalStatus(jpID, feeds.JobProposalStatusRejected) + err = orm.UpdateJobProposalStatus(ctx, jpID, feeds.JobProposalStatusRejected) require.NoError(t, err) - actual, err := orm.GetJobProposal(jpID) + actual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, jpID, actual.ID) @@ -812,6 +832,7 @@ func Test_ORM_UpdateJobProposalStatus(t *testing.T) { func Test_ORM_UpsertJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -833,19 +854,19 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { // from pending to approved, and then approved to pending, and pending to deleted and so forth. // Create - count, err := orm.CountJobProposals() + count, err := orm.CountJobProposals(ctx) require.NoError(t, err) require.Equal(t, int64(0), count) - jpID, err := orm.UpsertJobProposal(jp) + jpID, err := orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) - createdActual, err := orm.GetJobProposal(jpID) + createdActual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.False(t, createdActual.PendingUpdate) - count, err = orm.CountJobProposals() + count, err = orm.CountJobProposals(ctx) require.NoError(t, err) require.Equal(t, int64(1), count) @@ -855,10 +876,10 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { jp.Multiaddrs = pq.StringArray{"dns/example.com"} jp.Name = null.StringFrom("jp1_updated") - jpID, err = orm.UpsertJobProposal(jp) + jpID, err = orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) - actual, err := orm.GetJobProposal(jpID) + actual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, jp.Name, actual.Name) assert.Equal(t, jp.Status, actual.Status) @@ -874,14 +895,14 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err = orm.ApproveSpec(specID, externalJobID.UUID) + err = orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) // Assert that the job proposal is now approved. @@ -893,10 +914,10 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { jp.Name = null.StringFrom("jp1_updated_again") jp.Status = feeds.JobProposalStatusPending - _, err = orm.UpsertJobProposal(jp) + _, err = orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, feeds.JobProposalStatusApproved, actual.Status) @@ -904,10 +925,10 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { assert.True(t, actual.PendingUpdate) // Delete the proposal - err = orm.DeleteProposal(jpID) + err = orm.DeleteProposal(ctx, jpID) require.NoError(t, err) - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, feeds.JobProposalStatusDeleted, actual.Status) @@ -915,11 +936,11 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { // Update deleted proposal jp.Status = feeds.JobProposalStatusRejected - jpID, err = orm.UpsertJobProposal(jp) + jpID, err = orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) // Ensure the deleted proposal does not get updated - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.NotEqual(t, jp.Status, actual.Status) assert.Equal(t, feeds.JobProposalStatusDeleted, actual.Status) @@ -929,6 +950,7 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { func Test_ORM_ApproveSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -937,7 +959,7 @@ func Test_ORM_ApproveSpec(t *testing.T) { ) // Manually create the job proposal to set pending update - jpID, err := orm.CreateJobProposal(&feeds.JobProposal{ + jpID, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: uuid.New(), Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, @@ -947,20 +969,20 @@ func Test_ORM_ApproveSpec(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err = orm.ApproveSpec(specID, externalJobID.UUID) + err = orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, feeds.SpecStatusApproved, actual.Status) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, externalJobID, actualJP.ExternalJobID) @@ -973,14 +995,14 @@ func Test_ORM_CancelSpec(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) (int64, int64) + before func(t *testing.T, orm *TestORM) (int64, int64) wantSpecStatus feeds.SpecStatus wantProposalStatus feeds.JobProposalStatus wantErr string }{ { name: "pending proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -992,7 +1014,7 @@ func Test_ORM_CancelSpec(t *testing.T) { }, { name: "deleted proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusDeleted, fmID) specID := createJobSpec(t, orm, jpID) @@ -1004,7 +1026,7 @@ func Test_ORM_CancelSpec(t *testing.T) { }, { name: "not found", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { return 0, 0 }, wantErr: "sql: no rows in result set", @@ -1015,24 +1037,25 @@ func Test_ORM_CancelSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID, specID := tc.before(orm) + jpID, specID := tc.before(t, orm) - err := orm.CancelSpec(specID) + err := orm.CancelSpec(ctx, specID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, tc.wantSpecStatus, actual.Status) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, tc.wantProposalStatus, actualJP.Status) @@ -1047,14 +1070,14 @@ func Test_ORM_DeleteProposal(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) int64 + before func(t *testing.T, orm *TestORM) int64 wantProposalStatus feeds.JobProposalStatus wantProposalPendingUpdate bool wantErr string }{ { name: "pending proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) createJobSpec(t, orm, jpID) @@ -1066,7 +1089,8 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "approved proposal with approved spec", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1074,11 +1098,11 @@ func Test_ORM_DeleteProposal(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) return jpID @@ -1088,7 +1112,8 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "approved proposal with pending spec", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1096,25 +1121,25 @@ func Test_ORM_DeleteProposal(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - jp, err := orm.GetJobProposal(jpID) + jp, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) // Update the proposal to pending and create a new pending spec - _, err = orm.UpsertJobProposal(&feeds.JobProposal{ + _, err = orm.UpsertJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jp.RemoteUUID, Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, }) require.NoError(t, err) - _, err = orm.CreateSpec(feeds.JobProposalSpec{ + _, err = orm.CreateSpec(ctx, feeds.JobProposalSpec{ Definition: "spec data", Version: 2, Status: feeds.SpecStatusPending, @@ -1129,7 +1154,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "cancelled proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) createJobSpec(t, orm, jpID) @@ -1141,7 +1166,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "rejected proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusRejected, fmID) createJobSpec(t, orm, jpID) @@ -1153,7 +1178,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "not found spec", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusRejected, fmID) @@ -1163,7 +1188,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "not found proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { return 0 }, wantErr: "sql: no rows in result set", @@ -1174,18 +1199,19 @@ func Test_ORM_DeleteProposal(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID := tc.before(orm) + jpID := tc.before(t, orm) - err := orm.DeleteProposal(jpID) + err := orm.DeleteProposal(ctx, jpID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actual, err := orm.GetJobProposal(jpID) + actual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, jpID, actual.ID) @@ -1201,7 +1227,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) (int64, int64) + before func(t *testing.T, orm *TestORM) (int64, int64) wantProposalStatus feeds.JobProposalStatus wantSpecStatus feeds.SpecStatus wantErr string @@ -1209,7 +1235,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }{ { name: "pending proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1222,7 +1248,8 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "approved proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1230,11 +1257,11 @@ func Test_ORM_RevokeSpec(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) return jpID, specID @@ -1244,7 +1271,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "cancelled proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) specID := createJobSpec(t, orm, jpID) @@ -1256,7 +1283,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "rejected proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusRejected, fmID) specID := createJobSpec(t, orm, jpID) @@ -1268,7 +1295,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "deleted proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusDeleted, fmID) specID := createJobSpec(t, orm, jpID) @@ -1280,7 +1307,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "not found", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { return 0, 0 }, wantErr: "sql: no rows in result set", @@ -1291,18 +1318,19 @@ func Test_ORM_RevokeSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID, specID := tc.before(orm) + jpID, specID := tc.before(t, orm) - err := orm.RevokeSpec(specID) + err := orm.RevokeSpec(ctx, specID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, tc.wantProposalStatus, actualJP.Status) @@ -1318,6 +1346,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { func Test_ORM_ExistsSpecByJobProposalIDAndVersion(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1327,17 +1356,18 @@ func Test_ORM_ExistsSpecByJobProposalIDAndVersion(t *testing.T) { createJobSpec(t, orm, jpID) - exists, err := orm.ExistsSpecByJobProposalIDAndVersion(jpID, 1) + exists, err := orm.ExistsSpecByJobProposalIDAndVersion(ctx, jpID, 1) require.NoError(t, err) require.True(t, exists) - exists, err = orm.ExistsSpecByJobProposalIDAndVersion(jpID, 2) + exists, err = orm.ExistsSpecByJobProposalIDAndVersion(ctx, jpID, 2) require.NoError(t, err) require.False(t, exists) } func Test_ORM_GetSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1346,7 +1376,7 @@ func Test_ORM_GetSpec(t *testing.T) { specID = createJobSpec(t, orm, jpID) ) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, "spec data", actual.Definition) @@ -1357,6 +1387,7 @@ func Test_ORM_GetSpec(t *testing.T) { func Test_ORM_GetApprovedSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1368,23 +1399,23 @@ func Test_ORM_GetApprovedSpec(t *testing.T) { // Defer the FK requirement of a job proposal so we don't have to setup a // real job. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - actual, err := orm.GetApprovedSpec(jpID) + actual, err := orm.GetApprovedSpec(ctx, jpID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, feeds.SpecStatusApproved, actual.Status) - err = orm.CancelSpec(specID) + err = orm.CancelSpec(ctx, specID) require.NoError(t, err) - _, err = orm.GetApprovedSpec(jpID) + _, err = orm.GetApprovedSpec(ctx, jpID) require.Error(t, err) assert.ErrorIs(t, err, sql.ErrNoRows) @@ -1392,6 +1423,7 @@ func Test_ORM_GetApprovedSpec(t *testing.T) { func Test_ORM_GetLatestSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1400,7 +1432,7 @@ func Test_ORM_GetLatestSpec(t *testing.T) { ) _ = createJobSpec(t, orm, jpID) - spec2ID, err := orm.CreateSpec(feeds.JobProposalSpec{ + spec2ID, err := orm.CreateSpec(ctx, feeds.JobProposalSpec{ Definition: "spec data", Version: 2, Status: feeds.SpecStatusPending, @@ -1408,7 +1440,7 @@ func Test_ORM_GetLatestSpec(t *testing.T) { }) require.NoError(t, err) - actual, err := orm.GetSpec(spec2ID) + actual, err := orm.GetSpec(ctx, spec2ID) require.NoError(t, err) assert.Equal(t, spec2ID, actual.ID) @@ -1420,6 +1452,7 @@ func Test_ORM_GetLatestSpec(t *testing.T) { func Test_ORM_ListSpecsByJobProposalIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1433,7 +1466,7 @@ func Test_ORM_ListSpecsByJobProposalIDs(t *testing.T) { createJobSpec(t, orm, jp1ID) createJobSpec(t, orm, jp2ID) - specs, err := orm.ListSpecsByJobProposalIDs([]int64{jp1ID, jp2ID}) + specs, err := orm.ListSpecsByJobProposalIDs(ctx, []int64{jp1ID, jp2ID}) require.NoError(t, err) require.Len(t, specs, 2) @@ -1457,14 +1490,14 @@ func Test_ORM_RejectSpec(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) (int64, int64) + before func(t *testing.T, orm *TestORM) (int64, int64) wantSpecStatus feeds.SpecStatus wantProposalStatus feeds.JobProposalStatus wantErr string }{ { name: "pending proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1476,7 +1509,8 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "approved proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1484,11 +1518,11 @@ func Test_ORM_RejectSpec(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) return jpID, specID @@ -1498,7 +1532,7 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "cancelled proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) specID := createJobSpec(t, orm, jpID) @@ -1510,7 +1544,7 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "deleted proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusDeleted, fmID) specID := createJobSpec(t, orm, jpID) @@ -1522,7 +1556,7 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "not found", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { return 0, 0 }, wantErr: "sql: no rows in result set", @@ -1533,24 +1567,25 @@ func Test_ORM_RejectSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID, specID := tc.before(orm) + jpID, specID := tc.before(t, orm) - err := orm.RejectSpec(specID) + err := orm.RejectSpec(ctx, specID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, tc.wantSpecStatus, actual.Status) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, tc.wantProposalStatus, actualJP.Status) @@ -1562,6 +1597,7 @@ func Test_ORM_RejectSpec(t *testing.T) { func Test_ORM_UpdateSpecDefinition(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1570,13 +1606,13 @@ func Test_ORM_UpdateSpecDefinition(t *testing.T) { specID = createJobSpec(t, orm, jpID) ) - prev, err := orm.GetSpec(specID) + prev, err := orm.GetSpec(ctx, specID) require.NoError(t, err) - err = orm.UpdateSpecDefinition(specID, "updated spec") + err = orm.UpdateSpecDefinition(ctx, specID, "updated spec") require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) @@ -1584,7 +1620,7 @@ func Test_ORM_UpdateSpecDefinition(t *testing.T) { require.Equal(t, "updated spec", actual.Definition) // Not found - err = orm.UpdateSpecDefinition(-1, "updated spec") + err = orm.UpdateSpecDefinition(ctx, -1, "updated spec") require.Error(t, err) } @@ -1592,6 +1628,7 @@ func Test_ORM_UpdateSpecDefinition(t *testing.T) { func Test_ORM_IsJobManaged(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1603,14 +1640,14 @@ func Test_ORM_IsJobManaged(t *testing.T) { j := createJob(t, orm.db, externalJobID.UUID) - isManaged, err := orm.IsJobManaged(int64(j.ID)) + isManaged, err := orm.IsJobManaged(ctx, int64(j.ID)) require.NoError(t, err) assert.False(t, isManaged) - err = orm.ApproveSpec(specID, externalJobID.UUID) + err = orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - isManaged, err = orm.IsJobManaged(int64(j.ID)) + isManaged, err = orm.IsJobManaged(ctx, int64(j.ID)) require.NoError(t, err) assert.True(t, isManaged) } @@ -1640,7 +1677,8 @@ func createFeedsManager(t *testing.T, orm feeds.ORM) int64 { PublicKey: publicKey, } - id, err := orm.CreateManager(mgr) + ctx := testutils.Context(t) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) return id @@ -1658,7 +1696,7 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { bridgeORM = bridges.NewORM(db) relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) ) - orm := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, config.Database()) + orm := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr) require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) @@ -1679,7 +1717,7 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(ctx, &jb) require.NoError(t, err) return &jb @@ -1688,7 +1726,8 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { func createJobProposal(t *testing.T, orm feeds.ORM, status feeds.JobProposalStatus, fmID int64) int64 { t.Helper() - id, err := orm.CreateJobProposal(&feeds.JobProposal{ + ctx := testutils.Context(t) + id, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: uuid.New(), Status: status, FeedsManagerID: fmID, @@ -1702,7 +1741,8 @@ func createJobProposal(t *testing.T, orm feeds.ORM, status feeds.JobProposalStat func createJobSpec(t *testing.T, orm feeds.ORM, jpID int64) int64 { t.Helper() - id, err := orm.CreateSpec(feeds.JobProposalSpec{ + ctx := testutils.Context(t) + id, err := orm.CreateSpec(ctx, feeds.JobProposalSpec{ Definition: "spec data", Version: 1, Status: feeds.SpecStatusPending, diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 8c4ea7a36bf..d6032befbdc 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -15,9 +15,8 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "gopkg.in/guregu/null.v4" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/plugins" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -33,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr" ocr2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) @@ -66,17 +64,17 @@ type Service interface { Start(ctx context.Context) error Close() error - CountManagers() (int64, error) - GetManager(id int64) (*FeedsManager, error) - ListManagers() ([]FeedsManager, error) - ListManagersByIDs(ids []int64) ([]FeedsManager, error) + CountManagers(ctx context.Context) (int64, error) + GetManager(ctx context.Context, id int64) (*FeedsManager, error) + ListManagers(ctx context.Context) ([]FeedsManager, error) + ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) RegisterManager(ctx context.Context, params RegisterManagerParams) (int64, error) UpdateManager(ctx context.Context, mgr FeedsManager) error CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) DeleteChainConfig(ctx context.Context, id int64) (int64, error) - GetChainConfig(id int64) (*ChainConfig, error) - ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) + GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) + ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, error) @@ -85,19 +83,17 @@ type Service interface { RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, error) SyncNodeInfo(ctx context.Context, id int64) error - CountJobProposalsByStatus() (*JobProposalCounts, error) - GetJobProposal(id int64) (*JobProposal, error) - ListJobProposals() ([]JobProposal, error) - ListJobProposalsByManagersIDs(ids []int64) ([]JobProposal, error) + CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) + GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) + ListJobProposals(ctx context.Context) ([]JobProposal, error) + ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) ApproveSpec(ctx context.Context, id int64, force bool) error CancelSpec(ctx context.Context, id int64) error - GetSpec(id int64) (*JobProposalSpec, error) - ListSpecsByJobProposalIDs(ids []int64) ([]JobProposalSpec, error) + GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) + ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) RejectSpec(ctx context.Context, id int64) error UpdateSpecDefinition(ctx context.Context, id int64, spec string) error - - Unsafe_SetConnectionsManager(ConnectionsManager) } type service struct { @@ -105,7 +101,7 @@ type service struct { orm ORM jobORM job.ORM - q pg.Q + ds sqlutil.DataSource csaKeyStore keystore.CSA p2pKeyStore keystore.P2P ocr1KeyStore keystore.OCR @@ -127,7 +123,7 @@ type service struct { func NewService( orm ORM, jobORM job.ORM, - db *sqlx.DB, + ds sqlutil.DataSource, jobSpawner job.Spawner, keyStore keystore.Master, gCfg GeneralConfig, @@ -135,7 +131,6 @@ func NewService( jobCfg JobConfig, ocrCfg OCRConfig, ocr2Cfg OCR2Config, - dbCfg pg.QConfig, legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger, version string, @@ -145,7 +140,7 @@ func NewService( svc := &service{ orm: orm, jobORM: jobORM, - q: pg.NewQ(db, lggr, dbCfg), + ds: ds, jobSpawner: jobSpawner, p2pKeyStore: keyStore.P2P(), csaKeyStore: keyStore.CSA(), @@ -178,7 +173,7 @@ type RegisterManagerParams struct { // // Only a single feeds manager is currently supported. func (s *service) RegisterManager(ctx context.Context, params RegisterManagerParams) (int64, error) { - count, err := s.CountManagers() + count, err := s.CountManagers(ctx) if err != nil { return 0, err } @@ -193,16 +188,16 @@ func (s *service) RegisterManager(ctx context.Context, params RegisterManagerPar } var id int64 - q := s.q.WithOpts(pg.WithParentCtx(ctx)) - err = q.Transaction(func(tx pg.Queryer) error { + + err = s.orm.Transact(ctx, func(tx ORM) error { var txerr error - id, txerr = s.orm.CreateManager(&mgr, pg.WithQueryer(tx)) + id, txerr = tx.CreateManager(ctx, &mgr) if err != nil { return txerr } - if _, txerr = s.orm.CreateBatchChainConfig(params.ChainConfigs, pg.WithQueryer(tx)); txerr != nil { + if _, txerr = tx.CreateBatchChainConfig(ctx, params.ChainConfigs); txerr != nil { return txerr } @@ -229,7 +224,7 @@ func (s *service) SyncNodeInfo(ctx context.Context, id int64) error { return errors.Wrap(err, "could not fetch client") } - cfgs, err := s.orm.ListChainConfigsByManagerIDs([]int64{id}) + cfgs, err := s.orm.ListChainConfigsByManagerIDs(ctx, []int64{id}) if err != nil { return errors.Wrap(err, "could not fetch chain configs") } @@ -259,17 +254,9 @@ func (s *service) SyncNodeInfo(ctx context.Context, id int64) error { // UpdateManager updates the feed manager details, takes down the // connection and reestablishes a new connection with the updated public key. func (s *service) UpdateManager(ctx context.Context, mgr FeedsManager) error { - q := s.q.WithOpts(pg.WithParentCtx(ctx)) - err := q.Transaction(func(tx pg.Queryer) error { - txerr := s.orm.UpdateManager(mgr, pg.WithQueryer(tx)) - if txerr != nil { - return errors.Wrap(txerr, "could not update manager") - } - - return nil - }) + err := s.orm.UpdateManager(ctx, mgr) if err != nil { - return err + return errors.Wrap(err, "could not update manager") } if err := s.restartConnection(ctx, mgr); err != nil { @@ -280,8 +267,8 @@ func (s *service) UpdateManager(ctx context.Context, mgr FeedsManager) error { } // ListManagerServices lists all the manager services. -func (s *service) ListManagers() ([]FeedsManager, error) { - managers, err := s.orm.ListManagers() +func (s *service) ListManagers(ctx context.Context) ([]FeedsManager, error) { + managers, err := s.orm.ListManagers(ctx) if err != nil { return nil, errors.Wrap(err, "failed to get a list of managers") } @@ -294,8 +281,8 @@ func (s *service) ListManagers() ([]FeedsManager, error) { } // GetManager gets a manager service by id. -func (s *service) GetManager(id int64) (*FeedsManager, error) { - manager, err := s.orm.GetManager(id) +func (s *service) GetManager(ctx context.Context, id int64) (*FeedsManager, error) { + manager, err := s.orm.GetManager(ctx, id) if err != nil { return nil, errors.Wrap(err, "failed to get manager by ID") } @@ -305,8 +292,8 @@ func (s *service) GetManager(id int64) (*FeedsManager, error) { } // ListManagersByIDs get managers services by ids. -func (s *service) ListManagersByIDs(ids []int64) ([]FeedsManager, error) { - managers, err := s.orm.ListManagersByIDs(ids) +func (s *service) ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) { + managers, err := s.orm.ListManagersByIDs(ctx, ids) if err != nil { return nil, errors.Wrap(err, "failed to list managers by IDs") } @@ -319,8 +306,8 @@ func (s *service) ListManagersByIDs(ids []int64) ([]FeedsManager, error) { } // CountManagers gets the total number of manager services -func (s *service) CountManagers() (int64, error) { - return s.orm.CountManagers() +func (s *service) CountManagers(ctx context.Context) (int64, error) { + return s.orm.CountManagers(ctx) } // CreateChainConfig creates a chain config. @@ -333,12 +320,12 @@ func (s *service) CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64 } } - id, err := s.orm.CreateChainConfig(cfg) + id, err := s.orm.CreateChainConfig(ctx, cfg) if err != nil { return 0, errors.Wrap(err, "CreateChainConfig failed") } - mgr, err := s.orm.GetManager(cfg.FeedsManagerID) + mgr, err := s.orm.GetManager(ctx, cfg.FeedsManagerID) if err != nil { return 0, errors.Wrap(err, "CreateChainConfig: failed to fetch manager") } @@ -352,17 +339,17 @@ func (s *service) CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64 // DeleteChainConfig deletes the chain config by id. func (s *service) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { - cfg, err := s.orm.GetChainConfig(id) + cfg, err := s.orm.GetChainConfig(ctx, id) if err != nil { return 0, errors.Wrap(err, "DeleteChainConfig failed: could not get chain config") } - _, err = s.orm.DeleteChainConfig(id) + _, err = s.orm.DeleteChainConfig(ctx, id) if err != nil { return 0, errors.Wrap(err, "DeleteChainConfig failed") } - mgr, err := s.orm.GetManager(cfg.FeedsManagerID) + mgr, err := s.orm.GetManager(ctx, cfg.FeedsManagerID) if err != nil { return 0, errors.Wrap(err, "DeleteChainConfig: failed to fetch manager") } @@ -374,8 +361,8 @@ func (s *service) DeleteChainConfig(ctx context.Context, id int64) (int64, error return id, nil } -func (s *service) GetChainConfig(id int64) (*ChainConfig, error) { - cfg, err := s.orm.GetChainConfig(id) +func (s *service) GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) { + cfg, err := s.orm.GetChainConfig(ctx, id) if err != nil { return nil, errors.Wrap(err, "GetChainConfig failed") } @@ -383,8 +370,8 @@ func (s *service) GetChainConfig(id int64) (*ChainConfig, error) { return cfg, nil } -func (s *service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) { - cfgs, err := s.orm.ListChainConfigsByManagerIDs(mgrIDs) +func (s *service) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) { + cfgs, err := s.orm.ListChainConfigsByManagerIDs(ctx, mgrIDs) return cfgs, errors.Wrap(err, "ListChainConfigsByManagerIDs failed") } @@ -398,12 +385,12 @@ func (s *service) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64 } } - id, err := s.orm.UpdateChainConfig(cfg) + id, err := s.orm.UpdateChainConfig(ctx, cfg) if err != nil { return 0, errors.Wrap(err, "UpdateChainConfig failed") } - ccfg, err := s.orm.GetChainConfig(cfg.ID) + ccfg, err := s.orm.GetChainConfig(ctx, cfg.ID) if err != nil { return 0, errors.Wrap(err, "UpdateChainConfig failed: could not get chain config") } @@ -419,13 +406,13 @@ func (s *service) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64 // // When we support multiple feed managers, we will need to change this to filter // by feeds manager -func (s *service) ListJobProposals() ([]JobProposal, error) { - return s.orm.ListJobProposals() +func (s *service) ListJobProposals(ctx context.Context) ([]JobProposal, error) { + return s.orm.ListJobProposals(ctx) } // ListJobProposalsByManagersIDs gets job proposals by feeds managers IDs -func (s *service) ListJobProposalsByManagersIDs(ids []int64) ([]JobProposal, error) { - return s.orm.ListJobProposalsByManagersIDs(ids) +func (s *service) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { + return s.orm.ListJobProposalsByManagersIDs(ctx, ids) } // DeleteJobArgs are the arguments to provide to the DeleteJob method. @@ -437,7 +424,7 @@ type DeleteJobArgs struct { // DeleteJob deletes a job proposal if it exist. The feeds manager id check // ensures that only the intended feed manager can make this request. func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, error) { - proposal, err := s.orm.GetJobProposalByRemoteUUID(args.RemoteUUID) + proposal, err := s.orm.GetJobProposalByRemoteUUID(ctx, args.RemoteUUID) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return 0, errors.Wrap(err, "GetJobProposalByRemoteUUID failed to check existence of job proposal") @@ -456,14 +443,13 @@ func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, er return 0, errors.New("cannot delete a job proposal belonging to another feeds manager") } - pctx := pg.WithParentCtx(ctx) - if err = s.orm.DeleteProposal(proposal.ID, pctx); err != nil { + if err = s.orm.DeleteProposal(ctx, proposal.ID); err != nil { s.lggr.Errorw("Failed to delete the proposal", "err", err) return 0, errors.Wrap(err, "DeleteProposal failed") } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job proposal deletion", err) } @@ -479,7 +465,7 @@ type RevokeJobArgs struct { // RevokeJob revokes a pending job proposal if it exist. The feeds manager // id check ensures that only the intended feed manager can make this request. func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, error) { - proposal, err := s.orm.GetJobProposalByRemoteUUID(args.RemoteUUID) + proposal, err := s.orm.GetJobProposalByRemoteUUID(ctx, args.RemoteUUID) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return 0, errors.Wrap(err, "GetJobProposalByRemoteUUID failed to check existence of job proposal") @@ -495,7 +481,7 @@ func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, er } // get the latest spec for the proposal - latest, err := s.orm.GetLatestSpec(proposal.ID) + latest, err := s.orm.GetLatestSpec(ctx, proposal.ID) if err != nil { return 0, errors.Wrap(err, "GetLatestSpec failed to get latest spec") } @@ -504,8 +490,7 @@ func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, er return 0, errors.New("only pending job specs can be revoked") } - pctx := pg.WithParentCtx(ctx) - if err = s.orm.RevokeSpec(latest.ID, pctx); err != nil { + if err = s.orm.RevokeSpec(ctx, latest.ID); err != nil { s.lggr.Errorw("Failed to revoke the proposal", "err", err) return 0, errors.Wrap(err, "RevokeSpec failed") @@ -516,7 +501,7 @@ func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, er "job_proposal_spec_id", latest.ID, ) - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for revoke job", err) } @@ -545,7 +530,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, return 0, err } - existing, err := s.orm.GetJobProposalByRemoteUUID(args.RemoteUUID) + existing, err := s.orm.GetJobProposalByRemoteUUID(ctx, args.RemoteUUID) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return 0, errors.Wrap(err, "failed to check existence of job proposal") @@ -562,7 +547,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, // Check the version being proposed has not been previously proposed. var exists bool - exists, err = s.orm.ExistsSpecByJobProposalIDAndVersion(existing.ID, args.Version) + exists, err = s.orm.ExistsSpecByJobProposalIDAndVersion(ctx, existing.ID, args.Version) if err != nil { return 0, errors.Wrap(err, "failed to check existence of spec") } @@ -577,32 +562,31 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, ) var id int64 - q := s.q.WithOpts(pg.WithParentCtx(ctx)) - err = q.Transaction(func(tx pg.Queryer) error { + err = s.orm.Transact(ctx, func(tx ORM) error { var txerr error // Parse the Job Spec TOML to extract the name name := extractName(args.Spec) // Upsert job proposal - id, txerr = s.orm.UpsertJobProposal(&JobProposal{ + id, txerr = tx.UpsertJobProposal(ctx, &JobProposal{ Name: name, RemoteUUID: args.RemoteUUID, Status: JobProposalStatusPending, FeedsManagerID: args.FeedsManagerID, Multiaddrs: args.Multiaddrs, - }, pg.WithQueryer(tx)) + }) if txerr != nil { return errors.Wrap(txerr, "failed to upsert job proposal") } // Create the spec version - _, txerr = s.orm.CreateSpec(JobProposalSpec{ + _, txerr = tx.CreateSpec(ctx, JobProposalSpec{ Definition: args.Spec, Status: SpecStatusPending, Version: args.Version, JobProposalID: id, - }, pg.WithQueryer(tx)) + }) if txerr != nil { return errors.Wrap(txerr, "failed to create spec") } @@ -616,7 +600,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, // Track the given job proposal request promJobProposalRequest.Inc() - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for propose job", err) } @@ -624,20 +608,18 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, } // GetJobProposal gets a job proposal by id. -func (s *service) GetJobProposal(id int64) (*JobProposal, error) { - return s.orm.GetJobProposal(id) +func (s *service) GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) { + return s.orm.GetJobProposal(ctx, id) } // CountJobProposalsByStatus returns the count of job proposals with a given status. -func (s *service) CountJobProposalsByStatus() (*JobProposalCounts, error) { - return s.orm.CountJobProposalsByStatus() +func (s *service) CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) { + return s.orm.CountJobProposalsByStatus(ctx) } // RejectSpec rejects a spec. func (s *service) RejectSpec(ctx context.Context, id int64) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { return errors.Wrap(err, "orm: job proposal spec") } @@ -647,7 +629,7 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { return errors.New("must be a pending job proposal spec") } - proposal, err := s.orm.GetJobProposal(spec.JobProposalID, pctx) + proposal, err := s.orm.GetJobProposal(ctx, spec.JobProposalID) if err != nil { return errors.Wrap(err, "orm: job proposal") } @@ -662,9 +644,8 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { "job_proposal_spec_id", id, ) - q := s.q.WithOpts(pctx) - err = q.Transaction(func(tx pg.Queryer) error { - if err = s.orm.RejectSpec(id, pg.WithQueryer(tx)); err != nil { + err = s.orm.Transact(ctx, func(tx ORM) error { + if err = tx.RejectSpec(ctx, id); err != nil { return err } @@ -681,7 +662,7 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { return errors.Wrap(err, "could not reject job proposal") } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job rejection", err) } @@ -690,25 +671,23 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { // IsJobManaged determines is a job is managed by the Feeds Manager. func (s *service) IsJobManaged(ctx context.Context, jobID int64) (bool, error) { - return s.orm.IsJobManaged(jobID, pg.WithParentCtx(ctx)) + return s.orm.IsJobManaged(ctx, jobID) } // ApproveSpec approves a spec for a job proposal and creates a job with the // spec. func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { return errors.Wrap(err, "orm: job proposal spec") } - proposal, err := s.orm.GetJobProposal(spec.JobProposalID, pctx) + proposal, err := s.orm.GetJobProposal(ctx, spec.JobProposalID) if err != nil { return errors.Wrap(err, "orm: job proposal") } - if err = s.isApprovable(proposal.Status, proposal.ID, spec.Status, spec.ID); err != nil { + if err = s.isApprovable(ctx, proposal.Status, proposal.ID, spec.Status, spec.ID); err != nil { return err } @@ -741,17 +720,14 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { return errors.Wrap(err, "failed to approve job spec due to bridge check") } - q := s.q.WithOpts(pctx) - err = q.Transaction(func(tx pg.Queryer) error { + err = s.transact(ctx, func(tx datasources) error { var ( txerr error existingJobID int32 - - pgOpts = pg.WithQueryer(tx) ) // Use the external job id to check if a job already exists - foundJob, txerr := s.jobORM.FindJobByExternalJobID(j.ExternalJobID, pgOpts) + foundJob, txerr := tx.jobORM.FindJobByExternalJobID(ctx, j.ExternalJobID) if txerr != nil { // Return an error if the repository errors. If there is a not found // error we want to continue with approving the job. @@ -768,7 +744,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { if existingJobID == 0 { switch j.Type { case job.OffchainReporting, job.FluxMonitor: - existingJobID, txerr = s.findExistingJobForOCRFlux(j, pgOpts) + existingJobID, txerr = findExistingJobForOCRFlux(ctx, j, tx.jobORM) if txerr != nil { // Return an error if the repository errors. If there is a not found // error we want to continue with approving the job. @@ -777,7 +753,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } } case job.OffchainReporting2, job.Bootstrap: - existingJobID, txerr = s.findExistingJobForOCR2(j, pgOpts) + existingJobID, txerr = findExistingJobForOCR2(ctx, j, tx.jobORM) if txerr != nil { // Return an error if the repository errors. If there is a not found // error we want to continue with approving the job. @@ -798,7 +774,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } // Check if the job is managed by FMS - approvedSpec, serr := s.orm.GetApprovedSpec(proposal.ID, pgOpts) + approvedSpec, serr := tx.orm.GetApprovedSpec(ctx, proposal.ID) if serr != nil { if !errors.Is(serr, sql.ErrNoRows) { logger.Errorw("Failed to get approved spec", "err", serr) @@ -811,7 +787,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { // If a spec is found, cancel the existing job spec if serr == nil { - if cerr := s.orm.CancelSpec(approvedSpec.ID, pgOpts); cerr != nil { + if cerr := tx.orm.CancelSpec(ctx, approvedSpec.ID); cerr != nil { logger.Errorw("Failed to delete the cancel the spec", "err", cerr) return cerr @@ -819,7 +795,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } // Delete the job - if serr = s.jobSpawner.DeleteJob(existingJobID, pgOpts); serr != nil { + if serr = s.jobSpawner.DeleteJob(ctx, tx.ds, existingJobID); serr != nil { logger.Errorw("Failed to delete the job", "err", serr) return errors.Wrap(serr, "DeleteJob failed") @@ -827,14 +803,14 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } // Create the job - if txerr = s.jobSpawner.CreateJob(j, pgOpts); txerr != nil { + if txerr = s.jobSpawner.CreateJob(ctx, tx.ds, j); txerr != nil { logger.Errorw("Failed to create job", "err", txerr) return txerr } // Approve the job proposal spec - if txerr = s.orm.ApproveSpec(id, j.ExternalJobID, pgOpts); txerr != nil { + if txerr = tx.orm.ApproveSpec(ctx, id, j.ExternalJobID); txerr != nil { logger.Errorw("Failed to approve spec", "err", txerr) return txerr @@ -856,18 +832,32 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { return errors.Wrap(err, "could not approve job proposal") } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job approval", err) } return nil } +type datasources struct { + ds sqlutil.DataSource + orm ORM + jobORM job.ORM +} + +func (s *service) transact(ctx context.Context, fn func(datasources) error) error { + return sqlutil.Transact(ctx, func(tx sqlutil.DataSource) datasources { + return datasources{ + ds: tx, + orm: s.orm.WithDataSource(tx), + jobORM: s.jobORM.WithDataSource(tx), + } + }, s.ds, nil, fn) +} + // CancelSpec cancels a spec for a job proposal. func (s *service) CancelSpec(ctx context.Context, id int64) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { return errors.Wrap(err, "orm: job proposal spec") } @@ -876,7 +866,7 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { return errors.New("must be an approved job proposal spec") } - jp, err := s.orm.GetJobProposal(spec.JobProposalID, pg.WithParentCtx(ctx)) + jp, err := s.orm.GetJobProposal(ctx, spec.JobProposalID) if err != nil { return errors.Wrap(err, "orm: job proposal") } @@ -891,20 +881,18 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { "job_proposal_spec_id", id, ) - q := s.q.WithOpts(pctx) - err = q.Transaction(func(tx pg.Queryer) error { + err = s.transact(ctx, func(tx datasources) error { var ( - txerr error - pgOpts = pg.WithQueryer(tx) + txerr error ) - if txerr = s.orm.CancelSpec(id, pgOpts); txerr != nil { + if txerr = tx.orm.CancelSpec(ctx, id); txerr != nil { return txerr } // Delete the job if jp.ExternalJobID.Valid { - j, txerr := s.jobORM.FindJobByExternalJobID(jp.ExternalJobID.UUID, pgOpts) + j, txerr := tx.jobORM.FindJobByExternalJobID(ctx, jp.ExternalJobID.UUID) if txerr != nil { // Return an error if the repository errors. If there is a not found error we want // to continue with cancelling the spec but we won't have to cancel any jobs. @@ -914,7 +902,7 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { } if txerr == nil { - if serr := s.jobSpawner.DeleteJob(j.ID, pgOpts); serr != nil { + if serr := s.jobSpawner.DeleteJob(ctx, tx.ds, j.ID); serr != nil { return errors.Wrap(serr, "DeleteJob failed") } } @@ -934,7 +922,7 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { return err } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job cancellation", err) } @@ -942,20 +930,18 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { } // ListSpecsByJobProposalIDs gets the specs which belong to the job proposal ids. -func (s *service) ListSpecsByJobProposalIDs(ids []int64) ([]JobProposalSpec, error) { - return s.orm.ListSpecsByJobProposalIDs(ids) +func (s *service) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) { + return s.orm.ListSpecsByJobProposalIDs(ctx, ids) } // GetSpec gets the spec details by id. -func (s *service) GetSpec(id int64) (*JobProposalSpec, error) { - return s.orm.GetSpec(id) +func (s *service) GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) { + return s.orm.GetSpec(ctx, id) } // UpdateSpecDefinition updates the spec's TOML definition. func (s *service) UpdateSpecDefinition(ctx context.Context, id int64, defn string) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return errors.Wrap(err, "job proposal spec does not exist") @@ -969,7 +955,7 @@ func (s *service) UpdateSpecDefinition(ctx context.Context, id int64, defn strin } // Update the spec definition - if err = s.orm.UpdateSpecDefinition(id, defn, pctx); err != nil { + if err = s.orm.UpdateSpecDefinition(ctx, id, defn); err != nil { return errors.Wrap(err, "could not update job proposal") } @@ -985,7 +971,7 @@ func (s *service) Start(ctx context.Context) error { } // We only support a single feeds manager right now - mgrs, err := s.ListManagers() + mgrs, err := s.ListManagers(ctx) if err != nil { return err } @@ -998,7 +984,7 @@ func (s *service) Start(ctx context.Context) error { mgr := mgrs[0] s.connectFeedManager(ctx, mgr, privkey) - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { s.lggr.Error("failed to observe job proposal count when starting service", err) } @@ -1052,8 +1038,8 @@ func (s *service) getCSAPrivateKey() (privkey []byte, err error) { // observeJobProposalCounts is a helper method that queries the repository for the count of // job proposals by status and then updates prometheus gauges. -func (s *service) observeJobProposalCounts() error { - counts, err := s.CountJobProposalsByStatus() +func (s *service) observeJobProposalCounts(ctx context.Context) error { + counts, err := s.CountJobProposalsByStatus(ctx) if err != nil { return errors.Wrap(err, "failed to fetch counts of job proposals") } @@ -1073,18 +1059,8 @@ func (s *service) observeJobProposalCounts() error { return nil } -// Unsafe_SetConnectionsManager sets the ConnectionsManager on the service. -// -// We need to be able to inject a mock for the client to facilitate integration -// tests. -// -// ONLY TO BE USED FOR TESTING. -func (s *service) Unsafe_SetConnectionsManager(connMgr ConnectionsManager) { - s.connMgr = connMgr -} - // findExistingJobForOCR2 looks for existing job for OCR2 -func (s *service) findExistingJobForOCR2(j *job.Job, qopts pg.QOpt) (int32, error) { +func findExistingJobForOCR2(ctx context.Context, j *job.Job, tx job.ORM) (int32, error) { var contractID string var feedID *common.Hash @@ -1103,11 +1079,11 @@ func (s *service) findExistingJobForOCR2(j *job.Job, qopts pg.QOpt) (int32, erro return 0, errors.Errorf("unsupported job type: %s", j.Type) } - return s.jobORM.FindOCR2JobIDByAddress(contractID, feedID, qopts) + return tx.FindOCR2JobIDByAddress(ctx, contractID, feedID) } // findExistingJobForOCRFlux looks for existing job for OCR or flux -func (s *service) findExistingJobForOCRFlux(j *job.Job, qopts pg.QOpt) (int32, error) { +func findExistingJobForOCRFlux(ctx context.Context, j *job.Job, tx job.ORM) (int32, error) { var address types.EIP55Address var evmChainID *big.Big @@ -1124,7 +1100,7 @@ func (s *service) findExistingJobForOCRFlux(j *job.Job, qopts pg.QOpt) (int32, e return 0, errors.Errorf("unsupported job type: %s", j.Type) } - return s.jobORM.FindJobIDByAddress(address, evmChainID, qopts) + return tx.FindJobIDByAddress(ctx, address, evmChainID) } // generateJob validates and generates a job from a spec. @@ -1354,7 +1330,7 @@ func extractName(defn string) null.String { // isApprovable returns nil if a spec can be approved based on the current // proposal and spec status, and if it can't be approved, the reason as an // error. -func (s *service) isApprovable(propStatus JobProposalStatus, proposalID int64, specStatus SpecStatus, specID int64) error { +func (s *service) isApprovable(ctx context.Context, propStatus JobProposalStatus, proposalID int64, specStatus SpecStatus, specID int64) error { if propStatus == JobProposalStatusDeleted { return errors.New("cannot approve spec for a deleted job proposal") } @@ -1372,7 +1348,7 @@ func (s *service) isApprovable(propStatus JobProposalStatus, proposalID int64, s return errors.New("cannot approve a revoked spec") case SpecStatusCancelled: // Allowed to approve a cancelled job if it is the latest job - latest, serr := s.orm.GetLatestSpec(proposalID) + latest, serr := s.orm.GetLatestSpec(ctx, proposalID) if serr != nil { return errors.Wrap(serr, "failed to get latest spec") } @@ -1405,46 +1381,46 @@ func (ns NullService) Close() error { return nil } func (ns NullService) ApproveSpec(ctx context.Context, id int64, force bool) error { return ErrFeedsManagerDisabled } -func (ns NullService) CountManagers() (int64, error) { return 0, nil } -func (ns NullService) CountJobProposalsByStatus() (*JobProposalCounts, error) { +func (ns NullService) CountManagers(ctx context.Context) (int64, error) { return 0, nil } +func (ns NullService) CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) CancelSpec(ctx context.Context, id int64) error { return ErrFeedsManagerDisabled } -func (ns NullService) GetJobProposal(id int64) (*JobProposal, error) { +func (ns NullService) GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) ListSpecsByJobProposalIDs(ids []int64) ([]JobProposalSpec, error) { +func (ns NullService) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) GetManager(id int64) (*FeedsManager, error) { +func (ns NullService) GetManager(ctx context.Context, id int64) (*FeedsManager, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) ListManagersByIDs(ids []int64) ([]FeedsManager, error) { +func (ns NullService) ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) GetSpec(id int64) (*JobProposalSpec, error) { +func (ns NullService) GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) ListManagers() ([]FeedsManager, error) { return nil, nil } +func (ns NullService) ListManagers(ctx context.Context) ([]FeedsManager, error) { return nil, nil } func (ns NullService) CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) { return 0, ErrFeedsManagerDisabled } -func (ns NullService) GetChainConfig(id int64) (*ChainConfig, error) { +func (ns NullService) GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { return 0, ErrFeedsManagerDisabled } -func (ns NullService) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) { +func (ns NullService) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) { return 0, ErrFeedsManagerDisabled } -func (ns NullService) ListJobProposals() ([]JobProposal, error) { return nil, nil } -func (ns NullService) ListJobProposalsByManagersIDs(ids []int64) ([]JobProposal, error) { +func (ns NullService) ListJobProposals(ctx context.Context) ([]JobProposal, error) { return nil, nil } +func (ns NullService) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, error) { @@ -1472,6 +1448,5 @@ func (ns NullService) IsJobManaged(ctx context.Context, jobID int64) (bool, erro func (ns NullService) UpdateSpecDefinition(ctx context.Context, id int64, spec string) error { return ErrFeedsManagerDisabled } -func (ns NullService) Unsafe_SetConnectionsManager(_ ConnectionsManager) {} //revive:enable diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index f83a98986e2..af656618f78 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -186,7 +186,7 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * keyStore.On("P2P").Return(p2pKeystore) keyStore.On("OCR").Return(ocr1Keystore) keyStore.On("OCR2").Return(ocr2Keystore) - svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), gcfg.Database(), legacyChains, lggr, "1.0.0", nil) + svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), legacyChains, lggr, "1.0.0", nil) svc.SetConnectionsManager(connMgr) return &TestService{ @@ -233,14 +233,19 @@ func Test_Service_RegisterManager(t *testing.T) { svc := setupTestService(t) - svc.orm.On("CountManagers").Return(int64(0), nil) - svc.orm.On("CreateManager", &mgr, mock.Anything). + svc.orm.On("CountManagers", mock.Anything).Return(int64(0), nil) + svc.orm.On("CreateManager", mock.Anything, &mgr, mock.Anything). Return(id, nil) - svc.orm.On("CreateBatchChainConfig", params.ChainConfigs, mock.Anything). + svc.orm.On("CreateBatchChainConfig", mock.Anything, params.ChainConfigs, mock.Anything). Return([]int64{}, nil) svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) // ListManagers runs in a goroutine so it might be called. svc.orm.On("ListManagers", testutils.Context(t)).Return([]feeds.FeedsManager{mgr}, nil).Maybe() + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})) actual, err := svc.RegisterManager(testutils.Context(t), params) @@ -254,6 +259,7 @@ func Test_Service_RegisterManager(t *testing.T) { func Test_Service_ListManagers(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( mgr = feeds.FeedsManager{} @@ -261,10 +267,10 @@ func Test_Service_ListManagers(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListManagers").Return(mgrs, nil) + svc.orm.On("ListManagers", mock.Anything).Return(mgrs, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) - actual, err := svc.ListManagers() + actual, err := svc.ListManagers(ctx) require.NoError(t, err) assert.Equal(t, mgrs, actual) @@ -272,6 +278,7 @@ func Test_Service_ListManagers(t *testing.T) { func Test_Service_GetManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -279,11 +286,11 @@ func Test_Service_GetManager(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("GetManager", id). + svc.orm.On("GetManager", mock.Anything, id). Return(&mgr, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) - actual, err := svc.GetManager(id) + actual, err := svc.GetManager(ctx, id) require.NoError(t, err) assert.Equal(t, actual, &mgr) @@ -298,7 +305,7 @@ func Test_Service_UpdateFeedsManager(t *testing.T) { svc := setupTestService(t) - svc.orm.On("UpdateManager", mgr, mock.Anything).Return(nil) + svc.orm.On("UpdateManager", mock.Anything, mgr, mock.Anything).Return(nil) svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) svc.connMgr.On("Disconnect", mgr.ID).Return(nil) svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})).Return(nil) @@ -309,6 +316,7 @@ func Test_Service_UpdateFeedsManager(t *testing.T) { func Test_Service_ListManagersByIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( mgr = feeds.FeedsManager{} @@ -316,11 +324,11 @@ func Test_Service_ListManagersByIDs(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListManagersByIDs", []int64{mgr.ID}). + svc.orm.On("ListManagersByIDs", mock.Anything, []int64{mgr.ID}). Return(mgrs, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) - actual, err := svc.ListManagersByIDs([]int64{mgr.ID}) + actual, err := svc.ListManagersByIDs(ctx, []int64{mgr.ID}) require.NoError(t, err) assert.Equal(t, mgrs, actual) @@ -328,16 +336,17 @@ func Test_Service_ListManagersByIDs(t *testing.T) { func Test_Service_CountManagers(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( count = int64(1) ) svc := setupTestService(t) - svc.orm.On("CountManagers"). + svc.orm.On("CountManagers", mock.Anything). Return(count, nil) - actual, err := svc.CountManagers() + actual, err := svc.CountManagers(ctx) require.NoError(t, err) assert.Equal(t, count, actual) @@ -369,10 +378,10 @@ func Test_Service_CreateChainConfig(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("CreateChainConfig", cfg).Return(int64(1), nil) - svc.orm.On("GetManager", mgr.ID).Return(&mgr, nil) + svc.orm.On("CreateChainConfig", mock.Anything, cfg).Return(int64(1), nil) + svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -430,11 +439,11 @@ func Test_Service_DeleteChainConfig(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("GetChainConfig", cfg.ID).Return(&cfg, nil) - svc.orm.On("DeleteChainConfig", cfg.ID).Return(cfg.ID, nil) - svc.orm.On("GetManager", mgr.ID).Return(&mgr, nil) + svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) + svc.orm.On("DeleteChainConfig", mock.Anything, cfg.ID).Return(cfg.ID, nil) + svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return([]feeds.ChainConfig{}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{}, nil) svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{}, @@ -446,6 +455,7 @@ func Test_Service_DeleteChainConfig(t *testing.T) { } func Test_Service_ListChainConfigsByManagerIDs(t *testing.T) { + ctx := testutils.Context(t) var ( mgr = feeds.FeedsManager{ID: 1} cfg = feeds.ChainConfig{ @@ -457,9 +467,9 @@ func Test_Service_ListChainConfigsByManagerIDs(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("ListChainConfigsByManagerIDs", ids).Return([]feeds.ChainConfig{cfg}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, ids).Return([]feeds.ChainConfig{cfg}, nil) - actual, err := svc.ListChainConfigsByManagerIDs(ids) + actual, err := svc.ListChainConfigsByManagerIDs(ctx, ids) require.NoError(t, err) assert.Equal(t, []feeds.ChainConfig{cfg}, actual) } @@ -484,10 +494,10 @@ func Test_Service_UpdateChainConfig(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("UpdateChainConfig", cfg).Return(int64(1), nil) - svc.orm.On("GetChainConfig", cfg.ID).Return(&cfg, nil) + svc.orm.On("UpdateChainConfig", mock.Anything, cfg).Return(int64(1), nil) + svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -640,10 +650,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (Flux Monitor)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(idFluxMonitor, nil) - svc.orm.On("CreateSpec", specFluxMonitor, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(idFluxMonitor, nil) + svc.orm.On("CreateSpec", mock.Anything, specFluxMonitor).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantID: idFluxMonitor, @@ -651,10 +666,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (OCR1)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpOCR1.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpOCR1, mock.Anything).Return(idOCR1, nil) - svc.orm.On("CreateSpec", specOCR1, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpOCR1.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpOCR1).Return(idOCR1, nil) + svc.orm.On("CreateSpec", mock.Anything, specOCR1).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsOCR1, wantID: idOCR1, @@ -662,10 +682,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (OCR2)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpOCR2.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpOCR2, mock.Anything).Return(idOCR2, nil) - svc.orm.On("CreateSpec", specOCR2, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpOCR2.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpOCR2).Return(idOCR2, nil) + svc.orm.On("CreateSpec", mock.Anything, specOCR2).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsOCR2, wantID: idOCR2, @@ -673,10 +698,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (Bootstrap)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpBootstrap.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpBootstrap, mock.Anything).Return(idBootstrap, nil) - svc.orm.On("CreateSpec", specBootstrap, mock.Anything).Return(int64(102), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpBootstrap.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpBootstrap).Return(idBootstrap, nil) + svc.orm.On("CreateSpec", mock.Anything, specBootstrap).Return(int64(102), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsBootstrap, wantID: idBootstrap, @@ -685,16 +715,21 @@ func Test_Service_ProposeJob(t *testing.T) { name: "Update success", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: jpFluxMonitor.FeedsManagerID, RemoteUUID: jpFluxMonitor.RemoteUUID, Status: feeds.JobProposalStatusPending, }, nil) - svc.orm.On("ExistsSpecByJobProposalIDAndVersion", jpFluxMonitor.ID, argsFluxMonitor.Version).Return(false, nil) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(idFluxMonitor, nil) - svc.orm.On("CreateSpec", specFluxMonitor, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("ExistsSpecByJobProposalIDAndVersion", mock.Anything, jpFluxMonitor.ID, argsFluxMonitor.Version).Return(false, nil) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(idFluxMonitor, nil) + svc.orm.On("CreateSpec", mock.Anything, specFluxMonitor).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantID: idFluxMonitor, @@ -717,7 +752,7 @@ func Test_Service_ProposeJob(t *testing.T) { name: "ensure an upsert validates the job proposal belongs to the feeds manager", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: 2, RemoteUUID: jpFluxMonitor.RemoteUUID, @@ -730,13 +765,13 @@ func Test_Service_ProposeJob(t *testing.T) { name: "spec version already exists", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: jpFluxMonitor.FeedsManagerID, RemoteUUID: jpFluxMonitor.RemoteUUID, Status: feeds.JobProposalStatusPending, }, nil) - svc.orm.On("ExistsSpecByJobProposalIDAndVersion", jpFluxMonitor.ID, argsFluxMonitor.Version).Return(true, nil) + svc.orm.On("ExistsSpecByJobProposalIDAndVersion", mock.Anything, jpFluxMonitor.ID, argsFluxMonitor.Version).Return(true, nil) }, args: argsFluxMonitor, wantErr: "proposed job spec version already exists", @@ -744,8 +779,13 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "upsert error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(int64(0), errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(int64(0), errors.New("orm error")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantErr: "failed to upsert job proposal", @@ -753,9 +793,14 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create spec error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(idFluxMonitor, nil) - svc.orm.On("CreateSpec", specFluxMonitor, mock.Anything).Return(int64(0), errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(idFluxMonitor, nil) + svc.orm.On("CreateSpec", mock.Anything, specFluxMonitor).Return(int64(0), errors.New("orm error")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantErr: "failed to create spec", @@ -820,9 +865,9 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "Delete success", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(&approved, nil) - svc.orm.On("DeleteProposal", approved.ID, mock.Anything).Return(nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) + svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, args: args, wantID: approved.ID, @@ -831,7 +876,7 @@ func Test_Service_DeleteJob(t *testing.T) { name: "Job proposal being deleted belongs to the feeds manager", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", approved.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: 2, RemoteUUID: approved.RemoteUUID, @@ -844,7 +889,7 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "Get proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(nil, errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(nil, errors.New("orm error")) }, args: args, wantErr: "GetJobProposalByRemoteUUID failed", @@ -852,7 +897,7 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "No proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(nil, sql.ErrNoRows) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(nil, sql.ErrNoRows) }, args: args, wantErr: "GetJobProposalByRemoteUUID did not find any proposals to delete", @@ -860,8 +905,8 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "Delete proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(&approved, nil) - svc.orm.On("DeleteProposal", approved.ID, mock.Anything).Return(errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) + svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(errors.New("orm error")) }, args: args, wantErr: "DeleteProposal failed", @@ -960,10 +1005,10 @@ answer1 [type=median index=0]; { name: "Revoke success when latest spec status is pending", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(pendingSpec, nil) - svc.orm.On("RevokeSpec", pendingSpec.ID, mock.Anything).Return(nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(pendingSpec, nil) + svc.orm.On("RevokeSpec", mock.Anything, pendingSpec.ID).Return(nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, args: args, wantID: pendingProposal.ID, @@ -971,16 +1016,16 @@ answer1 [type=median index=0]; { name: "Revoke success when latest spec status is cancelled", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusCancelled, JobProposalID: pendingProposal.ID, Version: 1, Definition: defn, }, nil) - svc.orm.On("RevokeSpec", pendingSpec.ID, mock.Anything).Return(nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("RevokeSpec", mock.Anything, pendingSpec.ID).Return(nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, args: args, wantID: pendingProposal.ID, @@ -989,7 +1034,7 @@ answer1 [type=median index=0]; name: "Job proposal being revoked belongs to the feeds manager", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: 2, RemoteUUID: pendingProposal.RemoteUUID, @@ -1002,7 +1047,7 @@ answer1 [type=median index=0]; { name: "Get proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(nil, errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(nil, errors.New("orm error")) }, args: args, wantErr: "GetJobProposalByRemoteUUID failed", @@ -1010,7 +1055,7 @@ answer1 [type=median index=0]; { name: "No proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(nil, sql.ErrNoRows) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(nil, sql.ErrNoRows) }, args: args, wantErr: "GetJobProposalByRemoteUUID did not find any proposals to revoke", @@ -1018,8 +1063,8 @@ answer1 [type=median index=0]; { name: "Get latest spec error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(nil, sql.ErrNoRows) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(nil, sql.ErrNoRows) }, args: args, wantErr: "GetLatestSpec failed to get latest spec", @@ -1027,8 +1072,8 @@ answer1 [type=median index=0]; { name: "Not revokable due to spec status approved", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusApproved, JobProposalID: pendingProposal.ID, @@ -1042,8 +1087,8 @@ answer1 [type=median index=0]; { name: "Not revokable due to spec status rejected", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusRejected, JobProposalID: pendingProposal.ID, @@ -1057,8 +1102,8 @@ answer1 [type=median index=0]; { name: "Not revokable due to spec status already revoked", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusRevoked, JobProposalID: pendingProposal.ID, @@ -1072,13 +1117,13 @@ answer1 [type=median index=0]; { name: "Not revokable due to proposal status deleted", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(&feeds.JobProposal{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(&feeds.JobProposal{ ID: 1, FeedsManagerID: 1, RemoteUUID: remoteUUID, Status: feeds.JobProposalStatusDeleted, }, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(pendingSpec, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(pendingSpec, nil) }, args: args, wantErr: "only pending job specs can be revoked", @@ -1086,9 +1131,9 @@ answer1 [type=median index=0]; { name: "Revoke proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(pendingSpec, nil) - svc.orm.On("RevokeSpec", pendingSpec.ID, mock.Anything).Return(errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(pendingSpec, nil) + svc.orm.On("RevokeSpec", mock.Anything, pendingSpec.ID).Return(errors.New("orm error")) }, args: args, wantErr: "RevokeSpec failed", @@ -1168,7 +1213,7 @@ func Test_Service_SyncNodeInfo(t *testing.T) { svc := setupTestService(t) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return(chainConfigs, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return(chainConfigs, nil) // OCR1 key fetching svc.p2pKeystore.On("Get", p2pKey.PeerID()).Return(p2pKey, nil) @@ -1227,7 +1272,7 @@ func Test_Service_IsJobManaged(t *testing.T) { ctx := testutils.Context(t) jobID := int64(1) - svc.orm.On("IsJobManaged", jobID, mock.Anything).Return(true, nil) + svc.orm.On("IsJobManaged", mock.Anything, jobID).Return(true, nil) isManaged, err := svc.IsJobManaged(ctx, jobID) require.NoError(t, err) @@ -1236,6 +1281,7 @@ func Test_Service_IsJobManaged(t *testing.T) { func Test_Service_ListJobProposals(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( jp = feeds.JobProposal{} @@ -1243,10 +1289,10 @@ func Test_Service_ListJobProposals(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListJobProposals"). + svc.orm.On("ListJobProposals", mock.Anything). Return(jps, nil) - actual, err := svc.ListJobProposals() + actual, err := svc.ListJobProposals(ctx) require.NoError(t, err) assert.Equal(t, actual, jps) @@ -1254,6 +1300,7 @@ func Test_Service_ListJobProposals(t *testing.T) { func Test_Service_ListJobProposalsByManagersIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( jp = feeds.JobProposal{} @@ -1262,10 +1309,10 @@ func Test_Service_ListJobProposalsByManagersIDs(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListJobProposalsByManagersIDs", fmIDs). + svc.orm.On("ListJobProposalsByManagersIDs", mock.Anything, fmIDs). Return(jps, nil) - actual, err := svc.ListJobProposalsByManagersIDs(fmIDs) + actual, err := svc.ListJobProposalsByManagersIDs(ctx, fmIDs) require.NoError(t, err) assert.Equal(t, actual, jps) @@ -1273,6 +1320,7 @@ func Test_Service_ListJobProposalsByManagersIDs(t *testing.T) { func Test_Service_GetJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -1280,10 +1328,10 @@ func Test_Service_GetJobProposal(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("GetJobProposal", id). + svc.orm.On("GetJobProposal", mock.Anything, id). Return(&ms, nil) - actual, err := svc.GetJobProposal(id) + actual, err := svc.GetJobProposal(ctx, id) require.NoError(t, err) assert.Equal(t, actual, &ms) @@ -1320,12 +1368,12 @@ func Test_Service_CancelSpec(t *testing.T) { name: "success", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1334,7 +1382,9 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.CancelledJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, }, @@ -1342,14 +1392,14 @@ func Test_Service_CancelSpec(t *testing.T) { name: "success without external job id", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(&feeds.JobProposal{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(&feeds.JobProposal{ ID: 1, RemoteUUID: externalJobID, FeedsManagerID: 100, }, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), &proto.CancelledJobRequest{ @@ -1357,7 +1407,9 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.CancelledJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, }, @@ -1365,11 +1417,11 @@ func Test_Service_CancelSpec(t *testing.T) { name: "success without jobs", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), &proto.CancelledJobRequest{ @@ -1377,14 +1429,16 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.CancelledJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, }, { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, specID: spec.ID, wantErr: "orm: job proposal spec: Not Found", @@ -1396,7 +1450,7 @@ func Test_Service_CancelSpec(t *testing.T) { ID: spec.ID, Status: feeds.SpecStatusPending, } - svc.orm.On("GetSpec", pspec.ID, mock.Anything).Return(pspec, nil) + svc.orm.On("GetSpec", mock.Anything, pspec.ID, mock.Anything).Return(pspec, nil) }, specID: spec.ID, wantErr: "must be an approved job proposal spec", @@ -1404,8 +1458,8 @@ func Test_Service_CancelSpec(t *testing.T) { { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, specID: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -1413,8 +1467,8 @@ func Test_Service_CancelSpec(t *testing.T) { { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, specID: spec.ID, @@ -1424,9 +1478,11 @@ func Test_Service_CancelSpec(t *testing.T) { name: "cancel spec orm fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(errors.New("failure")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "failure", @@ -1435,11 +1491,13 @@ func Test_Service_CancelSpec(t *testing.T) { name: "find by external uuid orm fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, errors.New("failure")) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "FindJobByExternalJobID failed: failure", @@ -1448,12 +1506,14 @@ func Test_Service_CancelSpec(t *testing.T) { name: "delete job fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(errors.New("failure")) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "DeleteJob failed: failure", @@ -1462,12 +1522,12 @@ func Test_Service_CancelSpec(t *testing.T) { name: "cancelled job rpc call fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1476,6 +1536,8 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "failure", @@ -1509,6 +1571,7 @@ func Test_Service_CancelSpec(t *testing.T) { func Test_Service_GetSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -1516,10 +1579,10 @@ func Test_Service_GetSpec(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("GetSpec", id). + svc.orm.On("GetSpec", mock.Anything, id). Return(&spec, nil) - actual, err := svc.GetSpec(id) + actual, err := svc.GetSpec(ctx, id) require.NoError(t, err) assert.Equal(t, &spec, actual) @@ -1527,6 +1590,7 @@ func Test_Service_GetSpec(t *testing.T) { func Test_Service_ListSpecsByJobProposalIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -1536,10 +1600,10 @@ func Test_Service_ListSpecsByJobProposalIDs(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListSpecsByJobProposalIDs", []int64{jpID}). + svc.orm.On("ListSpecsByJobProposalIDs", mock.Anything, []int64{jpID}). Return(specs, nil) - actual, err := svc.ListSpecsByJobProposalIDs([]int64{jpID}) + actual, err := svc.ListSpecsByJobProposalIDs(ctx, []int64{jpID}) require.NoError(t, err) assert.Equal(t, specs, actual) @@ -1624,26 +1688,27 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, mock.IsType(uuid.UUID{}), - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1652,7 +1717,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -1662,27 +1729,28 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(cancelledSpec, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, cancelledSpec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1691,7 +1759,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: cancelledSpec.ID, force: false, @@ -1701,8 +1771,8 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec2, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec2, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -1711,8 +1781,8 @@ answer1 [type=median index=0]; { name: "failed due to proposal being revoked", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(&feeds.JobProposal{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(&feeds.JobProposal{ ID: 1, Status: feeds.JobProposalStatusRevoked, }, nil) @@ -1724,8 +1794,8 @@ answer1 [type=median index=0]; { name: "failed due to proposal being deleted", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(&feeds.JobProposal{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(&feeds.JobProposal{ ID: jp.ID, Status: feeds.JobProposalStatusDeleted, }, nil) @@ -1742,8 +1812,8 @@ answer1 [type=median index=0]; Status: feeds.SpecStatusApproved, JobProposalID: jp.ID, } - svc.orm.On("GetSpec", aspec.ID, mock.Anything).Return(aspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, aspec.ID, mock.Anything).Return(aspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -1752,8 +1822,8 @@ answer1 [type=median index=0]; { name: "rejected spec fail", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: rejectedSpec.ID, force: false, @@ -1762,9 +1832,9 @@ answer1 [type=median index=0]; { name: "cancelled spec failed not latest spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 21, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, @@ -1781,11 +1851,13 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -1796,12 +1868,14 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -1812,27 +1886,28 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1841,7 +1916,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1851,28 +1928,29 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1881,7 +1959,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1891,29 +1971,30 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1922,7 +2003,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1930,7 +2013,7 @@ answer1 [type=median index=0]; { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, force: false, @@ -1939,8 +2022,8 @@ answer1 [type=median index=0]; { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -1950,8 +2033,8 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) }, id: spec.ID, @@ -1960,8 +2043,8 @@ answer1 [type=median index=0]; { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, id: spec.ID, @@ -1973,11 +2056,13 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1988,12 +2073,14 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2004,12 +2091,14 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2020,13 +2109,15 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2036,22 +2127,25 @@ answer1 [type=median index=0]; name: "create job error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). Return(errors.New("could not save")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2061,28 +2155,31 @@ answer1 [type=median index=0]; name: "approve spec orm error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2092,27 +2189,28 @@ answer1 [type=median index=0]; name: "fms call error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2121,6 +2219,8 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2268,25 +2368,26 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2295,7 +2396,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2305,27 +2408,28 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(cancelledSpec, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, cancelledSpec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2334,7 +2438,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: cancelledSpec.ID, force: false, @@ -2342,9 +2448,9 @@ updateInterval = "20m" { name: "cancelled spec failed not latest spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 21, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, @@ -2359,8 +2465,8 @@ updateInterval = "20m" { name: "rejected spec failed cannot be approved", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: rejectedSpec.ID, force: false, @@ -2371,11 +2477,13 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2386,27 +2494,28 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2415,7 +2524,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2425,33 +2536,34 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, Version: 1, Definition: fmt.Sprintf(defn2, externalJobID.String(), &feedID), }, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, &feedID, mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, &feedID).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2460,7 +2572,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2470,28 +2584,29 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2500,7 +2615,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2508,7 +2625,7 @@ updateInterval = "20m" { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, force: false, @@ -2522,8 +2639,8 @@ updateInterval = "20m" JobProposalID: jp.ID, Status: feeds.SpecStatusApproved, } - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(aspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(aspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -2537,8 +2654,8 @@ updateInterval = "20m" JobProposalID: jp.ID, Status: feeds.SpecStatusRejected, } - svc.orm.On("GetSpec", rspec.ID, mock.Anything).Return(rspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, rspec.ID, mock.Anything).Return(rspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -2547,8 +2664,8 @@ updateInterval = "20m" { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -2558,8 +2675,8 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) }, id: spec.ID, @@ -2568,8 +2685,8 @@ updateInterval = "20m" { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, id: spec.ID, @@ -2580,22 +2697,25 @@ updateInterval = "20m" name: "create job error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). Return(errors.New("could not save")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2605,28 +2725,31 @@ updateInterval = "20m" name: "approve spec orm error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2636,27 +2759,28 @@ updateInterval = "20m" name: "fms call error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2665,6 +2789,8 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2774,25 +2900,26 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2801,7 +2928,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2811,27 +2940,28 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(cancelledSpec, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, cancelledSpec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2840,7 +2970,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: cancelledSpec.ID, force: false, @@ -2848,9 +2980,9 @@ chainID = 0 { name: "cancelled spec failed not latest spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 21, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, @@ -2865,8 +2997,8 @@ chainID = 0 { name: "rejected spec failed cannot be approved", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: rejectedSpec.ID, force: false, @@ -2877,11 +3009,13 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2892,27 +3026,28 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2921,7 +3056,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2931,33 +3068,34 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, Version: 1, Definition: fmt.Sprintf(defn2, externalJobID.String(), feedID), }, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, &feedID, mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, &feedID).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2966,7 +3104,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2976,28 +3116,29 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -3006,7 +3147,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -3014,7 +3157,7 @@ chainID = 0 { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, force: false, @@ -3028,8 +3171,8 @@ chainID = 0 JobProposalID: jp.ID, Status: feeds.SpecStatusApproved, } - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(aspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(aspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -3043,8 +3186,8 @@ chainID = 0 JobProposalID: jp.ID, Status: feeds.SpecStatusRejected, } - svc.orm.On("GetSpec", rspec.ID, mock.Anything).Return(rspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, rspec.ID).Return(rspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -3053,8 +3196,8 @@ chainID = 0 { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -3064,8 +3207,8 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) }, id: spec.ID, @@ -3074,8 +3217,8 @@ chainID = 0 { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, id: spec.ID, @@ -3086,22 +3229,25 @@ chainID = 0 name: "create job error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). Return(errors.New("could not save")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -3111,28 +3257,31 @@ chainID = 0 name: "approve spec orm error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -3142,27 +3291,28 @@ chainID = 0 name: "fms call error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -3171,6 +3321,8 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -3227,12 +3379,12 @@ func Test_Service_RejectSpec(t *testing.T) { { name: "Success", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.orm.On("RejectSpec", - spec.ID, mock.Anything, + spec.ID, ).Return(nil) svc.fmsClient.On("RejectedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -3241,20 +3393,25 @@ func Test_Service_RejectSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.RejectedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, }, { name: "Fails to get spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("failure")) }, wantErr: "failure", }, { name: "Cannot be a rejected proposal", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ Status: feeds.SpecStatusRejected, }, nil) }, @@ -3263,16 +3420,16 @@ func Test_Service_RejectSpec(t *testing.T) { { name: "Fails to get proposal", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("failure")) }, wantErr: "failure", }, { name: "FMS not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("disconnected")) }, wantErr: "disconnected", @@ -3280,18 +3437,23 @@ func Test_Service_RejectSpec(t *testing.T) { { name: "Fails to update spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.orm.On("RejectSpec", mock.Anything, mock.Anything).Return(errors.New("failure")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, wantErr: "failure", }, { name: "Fails to update spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.orm.On("RejectSpec", mock.Anything, mock.Anything).Return(nil) svc.fmsClient. @@ -3302,6 +3464,11 @@ func Test_Service_RejectSpec(t *testing.T) { Version: int64(spec.Version), }). Return(nil, errors.New("rpc failure")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, wantErr: "rpc failure", }, @@ -3352,9 +3519,9 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { name: "success", before: func(svc *TestService) { svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(spec, nil) - svc.orm.On("UpdateSpecDefinition", + svc.orm.On("UpdateSpecDefinition", mock.Anything, specID, updatedSpec, mock.Anything, @@ -3366,7 +3533,7 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { name: "does not exist", before: func(svc *TestService) { svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(nil, sql.ErrNoRows) }, specID: specID, @@ -3376,7 +3543,7 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { name: "other get errors", before: func(svc *TestService) { svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(nil, errors.New("other db error")) }, specID: specID, @@ -3391,7 +3558,7 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { } svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(spec, nil) }, specID: specID, @@ -3443,18 +3610,18 @@ func Test_Service_StartStop(t *testing.T) { name: "success with a feeds manager connection", beforeFunc: func(svc *TestService) { svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) - svc.orm.On("ListManagers").Return([]feeds.FeedsManager{mgr}, nil) + svc.orm.On("ListManagers", mock.Anything).Return([]feeds.FeedsManager{mgr}, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})) svc.connMgr.On("Close") - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, }, { name: "success with no registered managers", beforeFunc: func(svc *TestService) { svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) - svc.orm.On("ListManagers").Return([]feeds.FeedsManager{}, nil) + svc.orm.On("ListManagers", mock.Anything).Return([]feeds.FeedsManager{}, nil) svc.connMgr.On("Close") }, }, diff --git a/core/services/fluxmonitorv2/delegate.go b/core/services/fluxmonitorv2/delegate.go index b7b0df77cc4..1f0b72877ff 100644 --- a/core/services/fluxmonitorv2/delegate.go +++ b/core/services/fluxmonitorv2/delegate.go @@ -5,8 +5,7 @@ import ( "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -25,7 +24,7 @@ type DelegateConfig interface { // Delegate represents a Flux Monitor delegate type Delegate struct { cfg DelegateConfig - db *sqlx.DB + ds sqlutil.DataSource ethKeyStore keystore.Eth jobORM job.ORM pipelineORM pipeline.ORM @@ -43,13 +42,13 @@ func NewDelegate( jobORM job.ORM, pipelineORM pipeline.ORM, pipelineRunner pipeline.Runner, - db *sqlx.DB, + ds sqlutil.DataSource, legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger, ) *Delegate { return &Delegate{ cfg: cfg, - db: db, + ds: ds, ethKeyStore: ethKeyStore, jobORM: jobORM, pipelineORM: pipelineORM, @@ -86,8 +85,8 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] fm, err := NewFromJobSpec( jb, - d.db, - NewORM(d.db, d.lggr, chain.TxManager(), strategy, checker), + d.ds, + NewORM(d.ds, d.lggr, chain.TxManager(), strategy, checker), d.jobORM, d.pipelineORM, NewKeyStore(d.ethKeyStore), diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go index 5eebb319030..dd30156e15e 100644 --- a/core/services/fluxmonitorv2/flux_monitor.go +++ b/core/services/fluxmonitorv2/flux_monitor.go @@ -13,8 +13,6 @@ import ( "github.com/pkg/errors" "github.com/shopspring/decimal" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -149,7 +147,7 @@ func NewFluxMonitor( // validation. func NewFromJobSpec( jobSpec job.Job, - db *sqlx.DB, + ds sqlutil.DataSource, orm ORM, jobORM job.ORM, pipelineORM pipeline.ORM, @@ -250,7 +248,7 @@ func NewFromJobSpec( pipelineRunner, jobSpec, *jobSpec.PipelineSpec, - db, + ds, orm, jobORM, pipelineORM, @@ -760,7 +758,7 @@ func (fm *FluxMonitor) respondToNewRoundLog(log flux_aggregator_wrapper.FluxAggr result, err := results.FinalResult(newRoundLogger).SingularResult() if err != nil || result.Error != nil { newRoundLogger.Errorw("can't fetch answer", "err", err, "result", result) - fm.jobORM.TryRecordError(fm.spec.JobID, "Error polling") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Error polling") return } answer, err := utils.ToDecimal(result.Value) @@ -865,7 +863,7 @@ func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker roundState, err := fm.roundState(0) if err != nil { l.Errorw("unable to determine eligibility to submit from FluxAggregator contract", "err", err) - fm.jobORM.TryRecordError(fm.spec.JobID, + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Unable to call roundState method on provided contract. Check contract address.", ) @@ -885,7 +883,7 @@ func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker roundStateNew, err2 := fm.roundState(roundState.RoundId) if err2 != nil { l.Errorw("unable to determine eligibility to submit from FluxAggregator contract", "err", err2) - fm.jobORM.TryRecordError(fm.spec.JobID, + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Unable to call roundState method on provided contract. Check contract address.", ) @@ -962,13 +960,13 @@ func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker run, results, err := fm.runner.ExecuteRun(ctx, fm.spec, vars, fm.logger) if err != nil { l.Errorw("can't fetch answer", "err", err) - fm.jobORM.TryRecordError(fm.spec.JobID, "Error polling") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Error polling") return } result, err := results.FinalResult(l).SingularResult() if err != nil || result.Error != nil { l.Errorw("can't fetch answer", "err", err, "result", result) - fm.jobORM.TryRecordError(fm.spec.JobID, "Error polling") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Error polling") return } answer, err := utils.ToDecimal(result.Value) @@ -1041,7 +1039,7 @@ func (fm *FluxMonitor) isValidSubmission(ctx context.Context, l logger.Logger, a "max", fm.submissionChecker.Max, "answer", answer, ) - fm.jobORM.TryRecordError(fm.spec.JobID, "Answer is outside acceptable range") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Answer is outside acceptable range") jobId := fm.spec.JobID jobName := fm.spec.JobName diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index 2ac424bceab..b3a5bcee6b9 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -515,6 +515,7 @@ func TestFluxMonitor_PollIfEligible_Creates_JobErr(t *testing.T) { tm.jobORM. On("TryRecordError", + mock.Anything, pipelineSpec.JobID, "Unable to call roundState method on provided contract. Check contract address.", ).Once() diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index 7a967300867..6b9dcb99262 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -24,9 +24,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -43,7 +42,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -393,32 +391,34 @@ func assertNoSubmission(t *testing.T, // assertPipelineRunCreated checks that a pipeline exists for a given round and // verifies the answer -func assertPipelineRunCreated(t *testing.T, db *sqlx.DB, roundID int64, result int64) pipeline.Run { +func assertPipelineRunCreated(t *testing.T, ds sqlutil.DataSource, roundID int64, result int64) pipeline.Run { + ctx := testutils.Context(t) // Fetch the stats to extract the run id stats := fluxmonitorv2.FluxMonitorRoundStatsV2{} - require.NoError(t, db.Get(&stats, "SELECT * FROM flux_monitor_round_stats_v2 WHERE round_id = $1", roundID)) + require.NoError(t, ds.GetContext(ctx, &stats, "SELECT * FROM flux_monitor_round_stats_v2 WHERE round_id = $1", roundID)) if stats.ID == 0 { t.Fatalf("Stats for round id: %v not found!", roundID) } require.True(t, stats.PipelineRunID.Valid) // Verify the pipeline run data run := pipeline.Run{} - require.NoError(t, db.Get(&run, `SELECT * FROM pipeline_runs WHERE id = $1`, stats.PipelineRunID.Int64), "runID %v", stats.PipelineRunID) + require.NoError(t, ds.GetContext(ctx, &run, `SELECT * FROM pipeline_runs WHERE id = $1`, stats.PipelineRunID.Int64), "runID %v", stats.PipelineRunID) assert.Equal(t, []interface{}{result}, run.Outputs.Val) return run } -func checkLogWasConsumed(t *testing.T, fa fluxAggregatorUniverse, db *sqlx.DB, pipelineSpecID int32, blockNumber uint64, cfg pg.QConfig) { +func checkLogWasConsumed(t *testing.T, fa fluxAggregatorUniverse, ds sqlutil.DataSource, pipelineSpecID int32, blockNumber uint64) { t.Helper() lggr := logger.TestLogger(t) lggr.Infof("Waiting for log on block: %v, job id: %v", blockNumber, pipelineSpecID) g := gomega.NewWithT(t) g.Eventually(func() bool { + ctx := testutils.Context(t) block := fa.backend.Blockchain().GetBlockByNumber(blockNumber) require.NotNil(t, block) - orm := log.NewORM(db, fa.evmChainID) - consumed, err := orm.WasBroadcastConsumed(testutils.Context(t), block.Hash(), 0, pipelineSpecID) + orm := log.NewORM(ds, fa.evmChainID) + consumed, err := orm.WasBroadcastConsumed(ctx, block.Hash(), 0, pipelineSpecID) require.NoError(t, err) fa.backend.Commit() return consumed @@ -559,12 +559,12 @@ func TestFluxMonitor_Deviation(t *testing.T) { initialBalance, receiptBlock, ) - assertPipelineRunCreated(t, app.GetSqlxDB(), 1, int64(100)) + assertPipelineRunCreated(t, app.GetDB(), 1, int64(100)) // Need to wait until NewRound log is consumed - otherwise there is a chance // it will arrive after the next answer is submitted, and cause // DeleteFluxMonitorRoundsBackThrough to delete previous stats - checkLogWasConsumed(t, fa, app.GetSqlxDB(), jobID, receiptBlock, app.GetConfig().Database()) + checkLogWasConsumed(t, fa, app.GetDB(), jobID, receiptBlock) lggr.Info("Updating price to 103") // Change reported price to a value outside the deviation @@ -588,12 +588,12 @@ func TestFluxMonitor_Deviation(t *testing.T) { initialBalance-fee, receiptBlock, ) - assertPipelineRunCreated(t, app.GetSqlxDB(), 2, int64(103)) + assertPipelineRunCreated(t, app.GetDB(), 2, int64(103)) // Need to wait until NewRound log is consumed - otherwise there is a chance // it will arrive after the next answer is submitted, and cause // DeleteFluxMonitorRoundsBackThrough to delete previous stats - checkLogWasConsumed(t, fa, app.GetSqlxDB(), jobID, receiptBlock, app.GetConfig().Database()) + checkLogWasConsumed(t, fa, app.GetDB(), jobID, receiptBlock) // Should not received a submission as it is inside the deviation reportPrice.Store(104) @@ -795,7 +795,7 @@ ds1 -> ds1_parse // node doesn't submit initial response, because flag is up // Wait here so the next lower flags doesn't trigger immediately - cltest.AssertPipelineRunsStays(t, j.PipelineSpec.ID, app.GetSqlxDB(), 0) + cltest.AssertPipelineRunsStays(t, j.PipelineSpec.ID, app.GetDB(), 0) // lower global kill switch flag - should trigger job run _, err = fa.flagsContract.LowerFlags(fa.sergey, []common.Address{evmutils.ZeroAddress}) @@ -910,7 +910,7 @@ ds1 -> ds1_parse jobID, err := strconv.ParseInt(j.ID, 10, 32) require.NoError(t, err) - jse := cltest.WaitForSpecErrorV2(t, app.GetSqlxDB(), int32(jobID), 1) + jse := cltest.WaitForSpecErrorV2(t, app.GetDB(), int32(jobID), 1) assert.Contains(t, jse[0].Description, "Answer is outside acceptable range") } diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go index db00fabb4ff..9652c0b0e27 100644 --- a/core/services/fluxmonitorv2/orm_test.go +++ b/core/services/fluxmonitorv2/orm_test.go @@ -99,14 +99,14 @@ func TestORM_UpdateFluxMonitorRoundStats(t *testing.T) { // Instantiate a real job ORM because we need to create a job to satisfy // a check in pipeline.CreateRun - jobORM := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr) orm := newORM(t, db, nil) address := testutils.NewAddress() var roundID uint32 = 1 jb := makeJob(t) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(ctx, jb)) for expectedCount := uint64(1); expectedCount < 4; expectedCount++ { f := time.Now() diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go index f3754bbbc29..a1a29bf2500 100644 --- a/core/services/functions/listener_test.go +++ b/core/services/functions/listener_test.go @@ -186,7 +186,7 @@ func TestFunctionsListener_HandleOffchainRequest_Success(t *testing.T) { uni := NewFunctionsListenerUniverse(t, 0, 1_000_000) - uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything).Return(nil) + uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything, mock.Anything).Return(nil) uni.bridgeAccessor.On("NewExternalAdapterClient", mock.Anything).Return(uni.eaClient, nil) uni.eaClient.On("RunComputation", mock.Anything, RequestIDStr, mock.Anything, SubscriptionOwner.Hex(), SubscriptionID, mock.Anything, mock.Anything, mock.Anything).Return(ResultBytes, nil, nil, nil) uni.pluginORM.On("SetResult", mock.Anything, RequestID, ResultBytes, mock.Anything, mock.Anything).Return(nil) @@ -230,7 +230,7 @@ func TestFunctionsListener_HandleOffchainRequest_InternalError(t *testing.T) { testutils.SkipShortDB(t) t.Parallel() uni := NewFunctionsListenerUniverse(t, 0, 1_000_000) - uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything).Return(nil) + uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything, mock.Anything).Return(nil) uni.bridgeAccessor.On("NewExternalAdapterClient", mock.Anything).Return(uni.eaClient, nil) uni.eaClient.On("RunComputation", mock.Anything, RequestIDStr, mock.Anything, SubscriptionOwner.Hex(), SubscriptionID, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, errors.New("error")) uni.pluginORM.On("SetError", mock.Anything, RequestID, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) diff --git a/core/services/gateway/delegate.go b/core/services/gateway/delegate.go index 8cddc027803..5a30228db4c 100644 --- a/core/services/gateway/delegate.go +++ b/core/services/gateway/delegate.go @@ -5,34 +5,31 @@ import ( "encoding/json" "github.com/google/uuid" - "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type Delegate struct { legacyChains legacyevm.LegacyChainContainer ks keystore.Eth - db *sqlx.DB - cfg pg.QConfig + ds sqlutil.DataSource lggr logger.Logger } var _ job.Delegate = (*Delegate)(nil) -func NewDelegate(legacyChains legacyevm.LegacyChainContainer, ks keystore.Eth, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) *Delegate { +func NewDelegate(legacyChains legacyevm.LegacyChainContainer, ks keystore.Eth, ds sqlutil.DataSource, lggr logger.Logger) *Delegate { return &Delegate{ legacyChains: legacyChains, ks: ks, - db: db, - cfg: cfg, + ds: ds, lggr: lggr, } } @@ -57,7 +54,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services if err2 != nil { return nil, errors.Wrap(err2, "unmarshal gateway config") } - handlerFactory := NewHandlerFactory(d.legacyChains, d.db, d.cfg, d.lggr) + handlerFactory := NewHandlerFactory(d.legacyChains, d.ds, d.lggr) gateway, err := NewGatewayFromConfig(&gatewayConfig, handlerFactory, d.lggr) if err != nil { return nil, err diff --git a/core/services/gateway/gateway_test.go b/core/services/gateway/gateway_test.go index 7a5457c788c..3218c5428a2 100644 --- a/core/services/gateway/gateway_test.go +++ b/core/services/gateway/gateway_test.go @@ -57,7 +57,7 @@ Address = "0x0001020304050607080900010203040506070809" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.NoError(t, err) } @@ -75,7 +75,7 @@ HandlerName = "dummy" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -89,7 +89,7 @@ HandlerName = "no_such_handler" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -103,7 +103,7 @@ SomeOtherField = "abcd" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -121,7 +121,7 @@ Address = "0xnot_an_address" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -129,7 +129,7 @@ func TestGateway_CleanStartAndClose(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) - gateway, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, buildConfig("")), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + gateway, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, buildConfig("")), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.NoError(t, err) servicetest.Run(t, gateway) } diff --git a/core/services/gateway/handler_factory.go b/core/services/gateway/handler_factory.go index 8ccae8c7c4b..ca6b98e55aa 100644 --- a/core/services/gateway/handler_factory.go +++ b/core/services/gateway/handler_factory.go @@ -4,14 +4,12 @@ import ( "encoding/json" "fmt" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) const ( @@ -21,21 +19,20 @@ const ( type handlerFactory struct { legacyChains legacyevm.LegacyChainContainer - db *sqlx.DB - cfg pg.QConfig + ds sqlutil.DataSource lggr logger.Logger } var _ HandlerFactory = (*handlerFactory)(nil) -func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) HandlerFactory { - return &handlerFactory{legacyChains, db, cfg, lggr} +func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, ds sqlutil.DataSource, lggr logger.Logger) HandlerFactory { + return &handlerFactory{legacyChains, ds, lggr} } func (hf *handlerFactory) NewHandler(handlerType HandlerType, handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON) (handlers.Handler, error) { switch handlerType { case FunctionsHandlerType: - return functions.NewFunctionsHandlerFromConfig(handlerConfig, donConfig, don, hf.legacyChains, hf.db, hf.cfg, hf.lggr) + return functions.NewFunctionsHandlerFromConfig(handlerConfig, donConfig, don, hf.legacyChains, hf.ds, hf.lggr) case DummyHandlerType: return handlers.NewDummyHandler(donConfig, don, hf.lggr) default: diff --git a/core/services/gateway/handlers/functions/allowlist/orm.go b/core/services/gateway/handlers/functions/allowlist/orm.go index 7867c06d5d4..20a8ed15252 100644 --- a/core/services/gateway/handlers/functions/allowlist/orm.go +++ b/core/services/gateway/handlers/functions/allowlist/orm.go @@ -67,6 +67,11 @@ func (o *orm) GetAllowedSenders(ctx context.Context, offset, limit uint) ([]comm } func (o *orm) CreateAllowedSenders(ctx context.Context, allowedSenders []common.Address) error { + if len(allowedSenders) == 0 { + o.lggr.Debugf("empty allowed senders list: %v for routerContractAddress: %s. skipping...", allowedSenders, o.routerContractAddress) + return nil + } + var valuesPlaceholder []string for i := 1; i <= len(allowedSenders)*2; i += 2 { valuesPlaceholder = append(valuesPlaceholder, fmt.Sprintf("($%d, $%d)", i, i+1)) diff --git a/core/services/gateway/handlers/functions/allowlist/orm_test.go b/core/services/gateway/handlers/functions/allowlist/orm_test.go index 2584e131968..388d47a769b 100644 --- a/core/services/gateway/handlers/functions/allowlist/orm_test.go +++ b/core/services/gateway/handlers/functions/allowlist/orm_test.go @@ -128,6 +128,15 @@ func TestORM_CreateAllowedSenders(t *testing.T) { require.Equal(t, expected[0], results[0]) require.Equal(t, expected[1], results[1]) }) + + // this scenario can happen if the allowlist is empty but we call CreateAllowedSenders + t.Run("OK-empty_list", func(t *testing.T) { + ctx := testutils.Context(t) + orm, err := setupORM(t) + require.NoError(t, err) + err = orm.CreateAllowedSenders(ctx, []common.Address{}) + require.NoError(t, err) + }) } func TestORM_DeleteAllowedSenders(t *testing.T) { diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go index 692534db598..2d55bb23fde 100644 --- a/core/services/gateway/handlers/functions/handler.functions.go +++ b/core/services/gateway/handlers/functions/handler.functions.go @@ -10,13 +10,13 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "go.uber.org/multierr" "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" @@ -25,7 +25,6 @@ import ( hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" fallow "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/allowlist" fsub "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/subscriptions" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) var ( @@ -100,7 +99,7 @@ type PendingRequest struct { var _ handlers.Handler = (*functionsHandler)(nil) -func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON, legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, qcfg pg.QConfig, lggr logger.Logger) (handlers.Handler, error) { +func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON, legacyChains legacyevm.LegacyChainContainer, ds sqlutil.DataSource, lggr logger.Logger) (handlers.Handler, error) { var cfg FunctionsHandlerConfig err := json.Unmarshal(handlerConfig, &cfg) if err != nil { @@ -114,7 +113,7 @@ func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *con return nil, err2 } - orm, err2 := fallow.NewORM(db, lggr, cfg.OnchainAllowlist.ContractAddress) + orm, err2 := fallow.NewORM(ds, lggr, cfg.OnchainAllowlist.ContractAddress) if err2 != nil { return nil, err2 } @@ -143,7 +142,7 @@ func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *con return nil, err2 } - orm, err2 := fsub.NewORM(db, lggr, cfg.OnchainSubscriptions.ContractAddress) + orm, err2 := fsub.NewORM(ds, lggr, cfg.OnchainSubscriptions.ContractAddress) if err2 != nil { return nil, err2 } diff --git a/core/services/gateway/handlers/functions/handler.functions_test.go b/core/services/gateway/handlers/functions/handler.functions_test.go index 2e2c1c77caf..b7abeed8a99 100644 --- a/core/services/gateway/handlers/functions/handler.functions_test.go +++ b/core/services/gateway/handlers/functions/handler.functions_test.go @@ -84,7 +84,7 @@ func sendNodeReponses(t *testing.T, handler handlers.Handler, userRequestMsg api func TestFunctionsHandler_Minimal(t *testing.T) { t.Parallel() - handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, nil, logger.TestLogger(t)) + handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, logger.TestLogger(t)) require.NoError(t, err) // empty message should always error out @@ -96,7 +96,7 @@ func TestFunctionsHandler_Minimal(t *testing.T) { func TestFunctionsHandler_CleanStartAndClose(t *testing.T) { t.Parallel() - handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, nil, logger.TestLogger(t)) + handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, logger.TestLogger(t)) require.NoError(t, err) servicetest.Run(t, handler) diff --git a/core/services/gateway/integration_tests/gateway_integration_test.go b/core/services/gateway/integration_tests/gateway_integration_test.go index 7f4a2ab58fa..38a6b6ebbca 100644 --- a/core/services/gateway/integration_tests/gateway_integration_test.go +++ b/core/services/gateway/integration_tests/gateway_integration_test.go @@ -143,7 +143,7 @@ func TestIntegration_Gateway_NoFullNodes_BasicConnectionAndMessage(t *testing.T) // Launch Gateway lggr := logger.TestLogger(t) gatewayConfig := fmt.Sprintf(gatewayConfigTemplate, nodeKeys.Address) - gateway, err := gateway.NewGatewayFromConfig(parseGatewayConfig(t, gatewayConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + gateway, err := gateway.NewGatewayFromConfig(parseGatewayConfig(t, gatewayConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.NoError(t, err) servicetest.Run(t, gateway) userPort, nodePort := gateway.GetUserPort(), gateway.GetNodePort() diff --git a/core/services/job/common.go b/core/services/job/common.go index 58b1754cbf5..055195440b0 100644 --- a/core/services/job/common.go +++ b/core/services/job/common.go @@ -3,8 +3,6 @@ package job import ( "context" "net/url" - - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) //go:generate mockery --quiet --name ServiceCtx --output ./mocks/ --case=underscore @@ -22,7 +20,6 @@ type ServiceCtx interface { type Config interface { URL() url.URL - pg.QConfig } // ServiceAdapter is a helper introduced for transitioning from Service to ServiceCtx. diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go index 22e1b0bef63..7120fe4200c 100644 --- a/core/services/job/helpers_test.go +++ b/core/services/job/helpers_test.go @@ -268,8 +268,7 @@ func makeOCRJobSpecFromToml(t *testing.T, jobSpecToml string) *job.Job { return &jb } -func makeOCR2VRFJobSpec(t testing.TB, ks keystore.Master, cfg chainlink.GeneralConfig, - transmitter common.Address, chainID *big.Int, fromBlock uint64) *job.Job { +func makeOCR2VRFJobSpec(t testing.TB, ks keystore.Master, transmitter common.Address, chainID *big.Int, fromBlock uint64) *job.Job { t.Helper() ctx := testutils.Context(t) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index ffbd02c512b..3c7d5a7afa5 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -66,6 +66,11 @@ observationSource = """ chainID = 1 fromBlock = 1000 +[onchainSigningStrategy] +strategyName = 'single-chain' +[onchainSigningStrategy.config] +publicKey = '8fa807463ad73f9ee855cfd60ba406dcf98a2855b3dd8af613107b0f6890a707' + [pluginConfig] serverURL = 'wss://localhost:8080' serverPubKey = '8fa807463ad73f9ee855cfd60ba406dcf98a2855b3dd8af613107b0f6890a707' @@ -73,20 +78,21 @@ serverPubKey = '8fa807463ad73f9ee855cfd60ba406dcf98a2855b3dd8af613107b0f6890a707 func TestORM(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() - require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) + func() { + ctx := testutils.Context(t) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) + }() pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(db) - - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) borm := bridges.NewORM(db) + orm := NewTestORM(t, db, pipelineORM, borm, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -94,7 +100,7 @@ func TestORM(t *testing.T) { jb := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) t.Run("it creates job specs", func(t *testing.T) { - err := orm.CreateJob(jb) + err := orm.CreateJob(testutils.Context(t), jb) require.NoError(t, err) var returnedSpec job.Job @@ -109,8 +115,9 @@ func TestORM(t *testing.T) { }) t.Run("it correctly mark job_pipeline_specs as primary when creating a job", func(t *testing.T) { + ctx := testutils.Context(t) jb2 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) - err := orm.CreateJob(jb2) + err := orm.CreateJob(ctx, jb2) require.NoError(t, err) var pipelineSpec pipeline.Spec @@ -128,7 +135,7 @@ func TestORM(t *testing.T) { t.Run("autogenerates external job ID if missing", func(t *testing.T) { jb2 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) jb2.ExternalJobID = uuid.UUID{} - err := orm.CreateJob(jb2) + err := orm.CreateJob(testutils.Context(t), jb2) require.NoError(t, err) var returnedSpec job.Job @@ -145,7 +152,7 @@ func TestORM(t *testing.T) { require.NoError(t, err) require.Len(t, dbSpecs, 3) - err = orm.DeleteJob(jb.ID) + err = orm.DeleteJob(testutils.Context(t), jb.ID) require.NoError(t, err) dbSpecs = []job.Job{} @@ -155,8 +162,9 @@ func TestORM(t *testing.T) { }) t.Run("increase job spec error occurrence", func(t *testing.T) { + ctx := testutils.Context(t) jb3 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) - err := orm.CreateJob(jb3) + err := orm.CreateJob(ctx, jb3) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -164,9 +172,9 @@ func TestORM(t *testing.T) { ocrSpecError1 := "ocr spec 1 errored" ocrSpecError2 := "ocr spec 2 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) var specErrors []job.SpecError err = db.Select(&specErrors, "SELECT * FROM job_spec_errors") @@ -193,8 +201,9 @@ func TestORM(t *testing.T) { }) t.Run("finds job spec error by ID", func(t *testing.T) { + ctx := testutils.Context(t) jb3 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) - err := orm.CreateJob(jb3) + err := orm.CreateJob(ctx, jb3) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -207,8 +216,8 @@ func TestORM(t *testing.T) { ocrSpecError1 := "ocr spec 3 errored" ocrSpecError2 := "ocr spec 4 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) var updatedSpecError []job.SpecError @@ -221,9 +230,9 @@ func TestORM(t *testing.T) { assert.Equal(t, ocrSpecError1, updatedSpecError[2].Description) assert.Equal(t, ocrSpecError2, updatedSpecError[3].Description) - dbSpecErr1, err := orm.FindSpecError(updatedSpecError[2].ID) + dbSpecErr1, err := orm.FindSpecError(ctx, updatedSpecError[2].ID) require.NoError(t, err) - dbSpecErr2, err := orm.FindSpecError(updatedSpecError[3].ID) + dbSpecErr2, err := orm.FindSpecError(ctx, updatedSpecError[3].ID) require.NoError(t, err) assert.Equal(t, uint(1), dbSpecErr1.Occurrences) @@ -251,11 +260,12 @@ func TestORM(t *testing.T) { drJob, err := directrequest.ValidatedDirectRequestSpec(drSpec) require.NoError(t, err) - err = orm.CreateJob(&drJob) + err = orm.CreateJob(testutils.Context(t), &drJob) require.NoError(t, err) }) t.Run("creates webhook specs along with external_initiator_webhook_specs", func(t *testing.T) { + ctx := testutils.Context(t) eiFoo := cltest.MustInsertExternalInitiator(t, borm) eiBar := cltest.MustInsertExternalInitiator(t, borm) @@ -263,22 +273,23 @@ func TestORM(t *testing.T) { {Name: eiFoo.Name, Spec: cltest.JSONFromString(t, `{}`)}, {Name: eiBar.Name, Spec: cltest.JSONFromString(t, `{"bar": 1}`)}, } - eim := webhook.NewExternalInitiatorManager(db, nil, logger.TestLogger(t), config.Database()) - jb, err := webhook.ValidatedWebhookSpec(testspecs.GenerateWebhookSpec(testspecs.WebhookSpecParams{ExternalInitiators: eiWS}).Toml(), eim) + eim := webhook.NewExternalInitiatorManager(db, nil) + jb, err := webhook.ValidatedWebhookSpec(ctx, testspecs.GenerateWebhookSpec(testspecs.WebhookSpecParams{ExternalInitiators: eiWS}).Toml(), eim) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) cltest.AssertCount(t, db, "external_initiator_webhook_specs", 2) }) t.Run("it creates and deletes records for blockhash store jobs", func(t *testing.T) { + ctx := testutils.Context(t) bhsJob, err := blockhashstore.ValidatedSpec( testspecs.GenerateBlockhashStoreSpec(testspecs.BlockhashStoreSpecParams{}).Toml()) require.NoError(t, err) - err = orm.CreateJob(&bhsJob) + err = orm.CreateJob(ctx, &bhsJob) require.NoError(t, err) savedJob, err := orm.FindJob(testutils.Context(t), bhsJob.ID) require.NoError(t, err) @@ -298,18 +309,19 @@ func TestORM(t *testing.T) { require.Equal(t, bhsJob.BlockhashStoreSpec.RunTimeout, savedJob.BlockhashStoreSpec.RunTimeout) require.Equal(t, bhsJob.BlockhashStoreSpec.EVMChainID, savedJob.BlockhashStoreSpec.EVMChainID) require.Equal(t, bhsJob.BlockhashStoreSpec.FromAddresses, savedJob.BlockhashStoreSpec.FromAddresses) - err = orm.DeleteJob(bhsJob.ID) + err = orm.DeleteJob(ctx, bhsJob.ID) require.NoError(t, err) _, err = orm.FindJob(testutils.Context(t), bhsJob.ID) require.Error(t, err) }) t.Run("it creates and deletes records for blockheaderfeeder jobs", func(t *testing.T) { + ctx := testutils.Context(t) bhsJob, err := blockheaderfeeder.ValidatedSpec( testspecs.GenerateBlockHeaderFeederSpec(testspecs.BlockHeaderFeederSpecParams{}).Toml()) require.NoError(t, err) - err = orm.CreateJob(&bhsJob) + err = orm.CreateJob(ctx, &bhsJob) require.NoError(t, err) savedJob, err := orm.FindJob(testutils.Context(t), bhsJob.ID) require.NoError(t, err) @@ -329,7 +341,7 @@ func TestORM(t *testing.T) { require.Equal(t, bhsJob.BlockHeaderFeederSpec.FromAddresses, savedJob.BlockHeaderFeederSpec.FromAddresses) require.Equal(t, bhsJob.BlockHeaderFeederSpec.GetBlockhashesBatchSize, savedJob.BlockHeaderFeederSpec.GetBlockhashesBatchSize) require.Equal(t, bhsJob.BlockHeaderFeederSpec.StoreBlockhashesBatchSize, savedJob.BlockHeaderFeederSpec.StoreBlockhashesBatchSize) - err = orm.DeleteJob(bhsJob.ID) + err = orm.DeleteJob(ctx, bhsJob.ID) require.NoError(t, err) _, err = orm.FindJob(testutils.Context(t), bhsJob.ID) require.Error(t, err) @@ -349,10 +361,11 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) korm := keeper.NewORM(db, logger.TestLogger(t)) t.Run("it deletes records for offchainreporting jobs", func(t *testing.T) { + ctx := testutils.Context(t) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -366,13 +379,13 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { }).Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) cltest.AssertCount(t, db, "ocr_oracle_specs", 1) cltest.AssertCount(t, db, "pipeline_specs", 1) - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) cltest.AssertCount(t, db, "ocr_oracle_specs", 0) cltest.AssertCount(t, db, "pipeline_specs", 0) @@ -380,6 +393,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { }) t.Run("it deletes records for keeper jobs", func(t *testing.T) { + ctx := testutils.Context(t) registry, keeperJob := cltest.MustInsertKeeperRegistry(t, db, korm, keyStore.Eth(), 0, 1, 20) cltest.MustInsertUpkeepForRegistry(t, db, registry) @@ -387,7 +401,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { cltest.AssertCount(t, db, "keeper_registries", 1) cltest.AssertCount(t, db, "upkeep_registrations", 1) - err := jobORM.DeleteJob(keeperJob.ID) + err := jobORM.DeleteJob(ctx, keeperJob.ID) require.NoError(t, err) cltest.AssertCount(t, db, "keeper_specs", 0) cltest.AssertCount(t, db, "keeper_registries", 0) @@ -396,29 +410,31 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { }) t.Run("it creates and deletes records for vrf jobs", func(t *testing.T) { - key, err := keyStore.VRF().Create(testutils.Context(t)) + ctx := testutils.Context(t) + key, err := keyStore.VRF().Create(ctx) require.NoError(t, err) pk := key.PublicKey jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{PublicKey: pk.String()}).Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) }) t.Run("it deletes records for webhook jobs", func(t *testing.T) { + ctx := testutils.Context(t) ei := cltest.MustInsertExternalInitiator(t, bridges.NewORM(db)) jb, webhookSpec := cltest.MustInsertWebhookSpec(t, db) _, err := db.Exec(`INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, ei.ID, webhookSpec.ID, `{"ei": "foo", "name": "webhookSpecTwoEIs"}`) require.NoError(t, err) - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) cltest.AssertCount(t, db, "webhook_specs", 0) cltest.AssertCount(t, db, "external_initiator_webhook_specs", 0) @@ -449,7 +465,7 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()} jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec( @@ -465,7 +481,7 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) var requestedConfsDelay int64 @@ -505,20 +521,20 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { var vrfOwnerAddress evmtypes.EIP55Address require.NoError(t, db.Get(&vrfOwnerAddress, `SELECT vrf_owner_address FROM vrf_specs LIMIT 1`)) require.Equal(t, "0x32891BD79647DC9136Fc0a59AAB48c7825eb624c", vrfOwnerAddress.Address().String()) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) jb, err = vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{RequestTimeout: 1 * time.Hour}).Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) require.NoError(t, db.Get(&requestedConfsDelay, `SELECT requested_confs_delay FROM vrf_specs LIMIT 1`)) require.Equal(t, int64(0), requestedConfsDelay) require.NoError(t, db.Get(&requestTimeout, `SELECT request_timeout FROM vrf_specs LIMIT 1`)) require.Equal(t, 1*time.Hour, requestTimeout) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) } @@ -533,7 +549,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()} jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec( @@ -550,7 +566,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) var requestedConfsDelay int64 @@ -589,7 +605,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { require.ElementsMatch(t, fromAddresses, actual) var vrfOwnerAddress evmtypes.EIP55Address require.Error(t, db.Get(&vrfOwnerAddress, `SELECT vrf_owner_address FROM vrf_specs LIMIT 1`)) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) @@ -599,14 +615,14 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { FromAddresses: fromAddresses, }).Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) require.NoError(t, db.Get(&requestedConfsDelay, `SELECT requested_confs_delay FROM vrf_specs LIMIT 1`)) require.Equal(t, int64(0), requestedConfsDelay) require.NoError(t, db.Get(&requestTimeout, `SELECT request_timeout FROM vrf_specs LIMIT 1`)) require.Equal(t, 1*time.Hour, requestTimeout) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) } @@ -621,12 +637,12 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := ocrbootstrap.ValidatedBootstrapSpecToml(testspecs.GetOCRBootstrapSpec()) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) cltest.AssertCount(t, db, "bootstrap_specs", 1) cltest.AssertCount(t, db, "jobs", 1) @@ -634,7 +650,7 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) { require.NoError(t, db.Get(&relay, `SELECT relay FROM bootstrap_specs LIMIT 1`)) require.Equal(t, "evm", relay) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "bootstrap_specs", 0) cltest.AssertCount(t, db, "jobs", 0) } @@ -648,14 +664,14 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) t.Run("evm chain id validation for ocr works", func(t *testing.T) { jb := job.Job{ Type: job.OffchainReporting, OCROracleSpec: &job.OCROracleSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for direct request works", func(t *testing.T) { @@ -663,7 +679,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.DirectRequest, DirectRequestSpec: &job.DirectRequestSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for flux monitor works", func(t *testing.T) { @@ -671,7 +687,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.FluxMonitor, FluxMonitorSpec: &job.FluxMonitorSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for keepers works", func(t *testing.T) { @@ -679,7 +695,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.Keeper, KeeperSpec: &job.KeeperSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for vrf works", func(t *testing.T) { @@ -687,7 +703,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.VRF, VRFSpec: &job.VRFSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for block hash store works", func(t *testing.T) { @@ -695,7 +711,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.BlockhashStore, BlockhashStoreSpec: &job.BlockhashStoreSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for block header feeder works", func(t *testing.T) { @@ -703,7 +719,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.BlockHeaderFeeder, BlockHeaderFeederSpec: &job.BlockHeaderFeederSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for legacy gas station server spec works", func(t *testing.T) { @@ -711,7 +727,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.LegacyGasStationServer, LegacyGasStationServerSpec: &job.LegacyGasStationServerSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for legacy gas station sidecar spec works", func(t *testing.T) { @@ -719,7 +735,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.LegacyGasStationSidecar, LegacyGasStationSidecarSpec: &job.LegacyGasStationSidecarSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) } @@ -744,7 +760,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) // defaultChainID is deprecated defaultChainID := customChainID @@ -768,7 +784,8 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { require.NoError(t, err) t.Run("with a set chain id", func(t *testing.T) { - err = jobORM.CreateJob(&jb) // Add job with custom chain id + ctx := testutils.Context(t) + err = jobORM.CreateJob(ctx, &jb) // Add job with custom chain id require.NoError(t, err) cltest.AssertCount(t, db, "ocr_oracle_specs", 1) @@ -778,7 +795,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { spec.JobID = externalJobID.UUID.String() jba, err := ocr.ValidatedOracleSpecToml(config, legacyChains, spec.Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jba) // Try to add duplicate job with default id + err = jobORM.CreateJob(ctx, &jba) // Try to add duplicate job with default id require.Error(t, err) assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %s", jb.OCROracleSpec.ContractAddress, defaultChainID.String()), err.Error()) @@ -787,7 +804,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { jb2, err := ocr.ValidatedOracleSpecToml(config, legacyChains, spec.Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jb2) // Try to add duplicate job with custom id + err = jobORM.CreateJob(ctx, &jb2) // Try to add duplicate job with custom id require.Error(t, err) assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %s", jb2.OCROracleSpec.ContractAddress, customChainID), err.Error()) }) @@ -814,7 +831,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -831,7 +848,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) jb2, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) @@ -841,7 +858,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { jb2.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb2) + err = jobORM.CreateJob(ctx, &jb2) require.Error(t, err) jb3, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) @@ -851,7 +868,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { jb3.OCR2OracleSpec.RelayConfig["chainID"] = customChainID.Int64() jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb3) + err = jobORM.CreateJob(ctx, &jb3) require.Error(t, err) } @@ -876,37 +893,41 @@ func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) require.NoError(t, err) t.Run("sending keys or transmitterID must be defined", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.String{} - assert.Equal(t, "CreateJobFailed: neither sending keys nor transmitter ID is defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: neither sending keys nor transmitter ID is defined", jobORM.CreateJob(ctx, &jb).Error()) }) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) t.Run("sending keys validation works properly", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.String{} _, address2 := cltest.MustInsertRandomKey(t, keyStore.Eth()) jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = interface{}([]any{address.String(), address2.String(), common.HexToAddress("0X0").String()}) - assert.Equal(t, "CreateJobFailed: no EVM key matching: \"0x0000000000000000000000000000000000000000\": no such sending key exists", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: no EVM key matching: \"0x0000000000000000000000000000000000000000\": no such sending key exists", jobORM.CreateJob(ctx, &jb).Error()) jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = interface{}([]any{1, 2, 3}) - assert.Equal(t, "CreateJobFailed: sending keys are of wrong type", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: sending keys are of wrong type", jobORM.CreateJob(ctx, &jb).Error()) }) t.Run("sending keys and transmitter ID can't both be defined", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = interface{}([]any{address.String()}) - assert.Equal(t, "CreateJobFailed: sending keys and transmitter ID can't both be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: sending keys and transmitter ID can't both be defined", jobORM.CreateJob(ctx, &jb).Error()) }) t.Run("transmitter validation works", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.StringFrom("transmitterID that doesn't have a match in key store") jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = nil - assert.Equal(t, "CreateJobFailed: no EVM key matching: \"transmitterID that doesn't have a match in key store\": no such transmitter key exists", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: no EVM key matching: \"transmitterID that doesn't have a match in key store\": no such transmitter key exists", jobORM.CreateJob(ctx, &jb).Error()) }) } @@ -998,7 +1019,7 @@ func Test_FindJobs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1016,7 +1037,7 @@ func Test_FindJobs(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb1) + err = orm.CreateJob(ctx, &jb1) require.NoError(t, err) jb2, err := directrequest.ValidatedDirectRequestSpec( @@ -1024,11 +1045,11 @@ func Test_FindJobs(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb2) + err = orm.CreateJob(ctx, &jb2) require.NoError(t, err) t.Run("jobs are ordered by latest first", func(t *testing.T) { - jobs, count, err2 := orm.FindJobs(0, 2) + jobs, count, err2 := orm.FindJobs(testutils.Context(t), 0, 2) require.NoError(t, err2) require.Len(t, jobs, 2) assert.Equal(t, count, 2) @@ -1041,7 +1062,7 @@ func Test_FindJobs(t *testing.T) { }) t.Run("jobs respect pagination", func(t *testing.T) { - jobs, count, err2 := orm.FindJobs(0, 1) + jobs, count, err2 := orm.FindJobs(testutils.Context(t), 0, 1) require.NoError(t, err2) require.Len(t, jobs, 1) assert.Equal(t, count, 2) @@ -1080,7 +1101,7 @@ func Test_FindJob(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1148,20 +1169,20 @@ func Test_FindJob(t *testing.T) { jobOCR2WithFeedID2.Name = null.StringFrom("new name") require.NoError(t, err) - err = orm.CreateJob(&job) + err = orm.CreateJob(ctx, &job) require.NoError(t, err) - err = orm.CreateJob(&jobSameAddress) + err = orm.CreateJob(ctx, &jobSameAddress) require.NoError(t, err) - err = orm.CreateJob(&jobOCR2) + err = orm.CreateJob(ctx, &jobOCR2) require.NoError(t, err) - err = orm.CreateJob(&jobOCR2WithFeedID1) + err = orm.CreateJob(ctx, &jobOCR2WithFeedID1) require.NoError(t, err) // second ocr2 job with same contract id but different feed id - err = orm.CreateJob(&jobOCR2WithFeedID2) + err = orm.CreateJob(ctx, &jobOCR2WithFeedID2) require.NoError(t, err) t.Run("by id", func(t *testing.T) { @@ -1180,7 +1201,8 @@ func Test_FindJob(t *testing.T) { }) t.Run("by external job id", func(t *testing.T) { - jb, err2 := orm.FindJobByExternalJobID(externalJobID) + ctx := testutils.Context(t) + jb, err2 := orm.FindJobByExternalJobID(ctx, externalJobID) require.NoError(t, err2) assert.Equal(t, jb.ID, job.ID) @@ -1193,59 +1215,64 @@ func Test_FindJob(t *testing.T) { }) t.Run("by address", func(t *testing.T) { - jbID, err2 := orm.FindJobIDByAddress(job.OCROracleSpec.ContractAddress, job.OCROracleSpec.EVMChainID) + ctx := testutils.Context(t) + jbID, err2 := orm.FindJobIDByAddress(ctx, job.OCROracleSpec.ContractAddress, job.OCROracleSpec.EVMChainID) require.NoError(t, err2) assert.Equal(t, job.ID, jbID) - _, err2 = orm.FindJobIDByAddress("not-existing", big.NewI(0)) + _, err2 = orm.FindJobIDByAddress(ctx, "not-existing", big.NewI(0)) require.Error(t, err2) require.ErrorIs(t, err2, sql.ErrNoRows) }) t.Run("by address yet chain scoped", func(t *testing.T) { + ctx := testutils.Context(t) commonAddr := jobSameAddress.OCROracleSpec.ContractAddress // Find job ID for job on chain 1337 with common address. - jbID, err2 := orm.FindJobIDByAddress(commonAddr, jobSameAddress.OCROracleSpec.EVMChainID) + jbID, err2 := orm.FindJobIDByAddress(ctx, commonAddr, jobSameAddress.OCROracleSpec.EVMChainID) require.NoError(t, err2) assert.Equal(t, jobSameAddress.ID, jbID) // Find job ID for job on default evm chain with common address. - jbID, err2 = orm.FindJobIDByAddress(commonAddr, job.OCROracleSpec.EVMChainID) + jbID, err2 = orm.FindJobIDByAddress(ctx, commonAddr, job.OCROracleSpec.EVMChainID) require.NoError(t, err2) assert.Equal(t, job.ID, jbID) }) t.Run("by contract id without feed id", func(t *testing.T) { + ctx := testutils.Context(t) contractID := "0x613a38AC1659769640aaE063C651F48E0250454C" // Find job ID for ocr2 job without feedID. - jbID, err2 := orm.FindOCR2JobIDByAddress(contractID, nil) + jbID, err2 := orm.FindOCR2JobIDByAddress(ctx, contractID, nil) require.NoError(t, err2) assert.Equal(t, jobOCR2.ID, jbID) }) t.Run("by contract id with valid feed id", func(t *testing.T) { + ctx := testutils.Context(t) contractID := "0x0000000000000000000000000000000000000006" feedID := common.HexToHash(ocr2WithFeedID1) // Find job ID for ocr2 job with feed ID - jbID, err2 := orm.FindOCR2JobIDByAddress(contractID, &feedID) + jbID, err2 := orm.FindOCR2JobIDByAddress(ctx, contractID, &feedID) require.NoError(t, err2) assert.Equal(t, jobOCR2WithFeedID1.ID, jbID) }) t.Run("with duplicate contract id but different feed id", func(t *testing.T) { + ctx := testutils.Context(t) contractID := "0x0000000000000000000000000000000000000006" feedID := common.HexToHash(ocr2WithFeedID2) // Find job ID for ocr2 job with feed ID - jbID, err2 := orm.FindOCR2JobIDByAddress(contractID, &feedID) + jbID, err2 := orm.FindOCR2JobIDByAddress(ctx, contractID, &feedID) require.NoError(t, err2) assert.Equal(t, jobOCR2WithFeedID2.ID, jbID) @@ -1263,17 +1290,18 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) jb.DirectRequestSpec.EVMChainID = big.NewI(0) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with jobs", func(t *testing.T) { - jbs, err2 := orm.FindJobsByPipelineSpecIDs([]int32{jb.PipelineSpecID}) + ctx := testutils.Context(t) + jbs, err2 := orm.FindJobsByPipelineSpecIDs(ctx, []int32{jb.PipelineSpecID}) require.NoError(t, err2) assert.Len(t, jbs, 1) @@ -1286,15 +1314,17 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { }) t.Run("without jobs", func(t *testing.T) { - jbs, err2 := orm.FindJobsByPipelineSpecIDs([]int32{-1}) + ctx := testutils.Context(t) + jbs, err2 := orm.FindJobsByPipelineSpecIDs(ctx, []int32{-1}) require.NoError(t, err2) assert.Len(t, jbs, 0) }) t.Run("with chainID disabled", func(t *testing.T) { - orm2 := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + ctx := testutils.Context(t) + orm2 := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) - jbs, err2 := orm2.FindJobsByPipelineSpecIDs([]int32{jb.PipelineSpecID}) + jbs, err2 := orm2.FindJobsByPipelineSpecIDs(ctx, []int32{jb.PipelineSpecID}) require.NoError(t, err2) assert.Len(t, jbs, 1) }) @@ -1314,7 +1344,7 @@ func Test_FindPipelineRuns(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1331,20 +1361,22 @@ func Test_FindPipelineRuns(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - runs, count, err2 := orm.PipelineRuns(nil, 0, 10) + ctx := testutils.Context(t) + runs, count, err2 := orm.PipelineRuns(ctx, nil, 0, 10) require.NoError(t, err2) assert.Equal(t, count, 0) assert.Empty(t, runs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - runs, count, err2 := orm.PipelineRuns(nil, 0, 10) + runs, count, err2 := orm.PipelineRuns(ctx, nil, 0, 10) require.NoError(t, err2) assert.Equal(t, count, 1) @@ -1376,7 +1408,7 @@ func Test_PipelineRunsByJobID(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1393,20 +1425,22 @@ func Test_PipelineRunsByJobID(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - runs, count, err2 := orm.PipelineRuns(&jb.ID, 0, 10) + ctx := testutils.Context(t) + runs, count, err2 := orm.PipelineRuns(ctx, &jb.ID, 0, 10) require.NoError(t, err2) assert.Equal(t, count, 0) assert.Empty(t, runs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - runs, count, err2 := orm.PipelineRuns(&jb.ID, 0, 10) + runs, count, err2 := orm.PipelineRuns(ctx, &jb.ID, 0, 10) require.NoError(t, err2) assert.Equal(t, 1, count) @@ -1437,7 +1471,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -1461,7 +1495,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) jobs[j] = jb } @@ -1475,15 +1509,17 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { } t.Run("with no pipeline runs", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jb.ID, 0, 10) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jb.ID, 0, 10) require.NoError(t, err) assert.Empty(t, runIDs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - runIDs, err := orm.FindPipelineRunIDsByJobID(jb.ID, 0, 10) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jb.ID, 0, 10) require.NoError(t, err) require.Len(t, runIDs, 1) @@ -1493,7 +1529,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // Internally these queries are batched by 1000, this tests case requiring concatenation // of more than 1 batch t.Run("with batch concatenation limit 10", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 95, 10) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 95, 10) require.NoError(t, err) require.Len(t, runIDs, 10) assert.Equal(t, int64(4*(len(jobs)-1)), runIDs[3]-runIDs[7]) @@ -1502,7 +1539,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // Internally these queries are batched by 1000, this tests case requiring concatenation // of more than 1 batch t.Run("with batch concatenation limit 100", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 95, 100) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 95, 100) require.NoError(t, err) require.Len(t, runIDs, 100) assert.Equal(t, int64(67*(len(jobs)-1)), runIDs[12]-runIDs[79]) @@ -1516,7 +1554,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // returns empty. This can happen if the job id being requested hasn't run in a while, // but many other jobs have run since. t.Run("with first batch empty, over limit", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 0, 25) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 0, 25) require.NoError(t, err) require.Len(t, runIDs, 25) assert.Equal(t, int64(16*(len(jobs)-1)), runIDs[7]-runIDs[23]) @@ -1524,7 +1563,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // Same as previous, but where there are fewer matching jobs than the limit t.Run("with first batch empty, under limit", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 143, 190) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 143, 190) require.NoError(t, err) require.Len(t, runIDs, 107) assert.Equal(t, int64(16*(len(jobs)-1)), runIDs[7]-runIDs[23]) @@ -1546,7 +1586,7 @@ func Test_FindPipelineRunsByIDs(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1563,19 +1603,21 @@ func Test_FindPipelineRunsByIDs(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - runs, err2 := orm.FindPipelineRunsByIDs([]int64{-1}) + ctx := testutils.Context(t) + runs, err2 := orm.FindPipelineRunsByIDs(ctx, []int64{-1}) require.NoError(t, err2) assert.Empty(t, runs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - actual, err2 := orm.FindPipelineRunsByIDs([]int64{run.ID}) + actual, err2 := orm.FindPipelineRunsByIDs(ctx, []int64{run.ID}) require.NoError(t, err2) require.Len(t, actual, 1) @@ -1603,24 +1645,26 @@ func Test_FindPipelineRunByID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline run", func(t *testing.T) { - run, err2 := orm.FindPipelineRunByID(-1) + ctx := testutils.Context(t) + run, err2 := orm.FindPipelineRunByID(ctx, -1) assert.Equal(t, run, pipeline.Run{}) require.ErrorIs(t, err2, sql.ErrNoRows) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - actual, err2 := orm.FindPipelineRunByID(run.ID) + actual, err2 := orm.FindPipelineRunByID(ctx, run.ID) require.NoError(t, err2) actualRun := actual @@ -1647,12 +1691,12 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(ctx, &jb) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -1660,10 +1704,10 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) { ocrSpecError1 := "ocr spec 1 errored" ocrSpecError2 := "ocr spec 2 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) - jb, err = orm.FindJobWithoutSpecErrors(jobSpec.ID) + jb, err = orm.FindJobWithoutSpecErrors(ctx, jobSpec.ID) require.NoError(t, err) jbWithErrors, err := orm.FindJobTx(testutils.Context(t), jobSpec.ID) require.NoError(t, err) @@ -1685,12 +1729,12 @@ func Test_FindSpecErrorsByJobIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(ctx, &jb) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -1698,10 +1742,10 @@ func Test_FindSpecErrorsByJobIDs(t *testing.T) { ocrSpecError1 := "ocr spec 1 errored" ocrSpecError2 := "ocr spec 2 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) - specErrs, err := orm.FindSpecErrorsByJobIDs([]int32{jobSpec.ID}) + specErrs, err := orm.FindSpecErrorsByJobIDs(ctx, []int32{jobSpec.ID}) require.NoError(t, err) assert.Equal(t, len(specErrs), 2) @@ -1722,7 +1766,7 @@ func Test_CountPipelineRunsByJobID(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1739,19 +1783,21 @@ func Test_CountPipelineRunsByJobID(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - count, err2 := orm.CountPipelineRunsByJobID(jb.ID) + ctx := testutils.Context(t) + count, err2 := orm.CountPipelineRunsByJobID(ctx, jb.ID) require.NoError(t, err2) assert.Equal(t, int32(0), count) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) mustInsertPipelineRun(t, pipelineORM, jb) - count, err2 := orm.CountPipelineRunsByJobID(jb.ID) + count, err2 := orm.CountPipelineRunsByJobID(ctx, jb.ID) require.NoError(t, err2) require.Equal(t, int32(1), count) }) diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go index 33ee6dc306c..f8a43bca34d 100644 --- a/core/services/job/job_pipeline_orm_integration_test.go +++ b/core/services/job/job_pipeline_orm_integration_test.go @@ -135,7 +135,7 @@ func TestPipelineORM_Integration(t *testing.T) { p, err := pipeline.Parse(DotStr) require.NoError(t, err) - specID, err = orm.CreateSpec(ctx, nil, *p, models.Interval(0)) + specID, err = orm.CreateSpec(ctx, *p, models.Interval(0)) require.NoError(t, err) var pipelineSpecs []pipeline.Spec @@ -160,12 +160,12 @@ func TestPipelineORM_Integration(t *testing.T) { legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) runner := pipeline.NewRunner(orm, btORM, config.JobPipeline(), cfg.WebServer(), legacyChains, nil, nil, lggr, nil, nil) - jobORM := NewTestORM(t, db, orm, btORM, keyStore, cfg.Database()) + jobORM := NewTestORM(t, db, orm, btORM, keyStore) dbSpec := makeVoterTurnoutOCRJobSpec(t, transmitterAddress, bridge.Name.String(), bridge2.Name.String()) // Need a job in order to create a run - require.NoError(t, jobORM.CreateJob(dbSpec)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), dbSpec)) var pipelineSpecs []pipeline.Spec sql := `SELECT pipeline_specs.*, job_pipeline_specs.job_id FROM pipeline_specs JOIN job_pipeline_specs ON (pipeline_specs.id = job_pipeline_specs.pipeline_spec_id);` diff --git a/core/services/job/kv_orm.go b/core/services/job/kv_orm.go index 6108c123a62..63384efc25b 100644 --- a/core/services/job/kv_orm.go +++ b/core/services/job/kv_orm.go @@ -5,10 +5,8 @@ import ( "fmt" "time" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) // KVStore is a simple KV store that can store and retrieve serializable data. @@ -21,17 +19,17 @@ type KVStore interface { type kVStore struct { jobID int32 - q pg.Q + ds sqlutil.DataSource lggr logger.SugaredLogger } var _ KVStore = (*kVStore)(nil) -func NewKVStore(jobID int32, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) kVStore { +func NewKVStore(jobID int32, ds sqlutil.DataSource, lggr logger.Logger) kVStore { namedLogger := logger.Sugared(lggr.Named("JobORM")) return kVStore{ jobID: jobID, - q: pg.NewQ(db, namedLogger, cfg), + ds: ds, lggr: namedLogger, } } @@ -45,7 +43,7 @@ func (kv kVStore) Store(ctx context.Context, key string, val []byte) error { val_bytea = EXCLUDED.val_bytea, updated_at = $4;` - if _, err := kv.q.ExecContext(ctx, sql, kv.jobID, key, val, time.Now()); err != nil { + if _, err := kv.ds.ExecContext(ctx, sql, kv.jobID, key, val, time.Now()); err != nil { return fmt.Errorf("failed to store value: %s for key: %s for jobID: %d : %w", string(val), key, kv.jobID, err) } return nil @@ -55,7 +53,7 @@ func (kv kVStore) Store(ctx context.Context, key string, val []byte) error { func (kv kVStore) Get(ctx context.Context, key string) ([]byte, error) { var val []byte sql := "SELECT val_bytea FROM job_kv_store WHERE job_id = $1 AND key = $2" - if err := kv.q.GetContext(ctx, &val, sql, kv.jobID, key); err != nil { + if err := kv.ds.GetContext(ctx, &val, sql, kv.jobID, key); err != nil { return nil, fmt.Errorf("failed to get value by key: %s for jobID: %d : %w", key, kv.jobID, err) } diff --git a/core/services/job/kv_orm_test.go b/core/services/job/kv_orm_test.go index 156779ffb4d..0f229f09d88 100644 --- a/core/services/job/kv_orm_test.go +++ b/core/services/job/kv_orm_test.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -33,13 +34,13 @@ func TestJobKVStore(t *testing.T) { bridgesORM := bridges.NewORM(db) jobID := int32(1337) - kvStore := job.NewKVStore(jobID, db, config.Database(), lggr) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, cltest.NewKeyStore(t, db), config.Database()) + kvStore := job.NewKVStore(jobID, db, lggr) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, cltest.NewKeyStore(t, db)) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) jb.ID = jobID - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), &jb)) var values = [][]byte{ []byte("Hello"), @@ -72,5 +73,5 @@ func TestJobKVStore(t *testing.T) { require.NoError(t, err) require.Equal(t, td2, fetchedBytes) - require.NoError(t, jobORM.DeleteJob(jobID)) + require.NoError(t, jobORM.DeleteJob(ctx, jobID)) } diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index b8534b9d688..ec60137de93 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -12,10 +12,10 @@ import ( mock "github.com/stretchr/testify/mock" - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" - pipeline "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" uuid "github.com/google/uuid" @@ -62,9 +62,9 @@ func (_m *ORM) Close() error { return r0 } -// CountPipelineRunsByJobID provides a mock function with given fields: jobID -func (_m *ORM) CountPipelineRunsByJobID(jobID int32) (int32, error) { - ret := _m.Called(jobID) +// CountPipelineRunsByJobID provides a mock function with given fields: ctx, jobID +func (_m *ORM) CountPipelineRunsByJobID(ctx context.Context, jobID int32) (int32, error) { + ret := _m.Called(ctx, jobID) if len(ret) == 0 { panic("no return value specified for CountPipelineRunsByJobID") @@ -72,17 +72,17 @@ func (_m *ORM) CountPipelineRunsByJobID(jobID int32) (int32, error) { var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(int32) (int32, error)); ok { - return rf(jobID) + if rf, ok := ret.Get(0).(func(context.Context, int32) (int32, error)); ok { + return rf(ctx, jobID) } - if rf, ok := ret.Get(0).(func(int32) int32); ok { - r0 = rf(jobID) + if rf, ok := ret.Get(0).(func(context.Context, int32) int32); ok { + r0 = rf(ctx, jobID) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(int32) error); ok { - r1 = rf(jobID) + if rf, ok := ret.Get(1).(func(context.Context, int32) error); ok { + r1 = rf(ctx, jobID) } else { r1 = ret.Error(1) } @@ -90,24 +90,17 @@ func (_m *ORM) CountPipelineRunsByJobID(jobID int32) (int32, error) { return r0, r1 } -// CreateJob provides a mock function with given fields: jb, qopts -func (_m *ORM) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jb) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateJob provides a mock function with given fields: ctx, jb +func (_m *ORM) CreateJob(ctx context.Context, jb *job.Job) error { + ret := _m.Called(ctx, jb) if len(ret) == 0 { panic("no return value specified for CreateJob") } var r0 error - if rf, ok := ret.Get(0).(func(*job.Job, ...pg.QOpt) error); ok { - r0 = rf(jb, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *job.Job) error); ok { + r0 = rf(ctx, jb) } else { r0 = ret.Error(0) } @@ -115,24 +108,37 @@ func (_m *ORM) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { return r0 } -// DeleteJob provides a mock function with given fields: id, qopts -func (_m *ORM) DeleteJob(id int32, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] +// DataSource provides a mock function with given fields: +func (_m *ORM) DataSource() sqlutil.DataSource { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for DataSource") + } + + var r0 sqlutil.DataSource + if rf, ok := ret.Get(0).(func() sqlutil.DataSource); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(sqlutil.DataSource) + } } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) + + return r0 +} + +// DeleteJob provides a mock function with given fields: ctx, id +func (_m *ORM) DeleteJob(ctx context.Context, id int32) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for DeleteJob") } var r0 error - if rf, ok := ret.Get(0).(func(int32, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int32) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -186,16 +192,9 @@ func (_m *ORM) FindJob(ctx context.Context, id int32) (job.Job, error) { return r0, r1 } -// FindJobByExternalJobID provides a mock function with given fields: _a0, qopts -func (_m *ORM) FindJobByExternalJobID(_a0 uuid.UUID, qopts ...pg.QOpt) (job.Job, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, _a0) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindJobByExternalJobID provides a mock function with given fields: ctx, _a1 +func (_m *ORM) FindJobByExternalJobID(ctx context.Context, _a1 uuid.UUID) (job.Job, error) { + ret := _m.Called(ctx, _a1) if len(ret) == 0 { panic("no return value specified for FindJobByExternalJobID") @@ -203,17 +202,17 @@ func (_m *ORM) FindJobByExternalJobID(_a0 uuid.UUID, qopts ...pg.QOpt) (job.Job, var r0 job.Job var r1 error - if rf, ok := ret.Get(0).(func(uuid.UUID, ...pg.QOpt) (job.Job, error)); ok { - return rf(_a0, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) (job.Job, error)); ok { + return rf(ctx, _a1) } - if rf, ok := ret.Get(0).(func(uuid.UUID, ...pg.QOpt) job.Job); ok { - r0 = rf(_a0, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) job.Job); ok { + r0 = rf(ctx, _a1) } else { r0 = ret.Get(0).(job.Job) } - if rf, ok := ret.Get(1).(func(uuid.UUID, ...pg.QOpt) error); ok { - r1 = rf(_a0, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, _a1) } else { r1 = ret.Error(1) } @@ -221,16 +220,9 @@ func (_m *ORM) FindJobByExternalJobID(_a0 uuid.UUID, qopts ...pg.QOpt) (job.Job, return r0, r1 } -// FindJobIDByAddress provides a mock function with given fields: address, evmChainID, qopts -func (_m *ORM) FindJobIDByAddress(address types.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (int32, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, address, evmChainID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindJobIDByAddress provides a mock function with given fields: ctx, address, evmChainID +func (_m *ORM) FindJobIDByAddress(ctx context.Context, address types.EIP55Address, evmChainID *big.Big) (int32, error) { + ret := _m.Called(ctx, address, evmChainID) if len(ret) == 0 { panic("no return value specified for FindJobIDByAddress") @@ -238,17 +230,17 @@ func (_m *ORM) FindJobIDByAddress(address types.EIP55Address, evmChainID *big.Bi var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(types.EIP55Address, *big.Big, ...pg.QOpt) (int32, error)); ok { - return rf(address, evmChainID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, types.EIP55Address, *big.Big) (int32, error)); ok { + return rf(ctx, address, evmChainID) } - if rf, ok := ret.Get(0).(func(types.EIP55Address, *big.Big, ...pg.QOpt) int32); ok { - r0 = rf(address, evmChainID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, types.EIP55Address, *big.Big) int32); ok { + r0 = rf(ctx, address, evmChainID) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(types.EIP55Address, *big.Big, ...pg.QOpt) error); ok { - r1 = rf(address, evmChainID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, types.EIP55Address, *big.Big) error); ok { + r1 = rf(ctx, address, evmChainID) } else { r1 = ret.Error(1) } @@ -256,9 +248,9 @@ func (_m *ORM) FindJobIDByAddress(address types.EIP55Address, evmChainID *big.Bi return r0, r1 } -// FindJobIDsWithBridge provides a mock function with given fields: name -func (_m *ORM) FindJobIDsWithBridge(name string) ([]int32, error) { - ret := _m.Called(name) +// FindJobIDsWithBridge provides a mock function with given fields: ctx, name +func (_m *ORM) FindJobIDsWithBridge(ctx context.Context, name string) ([]int32, error) { + ret := _m.Called(ctx, name) if len(ret) == 0 { panic("no return value specified for FindJobIDsWithBridge") @@ -266,19 +258,19 @@ func (_m *ORM) FindJobIDsWithBridge(name string) ([]int32, error) { var r0 []int32 var r1 error - if rf, ok := ret.Get(0).(func(string) ([]int32, error)); ok { - return rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) ([]int32, error)); ok { + return rf(ctx, name) } - if rf, ok := ret.Get(0).(func(string) []int32); ok { - r0 = rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) []int32); ok { + r0 = rf(ctx, name) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]int32) } } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, name) } else { r1 = ret.Error(1) } @@ -314,9 +306,9 @@ func (_m *ORM) FindJobTx(ctx context.Context, id int32) (job.Job, error) { return r0, r1 } -// FindJobWithoutSpecErrors provides a mock function with given fields: id -func (_m *ORM) FindJobWithoutSpecErrors(id int32) (job.Job, error) { - ret := _m.Called(id) +// FindJobWithoutSpecErrors provides a mock function with given fields: ctx, id +func (_m *ORM) FindJobWithoutSpecErrors(ctx context.Context, id int32) (job.Job, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for FindJobWithoutSpecErrors") @@ -324,17 +316,17 @@ func (_m *ORM) FindJobWithoutSpecErrors(id int32) (job.Job, error) { var r0 job.Job var r1 error - if rf, ok := ret.Get(0).(func(int32) (job.Job, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int32) (job.Job, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int32) job.Job); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int32) job.Job); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(job.Job) } - if rf, ok := ret.Get(1).(func(int32) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int32) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -342,9 +334,9 @@ func (_m *ORM) FindJobWithoutSpecErrors(id int32) (job.Job, error) { return r0, r1 } -// FindJobs provides a mock function with given fields: offset, limit -func (_m *ORM) FindJobs(offset int, limit int) ([]job.Job, int, error) { - ret := _m.Called(offset, limit) +// FindJobs provides a mock function with given fields: ctx, offset, limit +func (_m *ORM) FindJobs(ctx context.Context, offset int, limit int) ([]job.Job, int, error) { + ret := _m.Called(ctx, offset, limit) if len(ret) == 0 { panic("no return value specified for FindJobs") @@ -353,25 +345,25 @@ func (_m *ORM) FindJobs(offset int, limit int) ([]job.Job, int, error) { var r0 []job.Job var r1 int var r2 error - if rf, ok := ret.Get(0).(func(int, int) ([]job.Job, int, error)); ok { - return rf(offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]job.Job, int, error)); ok { + return rf(ctx, offset, limit) } - if rf, ok := ret.Get(0).(func(int, int) []job.Job); ok { - r0 = rf(offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int, int) []job.Job); ok { + r0 = rf(ctx, offset, limit) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]job.Job) } } - if rf, ok := ret.Get(1).(func(int, int) int); ok { - r1 = rf(offset, limit) + if rf, ok := ret.Get(1).(func(context.Context, int, int) int); ok { + r1 = rf(ctx, offset, limit) } else { r1 = ret.Get(1).(int) } - if rf, ok := ret.Get(2).(func(int, int) error); ok { - r2 = rf(offset, limit) + if rf, ok := ret.Get(2).(func(context.Context, int, int) error); ok { + r2 = rf(ctx, offset, limit) } else { r2 = ret.Error(2) } @@ -379,9 +371,9 @@ func (_m *ORM) FindJobs(offset int, limit int) ([]job.Job, int, error) { return r0, r1, r2 } -// FindJobsByPipelineSpecIDs provides a mock function with given fields: ids -func (_m *ORM) FindJobsByPipelineSpecIDs(ids []int32) ([]job.Job, error) { - ret := _m.Called(ids) +// FindJobsByPipelineSpecIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]job.Job, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for FindJobsByPipelineSpecIDs") @@ -389,19 +381,19 @@ func (_m *ORM) FindJobsByPipelineSpecIDs(ids []int32) ([]job.Job, error) { var r0 []job.Job var r1 error - if rf, ok := ret.Get(0).(func([]int32) ([]job.Job, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int32) ([]job.Job, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int32) []job.Job); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int32) []job.Job); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]job.Job) } } - if rf, ok := ret.Get(1).(func([]int32) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int32) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -409,16 +401,9 @@ func (_m *ORM) FindJobsByPipelineSpecIDs(ids []int32) ([]job.Job, error) { return r0, r1 } -// FindOCR2JobIDByAddress provides a mock function with given fields: contractID, feedID, qopts -func (_m *ORM) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qopts ...pg.QOpt) (int32, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, contractID, feedID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindOCR2JobIDByAddress provides a mock function with given fields: ctx, contractID, feedID +func (_m *ORM) FindOCR2JobIDByAddress(ctx context.Context, contractID string, feedID *common.Hash) (int32, error) { + ret := _m.Called(ctx, contractID, feedID) if len(ret) == 0 { panic("no return value specified for FindOCR2JobIDByAddress") @@ -426,17 +411,17 @@ func (_m *ORM) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qo var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(string, *common.Hash, ...pg.QOpt) (int32, error)); ok { - return rf(contractID, feedID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, string, *common.Hash) (int32, error)); ok { + return rf(ctx, contractID, feedID) } - if rf, ok := ret.Get(0).(func(string, *common.Hash, ...pg.QOpt) int32); ok { - r0 = rf(contractID, feedID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, string, *common.Hash) int32); ok { + r0 = rf(ctx, contractID, feedID) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(string, *common.Hash, ...pg.QOpt) error); ok { - r1 = rf(contractID, feedID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, string, *common.Hash) error); ok { + r1 = rf(ctx, contractID, feedID) } else { r1 = ret.Error(1) } @@ -444,9 +429,9 @@ func (_m *ORM) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qo return r0, r1 } -// FindPipelineRunByID provides a mock function with given fields: id -func (_m *ORM) FindPipelineRunByID(id int64) (pipeline.Run, error) { - ret := _m.Called(id) +// FindPipelineRunByID provides a mock function with given fields: ctx, id +func (_m *ORM) FindPipelineRunByID(ctx context.Context, id int64) (pipeline.Run, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for FindPipelineRunByID") @@ -454,17 +439,17 @@ func (_m *ORM) FindPipelineRunByID(id int64) (pipeline.Run, error) { var r0 pipeline.Run var r1 error - if rf, ok := ret.Get(0).(func(int64) (pipeline.Run, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (pipeline.Run, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) pipeline.Run); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) pipeline.Run); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(pipeline.Run) } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -472,9 +457,9 @@ func (_m *ORM) FindPipelineRunByID(id int64) (pipeline.Run, error) { return r0, r1 } -// FindPipelineRunIDsByJobID provides a mock function with given fields: jobID, offset, limit -func (_m *ORM) FindPipelineRunIDsByJobID(jobID int32, offset int, limit int) ([]int64, error) { - ret := _m.Called(jobID, offset, limit) +// FindPipelineRunIDsByJobID provides a mock function with given fields: ctx, jobID, offset, limit +func (_m *ORM) FindPipelineRunIDsByJobID(ctx context.Context, jobID int32, offset int, limit int) ([]int64, error) { + ret := _m.Called(ctx, jobID, offset, limit) if len(ret) == 0 { panic("no return value specified for FindPipelineRunIDsByJobID") @@ -482,19 +467,19 @@ func (_m *ORM) FindPipelineRunIDsByJobID(jobID int32, offset int, limit int) ([] var r0 []int64 var r1 error - if rf, ok := ret.Get(0).(func(int32, int, int) ([]int64, error)); ok { - return rf(jobID, offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int32, int, int) ([]int64, error)); ok { + return rf(ctx, jobID, offset, limit) } - if rf, ok := ret.Get(0).(func(int32, int, int) []int64); ok { - r0 = rf(jobID, offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int32, int, int) []int64); ok { + r0 = rf(ctx, jobID, offset, limit) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]int64) } } - if rf, ok := ret.Get(1).(func(int32, int, int) error); ok { - r1 = rf(jobID, offset, limit) + if rf, ok := ret.Get(1).(func(context.Context, int32, int, int) error); ok { + r1 = rf(ctx, jobID, offset, limit) } else { r1 = ret.Error(1) } @@ -502,9 +487,9 @@ func (_m *ORM) FindPipelineRunIDsByJobID(jobID int32, offset int, limit int) ([] return r0, r1 } -// FindPipelineRunsByIDs provides a mock function with given fields: ids -func (_m *ORM) FindPipelineRunsByIDs(ids []int64) ([]pipeline.Run, error) { - ret := _m.Called(ids) +// FindPipelineRunsByIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) FindPipelineRunsByIDs(ctx context.Context, ids []int64) ([]pipeline.Run, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for FindPipelineRunsByIDs") @@ -512,19 +497,19 @@ func (_m *ORM) FindPipelineRunsByIDs(ids []int64) ([]pipeline.Run, error) { var r0 []pipeline.Run var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]pipeline.Run, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]pipeline.Run, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []pipeline.Run); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []pipeline.Run); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]pipeline.Run) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -532,16 +517,9 @@ func (_m *ORM) FindPipelineRunsByIDs(ids []int64) ([]pipeline.Run, error) { return r0, r1 } -// FindSpecError provides a mock function with given fields: id, qopts -func (_m *ORM) FindSpecError(id int64, qopts ...pg.QOpt) (job.SpecError, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindSpecError provides a mock function with given fields: ctx, id +func (_m *ORM) FindSpecError(ctx context.Context, id int64) (job.SpecError, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for FindSpecError") @@ -549,17 +527,17 @@ func (_m *ORM) FindSpecError(id int64, qopts ...pg.QOpt) (job.SpecError, error) var r0 job.SpecError var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (job.SpecError, error)); ok { - return rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (job.SpecError, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) job.SpecError); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) job.SpecError); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(job.SpecError) } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(id, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -567,16 +545,9 @@ func (_m *ORM) FindSpecError(id int64, qopts ...pg.QOpt) (job.SpecError, error) return r0, r1 } -// FindSpecErrorsByJobIDs provides a mock function with given fields: ids, qopts -func (_m *ORM) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]job.SpecError, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ids) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindSpecErrorsByJobIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) FindSpecErrorsByJobIDs(ctx context.Context, ids []int32) ([]job.SpecError, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for FindSpecErrorsByJobIDs") @@ -584,19 +555,19 @@ func (_m *ORM) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]job.Spec var r0 []job.SpecError var r1 error - if rf, ok := ret.Get(0).(func([]int32, ...pg.QOpt) ([]job.SpecError, error)); ok { - return rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int32) ([]job.SpecError, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int32, ...pg.QOpt) []job.SpecError); ok { - r0 = rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int32) []job.SpecError); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]job.SpecError) } } - if rf, ok := ret.Get(1).(func([]int32, ...pg.QOpt) error); ok { - r1 = rf(ids, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []int32) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -604,16 +575,9 @@ func (_m *ORM) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]job.Spec return r0, r1 } -// FindTaskResultByRunIDAndTaskName provides a mock function with given fields: runID, taskName, qopts -func (_m *ORM) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qopts ...pg.QOpt) ([]byte, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, runID, taskName) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindTaskResultByRunIDAndTaskName provides a mock function with given fields: ctx, runID, taskName +func (_m *ORM) FindTaskResultByRunIDAndTaskName(ctx context.Context, runID int64, taskName string) ([]byte, error) { + ret := _m.Called(ctx, runID, taskName) if len(ret) == 0 { panic("no return value specified for FindTaskResultByRunIDAndTaskName") @@ -621,19 +585,19 @@ func (_m *ORM) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qo var r0 []byte var r1 error - if rf, ok := ret.Get(0).(func(int64, string, ...pg.QOpt) ([]byte, error)); ok { - return rf(runID, taskName, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) ([]byte, error)); ok { + return rf(ctx, runID, taskName) } - if rf, ok := ret.Get(0).(func(int64, string, ...pg.QOpt) []byte); ok { - r0 = rf(runID, taskName, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) []byte); ok { + r0 = rf(ctx, runID, taskName) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]byte) } } - if rf, ok := ret.Get(1).(func(int64, string, ...pg.QOpt) error); ok { - r1 = rf(runID, taskName, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok { + r1 = rf(ctx, runID, taskName) } else { r1 = ret.Error(1) } @@ -641,24 +605,17 @@ func (_m *ORM) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qo return r0, r1 } -// InsertJob provides a mock function with given fields: _a0, qopts -func (_m *ORM) InsertJob(_a0 *job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, _a0) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// InsertJob provides a mock function with given fields: ctx, _a1 +func (_m *ORM) InsertJob(ctx context.Context, _a1 *job.Job) error { + ret := _m.Called(ctx, _a1) if len(ret) == 0 { panic("no return value specified for InsertJob") } var r0 error - if rf, ok := ret.Get(0).(func(*job.Job, ...pg.QOpt) error); ok { - r0 = rf(_a0, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *job.Job) error); ok { + r0 = rf(ctx, _a1) } else { r0 = ret.Error(0) } @@ -666,24 +623,17 @@ func (_m *ORM) InsertJob(_a0 *job.Job, qopts ...pg.QOpt) error { return r0 } -// InsertWebhookSpec provides a mock function with given fields: webhookSpec, qopts -func (_m *ORM) InsertWebhookSpec(webhookSpec *job.WebhookSpec, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, webhookSpec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// InsertWebhookSpec provides a mock function with given fields: ctx, webhookSpec +func (_m *ORM) InsertWebhookSpec(ctx context.Context, webhookSpec *job.WebhookSpec) error { + ret := _m.Called(ctx, webhookSpec) if len(ret) == 0 { panic("no return value specified for InsertWebhookSpec") } var r0 error - if rf, ok := ret.Get(0).(func(*job.WebhookSpec, ...pg.QOpt) error); ok { - r0 = rf(webhookSpec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *job.WebhookSpec) error); ok { + r0 = rf(ctx, webhookSpec) } else { r0 = ret.Error(0) } @@ -691,9 +641,9 @@ func (_m *ORM) InsertWebhookSpec(webhookSpec *job.WebhookSpec, qopts ...pg.QOpt) return r0 } -// PipelineRuns provides a mock function with given fields: jobID, offset, size -func (_m *ORM) PipelineRuns(jobID *int32, offset int, size int) ([]pipeline.Run, int, error) { - ret := _m.Called(jobID, offset, size) +// PipelineRuns provides a mock function with given fields: ctx, jobID, offset, size +func (_m *ORM) PipelineRuns(ctx context.Context, jobID *int32, offset int, size int) ([]pipeline.Run, int, error) { + ret := _m.Called(ctx, jobID, offset, size) if len(ret) == 0 { panic("no return value specified for PipelineRuns") @@ -702,25 +652,25 @@ func (_m *ORM) PipelineRuns(jobID *int32, offset int, size int) ([]pipeline.Run, var r0 []pipeline.Run var r1 int var r2 error - if rf, ok := ret.Get(0).(func(*int32, int, int) ([]pipeline.Run, int, error)); ok { - return rf(jobID, offset, size) + if rf, ok := ret.Get(0).(func(context.Context, *int32, int, int) ([]pipeline.Run, int, error)); ok { + return rf(ctx, jobID, offset, size) } - if rf, ok := ret.Get(0).(func(*int32, int, int) []pipeline.Run); ok { - r0 = rf(jobID, offset, size) + if rf, ok := ret.Get(0).(func(context.Context, *int32, int, int) []pipeline.Run); ok { + r0 = rf(ctx, jobID, offset, size) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]pipeline.Run) } } - if rf, ok := ret.Get(1).(func(*int32, int, int) int); ok { - r1 = rf(jobID, offset, size) + if rf, ok := ret.Get(1).(func(context.Context, *int32, int, int) int); ok { + r1 = rf(ctx, jobID, offset, size) } else { r1 = ret.Get(1).(int) } - if rf, ok := ret.Get(2).(func(*int32, int, int) error); ok { - r2 = rf(jobID, offset, size) + if rf, ok := ret.Get(2).(func(context.Context, *int32, int, int) error); ok { + r2 = rf(ctx, jobID, offset, size) } else { r2 = ret.Error(2) } @@ -728,24 +678,17 @@ func (_m *ORM) PipelineRuns(jobID *int32, offset int, size int) ([]pipeline.Run, return r0, r1, r2 } -// RecordError provides a mock function with given fields: jobID, description, qopts -func (_m *ORM) RecordError(jobID int32, description string, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jobID, description) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// RecordError provides a mock function with given fields: ctx, jobID, description +func (_m *ORM) RecordError(ctx context.Context, jobID int32, description string) error { + ret := _m.Called(ctx, jobID, description) if len(ret) == 0 { panic("no return value specified for RecordError") } var r0 error - if rf, ok := ret.Get(0).(func(int32, string, ...pg.QOpt) error); ok { - r0 = rf(jobID, description, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int32, string) error); ok { + r0 = rf(ctx, jobID, description) } else { r0 = ret.Error(0) } @@ -753,16 +696,29 @@ func (_m *ORM) RecordError(jobID int32, description string, qopts ...pg.QOpt) er return r0 } -// TryRecordError provides a mock function with given fields: jobID, description, qopts -func (_m *ORM) TryRecordError(jobID int32, description string, qopts ...pg.QOpt) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] +// TryRecordError provides a mock function with given fields: ctx, jobID, description +func (_m *ORM) TryRecordError(ctx context.Context, jobID int32, description string) { + _m.Called(ctx, jobID, description) +} + +// WithDataSource provides a mock function with given fields: source +func (_m *ORM) WithDataSource(source sqlutil.DataSource) job.ORM { + ret := _m.Called(source) + + if len(ret) == 0 { + panic("no return value specified for WithDataSource") } - var _ca []interface{} - _ca = append(_ca, jobID, description) - _ca = append(_ca, _va...) - _m.Called(_ca...) + + var r0 job.ORM + if rf, ok := ret.Get(0).(func(sqlutil.DataSource) job.ORM); ok { + r0 = rf(source) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(job.ORM) + } + } + + return r0 } // NewORM creates a new instance of ORM. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. diff --git a/core/services/job/mocks/spawner.go b/core/services/job/mocks/spawner.go index 37e883ef3c5..7127636cdbb 100644 --- a/core/services/job/mocks/spawner.go +++ b/core/services/job/mocks/spawner.go @@ -8,7 +8,7 @@ import ( job "github.com/smartcontractkit/chainlink/v2/core/services/job" mock "github.com/stretchr/testify/mock" - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" + sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) // Spawner is an autogenerated mock type for the Spawner type @@ -54,24 +54,17 @@ func (_m *Spawner) Close() error { return r0 } -// CreateJob provides a mock function with given fields: jb, qopts -func (_m *Spawner) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jb) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateJob provides a mock function with given fields: ctx, ds, jb +func (_m *Spawner) CreateJob(ctx context.Context, ds sqlutil.DataSource, jb *job.Job) error { + ret := _m.Called(ctx, ds, jb) if len(ret) == 0 { panic("no return value specified for CreateJob") } var r0 error - if rf, ok := ret.Get(0).(func(*job.Job, ...pg.QOpt) error); ok { - r0 = rf(jb, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, sqlutil.DataSource, *job.Job) error); ok { + r0 = rf(ctx, ds, jb) } else { r0 = ret.Error(0) } @@ -79,24 +72,17 @@ func (_m *Spawner) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { return r0 } -// DeleteJob provides a mock function with given fields: jobID, qopts -func (_m *Spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jobID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// DeleteJob provides a mock function with given fields: ctx, ds, jobID +func (_m *Spawner) DeleteJob(ctx context.Context, ds sqlutil.DataSource, jobID int32) error { + ret := _m.Called(ctx, ds, jobID) if len(ret) == 0 { panic("no return value specified for DeleteJob") } var r0 error - if rf, ok := ret.Get(0).(func(int32, ...pg.QOpt) error); ok { - r0 = rf(jobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, sqlutil.DataSource, int32) error); ok { + r0 = rf(ctx, ds, jobID) } else { r0 = ret.Error(0) } @@ -178,24 +164,17 @@ func (_m *Spawner) Start(_a0 context.Context) error { return r0 } -// StartService provides a mock function with given fields: ctx, spec, qopts -func (_m *Spawner) StartService(ctx context.Context, spec job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, spec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// StartService provides a mock function with given fields: ctx, spec +func (_m *Spawner) StartService(ctx context.Context, spec job.Job) error { + ret := _m.Called(ctx, spec) if len(ret) == 0 { panic("no return value specified for StartService") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, job.Job, ...pg.QOpt) error); ok { - r0 = rf(ctx, spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, job.Job) error); ok { + r0 = rf(ctx, spec) } else { r0 = ret.Error(0) } diff --git a/core/services/job/models.go b/core/services/job/models.go index 0c6390b3dbf..3d510efa0d2 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -362,6 +362,7 @@ type OCR2OracleSpec struct { BlockchainTimeout models.Interval `toml:"blockchainTimeout"` ContractConfigTrackerPollInterval models.Interval `toml:"contractConfigTrackerPollInterval"` ContractConfigConfirmations uint16 `toml:"contractConfigConfirmations"` + OnchainSigningStrategy JSONConfig `toml:"onchainSigningStrategy"` PluginConfig JSONConfig `toml:"pluginConfig"` PluginType types.OCR2PluginType `toml:"pluginType"` CreatedAt time.Time `toml:"-"` diff --git a/core/services/job/models_test.go b/core/services/job/models_test.go index 4d10fbb43c4..c177b3b81e1 100644 --- a/core/services/job/models_test.go +++ b/core/services/job/models_test.go @@ -219,6 +219,13 @@ func TestOCR2OracleSpec(t *testing.T) { }, }, }, + OnchainSigningStrategy: map[string]interface{}{ + "strategyName": "single-chain", + "config": map[string]interface{}{ + "evm": "", + "publicKey": "0xdeadbeef", + }, + }, PluginConfig: map[string]interface{}{"juelsPerFeeCoinSource": ` // data source 1 ds1 [type=bridge name="%s"]; ds1_parse [type=jsonparse path="data"]; diff --git a/core/services/job/orm.go b/core/services/job/orm.go index f7238799634..d87b0204263 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -18,6 +18,7 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -29,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" medianconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median/config" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -44,37 +44,40 @@ var ( //go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore type ORM interface { - InsertWebhookSpec(webhookSpec *WebhookSpec, qopts ...pg.QOpt) error - InsertJob(job *Job, qopts ...pg.QOpt) error - CreateJob(jb *Job, qopts ...pg.QOpt) error - FindJobs(offset, limit int) ([]Job, int, error) + InsertWebhookSpec(ctx context.Context, webhookSpec *WebhookSpec) error + InsertJob(ctx context.Context, job *Job) error + CreateJob(ctx context.Context, jb *Job) error + FindJobs(ctx context.Context, offset, limit int) ([]Job, int, error) FindJobTx(ctx context.Context, id int32) (Job, error) FindJob(ctx context.Context, id int32) (Job, error) - FindJobByExternalJobID(uuid uuid.UUID, qopts ...pg.QOpt) (Job, error) - FindJobIDByAddress(address evmtypes.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (int32, error) - FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qopts ...pg.QOpt) (int32, error) - FindJobIDsWithBridge(name string) ([]int32, error) - DeleteJob(id int32, qopts ...pg.QOpt) error - RecordError(jobID int32, description string, qopts ...pg.QOpt) error + FindJobByExternalJobID(ctx context.Context, uuid uuid.UUID) (Job, error) + FindJobIDByAddress(ctx context.Context, address evmtypes.EIP55Address, evmChainID *big.Big) (int32, error) + FindOCR2JobIDByAddress(ctx context.Context, contractID string, feedID *common.Hash) (int32, error) + FindJobIDsWithBridge(ctx context.Context, name string) ([]int32, error) + DeleteJob(ctx context.Context, id int32) error + RecordError(ctx context.Context, jobID int32, description string) error // TryRecordError is a helper which calls RecordError and logs the returned error if present. - TryRecordError(jobID int32, description string, qopts ...pg.QOpt) + TryRecordError(ctx context.Context, jobID int32, description string) DismissError(ctx context.Context, errorID int64) error - FindSpecError(id int64, qopts ...pg.QOpt) (SpecError, error) + FindSpecError(ctx context.Context, id int64) (SpecError, error) Close() error - PipelineRuns(jobID *int32, offset, size int) ([]pipeline.Run, int, error) + PipelineRuns(ctx context.Context, jobID *int32, offset, size int) ([]pipeline.Run, int, error) - FindPipelineRunIDsByJobID(jobID int32, offset, limit int) (ids []int64, err error) - FindPipelineRunsByIDs(ids []int64) (runs []pipeline.Run, err error) - CountPipelineRunsByJobID(jobID int32) (count int32, err error) + FindPipelineRunIDsByJobID(ctx context.Context, jobID int32, offset, limit int) (ids []int64, err error) + FindPipelineRunsByIDs(ctx context.Context, ids []int64) (runs []pipeline.Run, err error) + CountPipelineRunsByJobID(ctx context.Context, jobID int32) (count int32, err error) - FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) - FindPipelineRunByID(id int64) (pipeline.Run, error) + FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]Job, error) + FindPipelineRunByID(ctx context.Context, id int64) (pipeline.Run, error) - FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]SpecError, error) - FindJobWithoutSpecErrors(id int32) (jb Job, err error) + FindSpecErrorsByJobIDs(ctx context.Context, ids []int32) ([]SpecError, error) + FindJobWithoutSpecErrors(ctx context.Context, id int32) (jb Job, err error) - FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qopts ...pg.QOpt) ([]byte, error) + FindTaskResultByRunIDAndTaskName(ctx context.Context, runID int64, taskName string) ([]byte, error) AssertBridgesExist(ctx context.Context, p pipeline.Pipeline) error + + DataSource() sqlutil.DataSource + WithDataSource(source sqlutil.DataSource) ORM } type ORMConfig interface { @@ -82,31 +85,56 @@ type ORMConfig interface { } type orm struct { - q pg.Q + ds sqlutil.DataSource keyStore keystore.Master pipelineORM pipeline.ORM lggr logger.SugaredLogger - cfg pg.QConfig bridgeORM bridges.ORM } var _ ORM = (*orm)(nil) -func NewORM(db *sqlx.DB, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, lggr logger.Logger, cfg pg.QConfig) *orm { +func NewORM(ds sqlutil.DataSource, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, lggr logger.Logger) *orm { namedLogger := logger.Sugared(lggr.Named("JobORM")) return &orm{ - q: pg.NewQ(db, namedLogger, cfg), + ds: ds, keyStore: keyStore, pipelineORM: pipelineORM, bridgeORM: bridgeORM, lggr: namedLogger, - cfg: cfg, } } + func (o *orm) Close() error { return nil } +func (o *orm) DataSource() sqlutil.DataSource { + return o.ds +} + +func (o *orm) WithDataSource(ds sqlutil.DataSource) ORM { return o.withDataSource(ds) } + +func (o *orm) withDataSource(ds sqlutil.DataSource) *orm { + n := &orm{ + ds: ds, + lggr: o.lggr, + keyStore: o.keyStore, + } + if o.bridgeORM != nil { + n.bridgeORM = o.bridgeORM.WithDataSource(ds) + } + if o.pipelineORM != nil { + n.pipelineORM = o.pipelineORM.WithDataSource(ds) + } + return n +} + +func (o *orm) transact(ctx context.Context, readOnly bool, fn func(*orm) error) error { + opts := &sqlutil.TxOptions{TxOptions: sql.TxOptions{ReadOnly: readOnly}} + return sqlutil.Transact(ctx, o.withDataSource, o.ds, opts, fn) +} + func (o *orm) AssertBridgesExist(ctx context.Context, p pipeline.Pipeline) error { var bridgeNames = make(map[bridges.BridgeName]struct{}) var uniqueBridges []bridges.BridgeName @@ -137,16 +165,14 @@ func (o *orm) AssertBridgesExist(ctx context.Context, p pipeline.Pipeline) error // CreateJob creates the job, and it's associated spec record. // Expects an unmarshalled job spec as the jb argument i.e. output from ValidatedXX. // Scans all persisted records back into jb -func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) +func (o *orm) CreateJob(ctx context.Context, jb *Job) error { p := jb.Pipeline - ctx := context.TODO() // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 if err := o.AssertBridgesExist(ctx, p); err != nil { return err } var jobID int32 - err := q.Transaction(func(tx pg.Queryer) error { + err := o.transact(ctx, false, func(tx *orm) error { // Autogenerate a job ID if not specified if jb.ExternalJobID == (uuid.UUID{}) { jb.ExternalJobID = uuid.New() @@ -157,26 +183,18 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { if jb.DirectRequestSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO direct_request_specs (contract_address, min_incoming_confirmations, requesters, min_contract_payment, evm_chain_id, created_at, updated_at) - VALUES (:contract_address, :min_incoming_confirmations, :requesters, :min_contract_payment, :evm_chain_id, now(), now()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.DirectRequestSpec); err != nil { - return errors.Wrap(err, "failed to create DirectRequestSpec") + specID, err := tx.insertDirectRequestSpec(ctx, jb.DirectRequestSpec) + if err != nil { + return fmt.Errorf("failed to create DirectRequestSpec for jobSpec: %w", err) } jb.DirectRequestSpecID = &specID case FluxMonitor: if jb.FluxMonitorSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO flux_monitor_specs (contract_address, threshold, absolute_threshold, poll_timer_period, poll_timer_disabled, idle_timer_period, idle_timer_disabled, - drumbeat_schedule, drumbeat_random_delay, drumbeat_enabled, min_payment, evm_chain_id, created_at, updated_at) - VALUES (:contract_address, :threshold, :absolute_threshold, :poll_timer_period, :poll_timer_disabled, :idle_timer_period, :idle_timer_disabled, - :drumbeat_schedule, :drumbeat_random_delay, :drumbeat_enabled, :min_payment, :evm_chain_id, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.FluxMonitorSpec); err != nil { - return errors.Wrap(err, "failed to create FluxMonitorSpec") + specID, err := tx.insertFluxMonitorSpec(ctx, jb.FluxMonitorSpec) + if err != nil { + return fmt.Errorf("failed to create FluxMonitorSpec for jobSpec: %w", err) } jb.FluxMonitorSpecID = &specID case OffchainReporting: @@ -184,15 +202,14 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { return errors.New("evm chain id must be defined") } - var specID int32 if jb.OCROracleSpec.EncryptedOCRKeyBundleID != nil { - _, err := o.keyStore.OCR().Get(jb.OCROracleSpec.EncryptedOCRKeyBundleID.String()) + _, err := tx.keyStore.OCR().Get(jb.OCROracleSpec.EncryptedOCRKeyBundleID.String()) if err != nil { return errors.Wrapf(ErrNoSuchKeyBundle, "no key bundle with id: %x", jb.OCROracleSpec.EncryptedOCRKeyBundleID) } } if jb.OCROracleSpec.TransmitterAddress != nil { - _, err := o.keyStore.Eth().Get(q.ParentCtx, jb.OCROracleSpec.TransmitterAddress.Hex()) + _, err := tx.keyStore.Eth().Get(ctx, jb.OCROracleSpec.TransmitterAddress.Hex()) if err != nil { return errors.Wrapf(ErrNoSuchTransmitterKey, "no key matching transmitter address: %s", jb.OCROracleSpec.TransmitterAddress.Hex()) } @@ -200,7 +217,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { newChainID := jb.OCROracleSpec.EVMChainID existingSpec := new(OCROracleSpec) - err := tx.Get(existingSpec, `SELECT * FROM ocr_oracle_specs WHERE contract_address = $1 and (evm_chain_id = $2 or evm_chain_id IS NULL) LIMIT 1;`, + err := tx.ds.GetContext(ctx, existingSpec, `SELECT * FROM ocr_oracle_specs WHERE contract_address = $1 and (evm_chain_id = $2 or evm_chain_id IS NULL) LIMIT 1;`, jb.OCROracleSpec.ContractAddress, newChainID, ) @@ -212,23 +229,14 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { return errors.Errorf("a job with contract address %s already exists for chain ID %s", jb.OCROracleSpec.ContractAddress, newChainID) } - sql := `INSERT INTO ocr_oracle_specs (contract_address, p2pv2_bootstrappers, is_bootstrap_peer, encrypted_ocr_key_bundle_id, transmitter_address, - observation_timeout, blockchain_timeout, contract_config_tracker_subscribe_interval, contract_config_tracker_poll_interval, contract_config_confirmations, evm_chain_id, - created_at, updated_at, database_timeout, observation_grace_period, contract_transmitter_transmit_timeout) - VALUES (:contract_address, :p2pv2_bootstrappers, :is_bootstrap_peer, :encrypted_ocr_key_bundle_id, :transmitter_address, - :observation_timeout, :blockchain_timeout, :contract_config_tracker_subscribe_interval, :contract_config_tracker_poll_interval, :contract_config_confirmations, :evm_chain_id, - NOW(), NOW(), :database_timeout, :observation_grace_period, :contract_transmitter_transmit_timeout) - RETURNING id;` - err = pg.PrepareQueryRowx(tx, sql, &specID, jb.OCROracleSpec) + specID, err := tx.insertOCROracleSpec(ctx, jb.OCROracleSpec) if err != nil { - return errors.Wrap(err, "failed to create OffchainreportingOracleSpec") + return fmt.Errorf("failed to create OCROracleSpec for jobSpec: %w", err) } jb.OCROracleSpecID = &specID case OffchainReporting2: - var specID int32 - if jb.OCR2OracleSpec.OCRKeyBundleID.Valid { - _, err := o.keyStore.OCR2().Get(jb.OCR2OracleSpec.OCRKeyBundleID.String) + _, err := tx.keyStore.OCR2().Get(jb.OCR2OracleSpec.OCRKeyBundleID.String) if err != nil { return errors.Wrapf(ErrNoSuchKeyBundle, "no key bundle with id: %q", jb.OCR2OracleSpec.OCRKeyBundleID.ValueOrZero()) } @@ -239,7 +247,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } // checks if they are present and if they are valid - sendingKeysDefined, err := areSendingKeysDefined(q.ParentCtx, jb, o.keyStore) + sendingKeysDefined, err := areSendingKeysDefined(ctx, jb, tx.keyStore) if err != nil { return err } @@ -249,7 +257,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } if !sendingKeysDefined { - if err = ValidateKeyStoreMatch(q.ParentCtx, jb.OCR2OracleSpec, o.keyStore, jb.OCR2OracleSpec.TransmitterID.String); err != nil { + if err = ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, tx.keyStore, jb.OCR2OracleSpec.TransmitterID.String); err != nil { return errors.Wrap(ErrNoSuchTransmitterKey, err.Error()) } } @@ -278,66 +286,36 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { if err2 != nil { return err2 } - if err2 = o.AssertBridgesExist(ctx, *feePipeline); err2 != nil { + if err2 = tx.AssertBridgesExist(ctx, *feePipeline); err2 != nil { return err2 } } - sql := `INSERT INTO ocr2_oracle_specs (contract_id, feed_id, relay, relay_config, plugin_type, plugin_config, p2pv2_bootstrappers, ocr_key_bundle_id, transmitter_id, - blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, - created_at, updated_at) - VALUES (:contract_id, :feed_id, :relay, :relay_config, :plugin_type, :plugin_config, :p2pv2_bootstrappers, :ocr_key_bundle_id, :transmitter_id, - :blockchain_timeout, :contract_config_tracker_poll_interval, :contract_config_confirmations, - NOW(), NOW()) - RETURNING id;` - err = pg.PrepareQueryRowx(tx, sql, &specID, jb.OCR2OracleSpec) + specID, err := tx.insertOCR2OracleSpec(ctx, jb.OCR2OracleSpec) if err != nil { - return errors.Wrap(err, "failed to create Offchainreporting2OracleSpec") + return fmt.Errorf("failed to create OCR2OracleSpec for jobSpec: %w", err) } jb.OCR2OracleSpecID = &specID case Keeper: if jb.KeeperSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO keeper_specs (contract_address, from_address, evm_chain_id, created_at, updated_at) - VALUES (:contract_address, :from_address, :evm_chain_id, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.KeeperSpec); err != nil { - return errors.Wrap(err, "failed to create KeeperSpec") + specID, err := tx.insertKeeperSpec(ctx, jb.KeeperSpec) + if err != nil { + return fmt.Errorf("failed to create KeeperSpec for jobSpec: %w", err) } jb.KeeperSpecID = &specID case Cron: - var specID int32 - sql := `INSERT INTO cron_specs (cron_schedule, created_at, updated_at) - VALUES (:cron_schedule, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.CronSpec); err != nil { - return errors.Wrap(err, "failed to create CronSpec") + specID, err := tx.insertCronSpec(ctx, jb.CronSpec) + if err != nil { + return fmt.Errorf("failed to create CronSpec for jobSpec: %w", err) } jb.CronSpecID = &specID case VRF: if jb.VRFSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO vrf_specs ( - coordinator_address, public_key, min_incoming_confirmations, - evm_chain_id, from_addresses, poll_period, requested_confs_delay, - request_timeout, chunk_size, batch_coordinator_address, batch_fulfillment_enabled, - batch_fulfillment_gas_multiplier, backoff_initial_delay, backoff_max_delay, gas_lane_price, - vrf_owner_address, custom_reverts_pipeline_enabled, - created_at, updated_at) - VALUES ( - :coordinator_address, :public_key, :min_incoming_confirmations, - :evm_chain_id, :from_addresses, :poll_period, :requested_confs_delay, - :request_timeout, :chunk_size, :batch_coordinator_address, :batch_fulfillment_enabled, - :batch_fulfillment_gas_multiplier, :backoff_initial_delay, :backoff_max_delay, :gas_lane_price, - :vrf_owner_address, :custom_reverts_pipeline_enabled, - NOW(), NOW()) - RETURNING id;` - - err := pg.PrepareQueryRowx(tx, sql, &specID, toVRFSpecRow(jb.VRFSpec)) + specID, err := tx.insertVRFSpec(ctx, jb.VRFSpec) var pqErr *pgconn.PgError ok := errors.As(err, &pqErr) if err != nil && ok && pqErr.Code == "23503" { @@ -346,11 +324,11 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } } if err != nil { - return errors.Wrap(err, "failed to create VRFSpec") + return fmt.Errorf("failed to create VRFSpec for jobSpec: %w", err) } jb.VRFSpecID = &specID case Webhook: - err := o.InsertWebhookSpec(jb.WebhookSpec, pg.WithQueryer(tx)) + err := tx.InsertWebhookSpec(ctx, jb.WebhookSpec) if err != nil { return errors.Wrap(err, "failed to create WebhookSpec") } @@ -362,11 +340,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } sql := `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES (:external_initiator_id, :webhook_spec_id, :spec);` - query, args, err := tx.BindNamed(sql, jb.WebhookSpec.ExternalInitiatorWebhookSpecs) - if err != nil { - return errors.Wrap(err, "failed to bindquery for ExternalInitiatorWebhookSpecs") - } - if _, err = tx.Exec(query, args...); err != nil { + if _, err := tx.ds.NamedExecContext(ctx, sql, jb.WebhookSpec.ExternalInitiatorWebhookSpecs); err != nil { return errors.Wrap(err, "failed to create ExternalInitiatorWebhookSpecs") } } @@ -374,80 +348,58 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { if jb.BlockhashStoreSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO blockhash_store_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, trusted_blockhash_store_address, trusted_blockhash_store_batch_size, wait_blocks, lookback_blocks, heartbeat_period, blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, created_at, updated_at) - VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :trusted_blockhash_store_address, :trusted_blockhash_store_batch_size, :wait_blocks, :lookback_blocks, :heartbeat_period, :blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, toBlockhashStoreSpecRow(jb.BlockhashStoreSpec)); err != nil { - return errors.Wrap(err, "failed to create BlockhashStore spec") + specID, err := tx.insertBlockhashStoreSpec(ctx, jb.BlockhashStoreSpec) + if err != nil { + return fmt.Errorf("failed to create BlockhashStoreSpec for jobSpec: %w", err) } jb.BlockhashStoreSpecID = &specID case BlockHeaderFeeder: if jb.BlockHeaderFeederSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO block_header_feeder_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, wait_blocks, lookback_blocks, blockhash_store_address, batch_blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, get_blockhashes_batch_size, store_blockhashes_batch_size, created_at, updated_at) - VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :wait_blocks, :lookback_blocks, :blockhash_store_address, :batch_blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, :get_blockhashes_batch_size, :store_blockhashes_batch_size, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, toBlockHeaderFeederSpecRow(jb.BlockHeaderFeederSpec)); err != nil { - return errors.Wrap(err, "failed to create BlockHeaderFeeder spec") + specID, err := tx.insertBlockHeaderFeederSpec(ctx, jb.BlockHeaderFeederSpec) + if err != nil { + return fmt.Errorf("failed to create BlockHeaderFeederSpec for jobSpec: %w", err) } jb.BlockHeaderFeederSpecID = &specID case LegacyGasStationServer: if jb.LegacyGasStationServerSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO legacy_gas_station_server_specs (forwarder_address, evm_chain_id, ccip_chain_selector, from_addresses, created_at, updated_at) - VALUES (:forwarder_address, :evm_chain_id, :ccip_chain_selector, :from_addresses, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, toLegacyGasStationServerSpecRow(jb.LegacyGasStationServerSpec)); err != nil { - return errors.Wrap(err, "failed to create LegacyGasStationServer spec") + specID, err := tx.insertLegacyGasStationServerSpec(ctx, jb.LegacyGasStationServerSpec) + if err != nil { + return fmt.Errorf("failed to create LegacyGasStationServerSpec for jobSpec: %w", err) } jb.LegacyGasStationServerSpecID = &specID case LegacyGasStationSidecar: if jb.LegacyGasStationSidecarSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO legacy_gas_station_sidecar_specs (forwarder_address, off_ramp_address, lookback_blocks, poll_period, run_timeout, evm_chain_id, ccip_chain_selector, created_at, updated_at) - VALUES (:forwarder_address, :off_ramp_address, :lookback_blocks, :poll_period, :run_timeout, :evm_chain_id, :ccip_chain_selector, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.LegacyGasStationSidecarSpec); err != nil { - return errors.Wrap(err, "failed to create LegacyGasStationSidecar spec") + specID, err := tx.insertLegacyGasStationSidecarSpec(ctx, jb.LegacyGasStationSidecarSpec) + if err != nil { + return fmt.Errorf("failed to create LegacyGasStationSidecarSpec for jobSpec: %w", err) } jb.LegacyGasStationSidecarSpecID = &specID case Bootstrap: - var specID int32 - sql := `INSERT INTO bootstrap_specs (contract_id, feed_id, relay, relay_config, monitoring_endpoint, - blockchain_timeout, contract_config_tracker_poll_interval, - contract_config_confirmations, created_at, updated_at) - VALUES (:contract_id, :feed_id, :relay, :relay_config, :monitoring_endpoint, - :blockchain_timeout, :contract_config_tracker_poll_interval, - :contract_config_confirmations, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.BootstrapSpec); err != nil { - return errors.Wrap(err, "failed to create BootstrapSpec for jobSpec") + specID, err := tx.insertBootstrapSpec(ctx, jb.BootstrapSpec) + if err != nil { + return fmt.Errorf("failed to create BootstrapSpec for jobSpec: %w", err) } jb.BootstrapSpecID = &specID case Gateway: - var specID int32 - sql := `INSERT INTO gateway_specs (gateway_config, created_at, updated_at) - VALUES (:gateway_config, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.GatewaySpec); err != nil { - return errors.Wrap(err, "failed to create GatewaySpec for jobSpec") + specID, err := tx.insertGatewaySpec(ctx, jb.GatewaySpec) + if err != nil { + return fmt.Errorf("failed to create GatewaySpec for jobSpec: %w", err) } jb.GatewaySpecID = &specID case Stream: // 'stream' type has no associated spec, nothing to do here case Workflow: - var specID int32 sql := `INSERT INTO workflow_specs (workflow, workflow_id, workflow_owner, created_at, updated_at) VALUES (:workflow, :workflow_id, :workflow_owner, NOW(), NOW()) RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.WorkflowSpec); err != nil { + specID, err := tx.prepareQuerySpecID(ctx, sql, jb.WorkflowSpec) + if err != nil { return errors.Wrap(err, "failed to create WorkflowSpec for jobSpec") } jb.WorkflowSpecID = &specID @@ -455,14 +407,14 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { o.lggr.Panicf("Unsupported jb.Type: %v", jb.Type) } - pipelineSpecID, err := o.pipelineORM.CreateSpec(ctx, tx, p, jb.MaxTaskDuration) + pipelineSpecID, err := tx.pipelineORM.CreateSpec(ctx, p, jb.MaxTaskDuration) if err != nil { return errors.Wrap(err, "failed to create pipeline spec") } jb.PipelineSpecID = pipelineSpecID - err = o.InsertJob(jb, pg.WithQueryer(tx)) + err = tx.InsertJob(ctx, jb) jobID = jb.ID return errors.Wrap(err, "failed to insert job") }) @@ -470,7 +422,122 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { return errors.Wrap(err, "CreateJobFailed") } - return o.findJob(jb, "id", jobID, qopts...) + return o.findJob(ctx, jb, "id", jobID) +} + +func (o *orm) prepareQuerySpecID(ctx context.Context, sql string, arg any) (specID int32, err error) { + var stmt *sqlx.NamedStmt + stmt, err = o.ds.PrepareNamedContext(ctx, sql) + if err != nil { + return + } + defer stmt.Close() + err = stmt.QueryRowxContext(ctx, arg).Scan(&specID) + return +} + +func (o *orm) insertDirectRequestSpec(ctx context.Context, spec *DirectRequestSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO direct_request_specs (contract_address, min_incoming_confirmations, requesters, min_contract_payment, evm_chain_id, created_at, updated_at) + VALUES (:contract_address, :min_incoming_confirmations, :requesters, :min_contract_payment, :evm_chain_id, now(), now()) + RETURNING id;`, spec) +} + +func (o *orm) insertFluxMonitorSpec(ctx context.Context, spec *FluxMonitorSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO flux_monitor_specs (contract_address, threshold, absolute_threshold, poll_timer_period, poll_timer_disabled, idle_timer_period, idle_timer_disabled, + drumbeat_schedule, drumbeat_random_delay, drumbeat_enabled, min_payment, evm_chain_id, created_at, updated_at) + VALUES (:contract_address, :threshold, :absolute_threshold, :poll_timer_period, :poll_timer_disabled, :idle_timer_period, :idle_timer_disabled, + :drumbeat_schedule, :drumbeat_random_delay, :drumbeat_enabled, :min_payment, :evm_chain_id, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertOCROracleSpec(ctx context.Context, spec *OCROracleSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO ocr_oracle_specs (contract_address, p2pv2_bootstrappers, is_bootstrap_peer, encrypted_ocr_key_bundle_id, transmitter_address, + observation_timeout, blockchain_timeout, contract_config_tracker_subscribe_interval, contract_config_tracker_poll_interval, contract_config_confirmations, evm_chain_id, + created_at, updated_at, database_timeout, observation_grace_period, contract_transmitter_transmit_timeout) + VALUES (:contract_address, :p2pv2_bootstrappers, :is_bootstrap_peer, :encrypted_ocr_key_bundle_id, :transmitter_address, + :observation_timeout, :blockchain_timeout, :contract_config_tracker_subscribe_interval, :contract_config_tracker_poll_interval, :contract_config_confirmations, :evm_chain_id, + NOW(), NOW(), :database_timeout, :observation_grace_period, :contract_transmitter_transmit_timeout) + RETURNING id;`, spec) +} + +func (o *orm) insertOCR2OracleSpec(ctx context.Context, spec *OCR2OracleSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO ocr2_oracle_specs (contract_id, feed_id, relay, relay_config, plugin_type, plugin_config, onchain_signing_strategy, p2pv2_bootstrappers, ocr_key_bundle_id, transmitter_id, + blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, + created_at, updated_at) + VALUES (:contract_id, :feed_id, :relay, :relay_config, :plugin_type, :plugin_config, :onchain_signing_strategy, :p2pv2_bootstrappers, :ocr_key_bundle_id, :transmitter_id, + :blockchain_timeout, :contract_config_tracker_poll_interval, :contract_config_confirmations, + NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertKeeperSpec(ctx context.Context, spec *KeeperSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO keeper_specs (contract_address, from_address, evm_chain_id, created_at, updated_at) + VALUES (:contract_address, :from_address, :evm_chain_id, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertCronSpec(ctx context.Context, spec *CronSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO cron_specs (cron_schedule, created_at, updated_at) + VALUES (:cron_schedule, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertVRFSpec(ctx context.Context, spec *VRFSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO vrf_specs ( + coordinator_address, public_key, min_incoming_confirmations, + evm_chain_id, from_addresses, poll_period, requested_confs_delay, + request_timeout, chunk_size, batch_coordinator_address, batch_fulfillment_enabled, + batch_fulfillment_gas_multiplier, backoff_initial_delay, backoff_max_delay, gas_lane_price, + vrf_owner_address, custom_reverts_pipeline_enabled, + created_at, updated_at) + VALUES ( + :coordinator_address, :public_key, :min_incoming_confirmations, + :evm_chain_id, :from_addresses, :poll_period, :requested_confs_delay, + :request_timeout, :chunk_size, :batch_coordinator_address, :batch_fulfillment_enabled, + :batch_fulfillment_gas_multiplier, :backoff_initial_delay, :backoff_max_delay, :gas_lane_price, + :vrf_owner_address, :custom_reverts_pipeline_enabled, + NOW(), NOW()) + RETURNING id;`, toVRFSpecRow(spec)) +} + +func (o *orm) insertBlockhashStoreSpec(ctx context.Context, spec *BlockhashStoreSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO blockhash_store_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, trusted_blockhash_store_address, trusted_blockhash_store_batch_size, wait_blocks, lookback_blocks, heartbeat_period, blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, created_at, updated_at) + VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :trusted_blockhash_store_address, :trusted_blockhash_store_batch_size, :wait_blocks, :lookback_blocks, :heartbeat_period, :blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, NOW(), NOW()) + RETURNING id;`, toBlockhashStoreSpecRow(spec)) +} + +func (o *orm) insertBlockHeaderFeederSpec(ctx context.Context, spec *BlockHeaderFeederSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO block_header_feeder_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, wait_blocks, lookback_blocks, blockhash_store_address, batch_blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, get_blockhashes_batch_size, store_blockhashes_batch_size, created_at, updated_at) + VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :wait_blocks, :lookback_blocks, :blockhash_store_address, :batch_blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, :get_blockhashes_batch_size, :store_blockhashes_batch_size, NOW(), NOW()) + RETURNING id;`, toBlockHeaderFeederSpecRow(spec)) +} + +func (o *orm) insertLegacyGasStationServerSpec(ctx context.Context, spec *LegacyGasStationServerSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO legacy_gas_station_server_specs (forwarder_address, evm_chain_id, ccip_chain_selector, from_addresses, created_at, updated_at) + VALUES (:forwarder_address, :evm_chain_id, :ccip_chain_selector, :from_addresses, NOW(), NOW()) + RETURNING id;`, toLegacyGasStationServerSpecRow(spec)) +} + +func (o *orm) insertLegacyGasStationSidecarSpec(ctx context.Context, spec *LegacyGasStationSidecarSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO legacy_gas_station_sidecar_specs (forwarder_address, off_ramp_address, lookback_blocks, poll_period, run_timeout, evm_chain_id, ccip_chain_selector, created_at, updated_at) + VALUES (:forwarder_address, :off_ramp_address, :lookback_blocks, :poll_period, :run_timeout, :evm_chain_id, :ccip_chain_selector, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertBootstrapSpec(ctx context.Context, spec *BootstrapSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO bootstrap_specs (contract_id, feed_id, relay, relay_config, monitoring_endpoint, + blockchain_timeout, contract_config_tracker_poll_interval, + contract_config_confirmations, created_at, updated_at) + VALUES (:contract_id, :feed_id, :relay, :relay_config, :monitoring_endpoint, + :blockchain_timeout, :contract_config_tracker_poll_interval, + :contract_config_confirmations, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertGatewaySpec(ctx context.Context, spec *GatewaySpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO gateway_specs (gateway_config, created_at, updated_at) + VALUES (:gateway_config, NOW(), NOW()) + RETURNING id;`, spec) } // ValidateKeyStoreMatch confirms that the key has a valid match in the keystore @@ -531,17 +598,18 @@ func areSendingKeysDefined(ctx context.Context, jb *Job, keystore keystore.Maste return false, nil } -func (o *orm) InsertWebhookSpec(webhookSpec *WebhookSpec, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) - query := `INSERT INTO webhook_specs (created_at, updated_at) +func (o *orm) InsertWebhookSpec(ctx context.Context, webhookSpec *WebhookSpec) error { + query, args, err := o.ds.BindNamed(`INSERT INTO webhook_specs (created_at, updated_at) VALUES (NOW(), NOW()) - RETURNING *;` - return q.GetNamed(query, webhookSpec, webhookSpec) + RETURNING *;`, webhookSpec) + if err != nil { + return fmt.Errorf("error binding arg: %w", err) + } + return o.ds.GetContext(ctx, webhookSpec, query, args...) } -func (o *orm) InsertJob(job *Job, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) - return q.Transaction(func(querier pg.Queryer) error { +func (o *orm) InsertJob(ctx context.Context, job *Job) error { + return o.transact(ctx, false, func(tx *orm) error { var query string // if job has id, emplace otherwise insert with a new id. @@ -562,26 +630,30 @@ func (o *orm) InsertJob(job *Job, qopts ...pg.QOpt) error { :legacy_gas_station_server_spec_id, :legacy_gas_station_sidecar_spec_id, :workflow_spec_id, :external_job_id, :gas_limit, :forwarding_allowed, NOW()) RETURNING *;` } - err := q.GetNamed(query, job, job) + query, args, err := tx.ds.BindNamed(query, job) + if err != nil { + return fmt.Errorf("error binding arg: %w", err) + } + err = tx.ds.GetContext(ctx, job, query, args...) if err != nil { return err } // Always inserts the `job_pipeline_specs` record as primary, since this is the first one for the job. sqlStmt := `INSERT INTO job_pipeline_specs (job_id, pipeline_spec_id, is_primary) VALUES ($1, $2, true)` - _, err = q.Exec(sqlStmt, job.ID, job.PipelineSpecID) + _, err = tx.ds.ExecContext(ctx, sqlStmt, job.ID, job.PipelineSpecID) return errors.Wrap(err, "failed to insert job_pipeline_specs relationship") }) } // DeleteJob removes a job -func (o *orm) DeleteJob(id int32, qopts ...pg.QOpt) error { +func (o *orm) DeleteJob(ctx context.Context, id int32) error { o.lggr.Debugw("Deleting job", "jobID", id) // Added a 1-minute timeout to this query since this can take a long time as data increases. // This was added specifically due to an issue with a database that had a million of pipeline_runs and pipeline_task_runs // and this query was taking ~40secs. - qopts = append(qopts, pg.WithLongQueryTimeout()) - q := o.q.WithOpts(qopts...) + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() query := ` WITH deleted_jobs AS ( DELETE FROM jobs WHERE id = $1 RETURNING @@ -643,8 +715,7 @@ func (o *orm) DeleteJob(id int32, qopts ...pg.QOpt) error { DELETE FROM job_pipeline_specs WHERE job_id IN (SELECT id FROM deleted_jobs) RETURNING pipeline_spec_id ) DELETE FROM pipeline_specs WHERE id IN (SELECT pipeline_spec_id FROM deleted_job_pipeline_specs)` - res, cancel, err := q.ExecQIter(query, id) - defer cancel() + res, err := o.ds.ExecContext(ctx, query, id) if err != nil { return errors.Wrap(err, "DeleteJob failed to delete job") } @@ -659,14 +730,13 @@ func (o *orm) DeleteJob(id int32, qopts ...pg.QOpt) error { return nil } -func (o *orm) RecordError(jobID int32, description string, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) +func (o *orm) RecordError(ctx context.Context, jobID int32, description string) error { sql := `INSERT INTO job_spec_errors (job_id, description, occurrences, created_at, updated_at) VALUES ($1, $2, 1, $3, $3) ON CONFLICT (job_id, description) DO UPDATE SET occurrences = job_spec_errors.occurrences + 1, updated_at = excluded.updated_at` - err := q.ExecQ(sql, jobID, description, time.Now()) + _, err := o.ds.ExecContext(ctx, sql, jobID, description, time.Now()) // Noop if the job has been deleted. var pqErr *pgconn.PgError ok := errors.As(err, &pqErr) @@ -677,15 +747,13 @@ func (o *orm) RecordError(jobID int32, description string, qopts ...pg.QOpt) err } return err } -func (o *orm) TryRecordError(jobID int32, description string, qopts ...pg.QOpt) { - err := o.RecordError(jobID, description, qopts...) +func (o *orm) TryRecordError(ctx context.Context, jobID int32, description string) { + err := o.RecordError(ctx, jobID, description) o.lggr.ErrorIf(err, fmt.Sprintf("Error creating SpecError %v", description)) } func (o *orm) DismissError(ctx context.Context, ID int64) error { - q := o.q.WithOpts(pg.WithParentCtx(ctx)) - res, cancel, err := q.ExecQIter("DELETE FROM job_spec_errors WHERE id = $1", ID) - defer cancel() + res, err := o.ds.ExecContext(ctx, "DELETE FROM job_spec_errors WHERE id = $1", ID) if err != nil { return errors.Wrap(err, "failed to dismiss error") } @@ -699,35 +767,35 @@ func (o *orm) DismissError(ctx context.Context, ID int64) error { return nil } -func (o *orm) FindSpecError(id int64, qopts ...pg.QOpt) (SpecError, error) { +func (o *orm) FindSpecError(ctx context.Context, id int64) (SpecError, error) { stmt := `SELECT * FROM job_spec_errors WHERE id = $1;` specErr := new(SpecError) - err := o.q.WithOpts(qopts...).Get(specErr, stmt, id) + err := o.ds.GetContext(ctx, specErr, stmt, id) return *specErr, errors.Wrap(err, "FindSpecError failed") } -func (o *orm) FindJobs(offset, limit int) (jobs []Job, count int, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { +func (o *orm) FindJobs(ctx context.Context, offset, limit int) (jobs []Job, count int, err error) { + err = o.transact(ctx, false, func(tx *orm) error { sql := `SELECT count(*) FROM jobs;` - err = tx.QueryRowx(sql).Scan(&count) + err = tx.ds.QueryRowxContext(ctx, sql).Scan(&count) if err != nil { - return err + return fmt.Errorf("failed to query jobs count: %w", err) } sql = `SELECT jobs.*, job_pipeline_specs.pipeline_spec_id as pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) ORDER BY jobs.created_at DESC, jobs.id DESC OFFSET $1 LIMIT $2;` - err = tx.Select(&jobs, sql, offset, limit) + err = tx.ds.SelectContext(ctx, &jobs, sql, offset, limit) if err != nil { - return err + return fmt.Errorf("failed to select jobs: %w", err) } - err = LoadAllJobsTypes(tx, jobs) + err = tx.loadAllJobsTypes(ctx, jobs) if err != nil { - return err + return fmt.Errorf("failed to load job types: %w", err) } return nil @@ -820,32 +888,30 @@ func LoadConfigVarsOCR(evmOcrCfg evmconfig.OCR, ocrCfg OCRConfig, os OCROracleSp } func (o *orm) FindJobTx(ctx context.Context, id int32) (Job, error) { - ctx, cancel := context.WithTimeout(ctx, o.cfg.DefaultQueryTimeout()) - defer cancel() return o.FindJob(ctx, id) } // FindJob returns job by ID, with all relations preloaded func (o *orm) FindJob(ctx context.Context, id int32) (jb Job, err error) { - err = o.findJob(&jb, "id", id, pg.WithParentCtx(ctx)) + err = o.findJob(ctx, &jb, "id", id) return } // FindJobWithoutSpecErrors returns a job by ID, without loading Spec Errors preloaded -func (o *orm) FindJobWithoutSpecErrors(id int32) (jb Job, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { +func (o *orm) FindJobWithoutSpecErrors(ctx context.Context, id int32) (jb Job, err error) { + err = o.transact(ctx, true, func(tx *orm) error { stmt := "SELECT jobs.*, job_pipeline_specs.pipeline_spec_id as pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) WHERE jobs.id = $1 LIMIT 1" - err = tx.Get(&jb, stmt, id) + err = tx.ds.GetContext(ctx, &jb, stmt, id) if err != nil { return errors.Wrap(err, "failed to load job") } - if err = LoadAllJobTypes(tx, &jb); err != nil { + if err = tx.loadAllJobTypes(ctx, &jb); err != nil { return errors.Wrap(err, "failed to load job types") } return nil - }, pg.OptReadOnlyTx()) + }) if err != nil { return jb, errors.Wrap(err, "FindJobWithoutSpecErrors failed") } @@ -854,87 +920,76 @@ func (o *orm) FindJobWithoutSpecErrors(id int32) (jb Job, err error) { } // FindSpecErrorsByJobIDs returns all jobs spec errors by jobs IDs -func (o *orm) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]SpecError, error) { +func (o *orm) FindSpecErrorsByJobIDs(ctx context.Context, ids []int32) ([]SpecError, error) { stmt := `SELECT * FROM job_spec_errors WHERE job_id = ANY($1);` var specErrs []SpecError - err := o.q.WithOpts(qopts...).Select(&specErrs, stmt, ids) + err := o.ds.SelectContext(ctx, &specErrs, stmt, ids) return specErrs, errors.Wrap(err, "FindSpecErrorsByJobIDs failed") } -func (o *orm) FindJobByExternalJobID(externalJobID uuid.UUID, qopts ...pg.QOpt) (jb Job, err error) { - err = o.findJob(&jb, "external_job_id", externalJobID, qopts...) +func (o *orm) FindJobByExternalJobID(ctx context.Context, externalJobID uuid.UUID) (jb Job, err error) { + err = o.findJob(ctx, &jb, "external_job_id", externalJobID) return } // FindJobIDByAddress - finds a job id by contract address. Currently only OCR and FM jobs are supported -func (o *orm) FindJobIDByAddress(address evmtypes.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (jobID int32, err error) { - q := o.q.WithOpts(qopts...) - err = q.Transaction(func(tx pg.Queryer) error { - stmt := ` +func (o *orm) FindJobIDByAddress(ctx context.Context, address evmtypes.EIP55Address, evmChainID *big.Big) (jobID int32, err error) { + stmt := ` SELECT jobs.id FROM jobs LEFT JOIN ocr_oracle_specs ocrspec on ocrspec.contract_address = $1 AND (ocrspec.evm_chain_id = $2 OR ocrspec.evm_chain_id IS NULL) AND ocrspec.id = jobs.ocr_oracle_spec_id LEFT JOIN flux_monitor_specs fmspec on fmspec.contract_address = $1 AND (fmspec.evm_chain_id = $2 OR fmspec.evm_chain_id IS NULL) AND fmspec.id = jobs.flux_monitor_spec_id WHERE ocrspec.id IS NOT NULL OR fmspec.id IS NOT NULL ` - err = tx.Get(&jobID, stmt, address, evmChainID) - + err = o.ds.GetContext(ctx, &jobID, stmt, address, evmChainID) + if err != nil { if !errors.Is(err, sql.ErrNoRows) { - if err != nil { - return errors.Wrap(err, "error searching for job by contract address") - } - return nil + err = errors.Wrap(err, "error searching for job by contract address") } + err = errors.Wrap(err, "FindJobIDByAddress failed") + return + } - return err - }) - - return jobID, errors.Wrap(err, "FindJobIDByAddress failed") + return } -func (o *orm) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qopts ...pg.QOpt) (jobID int32, err error) { - q := o.q.WithOpts(qopts...) - err = q.Transaction(func(tx pg.Queryer) error { - // NOTE: We want to explicitly match on NULL feed_id hence usage of `IS - // NOT DISTINCT FROM` instead of `=` - stmt := ` +func (o *orm) FindOCR2JobIDByAddress(ctx context.Context, contractID string, feedID *common.Hash) (jobID int32, err error) { + // NOTE: We want to explicitly match on NULL feed_id hence usage of `IS + // NOT DISTINCT FROM` instead of `=` + stmt := ` SELECT jobs.id FROM jobs LEFT JOIN ocr2_oracle_specs ocr2spec on ocr2spec.contract_id = $1 AND ocr2spec.feed_id IS NOT DISTINCT FROM $2 AND ocr2spec.id = jobs.ocr2_oracle_spec_id LEFT JOIN bootstrap_specs bs on bs.contract_id = $1 AND bs.feed_id IS NOT DISTINCT FROM $2 AND bs.id = jobs.bootstrap_spec_id WHERE ocr2spec.id IS NOT NULL OR bs.id IS NOT NULL ` - err = tx.Get(&jobID, stmt, contractID, feedID) - + err = o.ds.GetContext(ctx, &jobID, stmt, contractID, feedID) + if err != nil { if !errors.Is(err, sql.ErrNoRows) { - if err != nil { - return errors.Wrapf(err, "error searching for job by contract id=%s and feed id=%s", contractID, feedID) - } - return nil + err = errors.Wrapf(err, "error searching for job by contract id=%s and feed id=%s", contractID, feedID) } + err = errors.Wrap(err, "FindOCR2JobIDByAddress failed") + return + } - return err - }) - - return jobID, errors.Wrap(err, "FindOCR2JobIDByAddress failed") + return } -func (o *orm) findJob(jb *Job, col string, arg interface{}, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) - err := q.Transaction(func(tx pg.Queryer) error { +func (o *orm) findJob(ctx context.Context, jb *Job, col string, arg interface{}) error { + err := o.transact(ctx, false, func(tx *orm) error { sql := fmt.Sprintf(`SELECT jobs.*, job_pipeline_specs.pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) WHERE jobs.%s = $1 AND job_pipeline_specs.is_primary = true LIMIT 1`, col) - err := tx.Get(jb, sql, arg) + err := tx.ds.GetContext(ctx, jb, sql, arg) if err != nil { return errors.Wrap(err, "failed to load job") } - if err = LoadAllJobTypes(tx, jb); err != nil { + if err = tx.loadAllJobTypes(ctx, jb); err != nil { return err } - return loadJobSpecErrors(tx, jb) + return tx.loadJobSpecErrors(ctx, jb) }) if err != nil { return errors.Wrap(err, "findJob failed") @@ -942,62 +997,62 @@ func (o *orm) findJob(jb *Job, col string, arg interface{}, qopts ...pg.QOpt) er return nil } -func (o *orm) FindJobIDsWithBridge(name string) (jids []int32, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - query := `SELECT +func (o *orm) FindJobIDsWithBridge(ctx context.Context, name string) (jids []int32, err error) { + query := `SELECT jobs.id, pipeline_specs.dot_dag_source FROM jobs JOIN job_pipeline_specs ON job_pipeline_specs.job_id = jobs.id JOIN pipeline_specs ON pipeline_specs.id = job_pipeline_specs.pipeline_spec_id WHERE pipeline_specs.dot_dag_source ILIKE '%' || $1 || '%' ORDER BY id` + var rows *sqlx.Rows + rows, err = o.ds.QueryxContext(ctx, query, name) + if err != nil { + return + } + defer rows.Close() + var ids []int32 + var sources []string + for rows.Next() { + var id int32 + var source string + if err = rows.Scan(&id, &source); err != nil { + return + } + ids = append(jids, id) + sources = append(sources, source) + } + if err = rows.Err(); err != nil { + return + } - var rows *sqlx.Rows - rows, err = tx.Queryx(query, name) + for i, id := range ids { + var p *pipeline.Pipeline + p, err = pipeline.Parse(sources[i]) if err != nil { - return err + return nil, errors.Wrapf(err, "could not parse dag for job %d", id) } - defer rows.Close() - var ids []int32 - var sources []string - for rows.Next() { - var id int32 - var source string - if err = rows.Scan(&id, &source); err != nil { - return err - } - ids = append(jids, id) - sources = append(sources, source) - } - - for i, id := range ids { - var p *pipeline.Pipeline - p, err = pipeline.Parse(sources[i]) - if err != nil { - return errors.Wrapf(err, "could not parse dag for job %d", id) - } - for _, task := range p.Tasks { - if task.Type() == pipeline.TaskTypeBridge { - if task.(*pipeline.BridgeTask).Name == name { - jids = append(jids, id) - } + for _, task := range p.Tasks { + if task.Type() == pipeline.TaskTypeBridge { + if task.(*pipeline.BridgeTask).Name == name { + jids = append(jids, id) } } } - return nil - }) - return jids, errors.Wrap(err, "FindJobIDsWithBridge failed") + } + + return } // PipelineRunsByJobsIDs returns pipeline runs for multiple jobs, not preloading data -func (o *orm) PipelineRunsByJobsIDs(ids []int32) (runs []pipeline.Run, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { +func (o *orm) PipelineRunsByJobsIDs(ctx context.Context, ids []int32) (runs []pipeline.Run, err error) { + err = o.transact(ctx, false, func(tx *orm) error { stmt := `SELECT pipeline_runs.* FROM pipeline_runs INNER JOIN job_pipeline_specs ON pipeline_runs.pipeline_spec_id = job_pipeline_specs.pipeline_spec_id WHERE jobs.id = ANY($1) ORDER BY pipeline_runs.created_at DESC, pipeline_runs.id DESC;` - if err = tx.Select(&runs, stmt, ids); err != nil { + if err = tx.ds.SelectContext(ctx, &runs, stmt, ids); err != nil { return errors.Wrap(err, "error loading runs") } - runs, err = o.loadPipelineRunsRelations(runs, tx) + runs, err = tx.loadPipelineRunsRelations(ctx, runs) return err }) @@ -1005,11 +1060,11 @@ func (o *orm) PipelineRunsByJobsIDs(ids []int32) (runs []pipeline.Run, err error return runs, errors.Wrap(err, "PipelineRunsByJobsIDs failed") } -func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) (ids []int64, err error) { +func (o *orm) loadPipelineRunIDs(ctx context.Context, jobID *int32, offset, limit int) (ids []int64, err error) { lggr := logger.Sugared(o.lggr) var res sql.NullInt64 - if err = tx.Get(&res, "SELECT MAX(id) FROM pipeline_runs"); err != nil { + if err = o.ds.GetContext(ctx, &res, "SELECT MAX(id) FROM pipeline_runs"); err != nil { err = errors.Wrap(err, "error while loading runs") return } else if !res.Valid { @@ -1037,7 +1092,7 @@ func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) for n := int64(1000); maxID > 0 && len(ids) < limit; n *= 2 { var batch []int64 minID := maxID - n - if err = tx.Select(&batch, stmt, offset, limit-len(ids), minID, maxID); err != nil { + if err = o.ds.SelectContext(ctx, &batch, stmt, offset, limit-len(ids), minID, maxID); err != nil { err = errors.Wrap(err, "error loading runs") return } @@ -1050,7 +1105,7 @@ func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) var skipped int // If no rows were returned, we need to know whether there were any ids skipped // in this batch due to the offset, and reduce it for the next batch - err = tx.Get(&skipped, + err = o.ds.GetContext(ctx, &skipped, fmt.Sprintf( `SELECT COUNT(p.id) FROM pipeline_runs AS p %s p.id >= $1 AND p.id <= $2`, filter, ), minID, maxID, @@ -1074,63 +1129,60 @@ func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) return } -func (o *orm) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qopts ...pg.QOpt) (result []byte, err error) { - q := o.q.WithOpts(qopts...) - err = q.Transaction(func(tx pg.Queryer) error { - stmt := fmt.Sprintf("SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = $1 AND dot_id = '%s';", taskName) +func (o *orm) FindTaskResultByRunIDAndTaskName(ctx context.Context, runID int64, taskName string) (result []byte, err error) { + stmt := fmt.Sprintf("SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = $1 AND dot_id = '%s';", taskName) - var taskRuns []pipeline.TaskRun - if errB := tx.Select(&taskRuns, stmt, runID); errB != nil { - return errB - } - if len(taskRuns) == 0 { - return fmt.Errorf("can't find task run with id: %v, taskName: %v", runID, taskName) - } - if len(taskRuns) > 1 { - o.lggr.Errorf("found multiple task runs with id: %v, taskName: %v. Using the first one.", runID, taskName) - } - taskRun := taskRuns[0] - if !taskRun.Error.IsZero() { - return errors.New(taskRun.Error.ValueOrZero()) - } - resBytes, errB := taskRun.Output.MarshalJSON() - if errB != nil { - return errB - } - result = resBytes - return nil - }) - return result, errors.Wrap(err, "failed") + var taskRuns []pipeline.TaskRun + if errB := o.ds.SelectContext(ctx, &taskRuns, stmt, runID); errB != nil { + return nil, errB + } + if len(taskRuns) == 0 { + return nil, fmt.Errorf("can't find task run with id: %v, taskName: %v", runID, taskName) + } + if len(taskRuns) > 1 { + o.lggr.Errorf("found multiple task runs with id: %v, taskName: %v. Using the first one.", runID, taskName) + } + taskRun := taskRuns[0] + if !taskRun.Error.IsZero() { + return nil, errors.New(taskRun.Error.ValueOrZero()) + } + resBytes, errB := taskRun.Output.MarshalJSON() + if errB != nil { + return + } + result = resBytes + + return } // FindPipelineRunIDsByJobID fetches the ids of pipeline runs for a job. -func (o *orm) FindPipelineRunIDsByJobID(jobID int32, offset, limit int) (ids []int64, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - ids, err = o.loadPipelineRunIDs(&jobID, offset, limit, tx) +func (o *orm) FindPipelineRunIDsByJobID(ctx context.Context, jobID int32, offset, limit int) (ids []int64, err error) { + err = o.transact(ctx, false, func(tx *orm) error { + ids, err = tx.loadPipelineRunIDs(ctx, &jobID, offset, limit) return err }) return ids, errors.Wrap(err, "FindPipelineRunIDsByJobID failed") } -func (o *orm) loadPipelineRunsByID(ids []int64, tx pg.Queryer) (runs []pipeline.Run, err error) { +func (o *orm) loadPipelineRunsByID(ctx context.Context, ids []int64) (runs []pipeline.Run, err error) { stmt := ` SELECT pipeline_runs.* FROM pipeline_runs WHERE id = ANY($1) ORDER BY created_at DESC, id DESC ` - if err = tx.Select(&runs, stmt, ids); err != nil { + if err = o.ds.SelectContext(ctx, &runs, stmt, ids); err != nil { err = errors.Wrap(err, "error loading runs") return } - return o.loadPipelineRunsRelations(runs, tx) + return o.loadPipelineRunsRelations(ctx, runs) } // FindPipelineRunsByIDs returns pipeline runs with the ids. -func (o *orm) FindPipelineRunsByIDs(ids []int64) (runs []pipeline.Run, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - runs, err = o.loadPipelineRunsByID(ids, tx) +func (o *orm) FindPipelineRunsByIDs(ctx context.Context, ids []int64) (runs []pipeline.Run, err error) { + err = o.transact(ctx, false, func(tx *orm) error { + runs, err = tx.loadPipelineRunsByID(ctx, ids) return err }) @@ -1138,21 +1190,21 @@ func (o *orm) FindPipelineRunsByIDs(ids []int64) (runs []pipeline.Run, err error } // FindPipelineRunByID returns pipeline run with the id. -func (o *orm) FindPipelineRunByID(id int64) (pipeline.Run, error) { +func (o *orm) FindPipelineRunByID(ctx context.Context, id int64) (pipeline.Run, error) { var run pipeline.Run - err := o.q.Transaction(func(tx pg.Queryer) error { + err := o.transact(ctx, false, func(tx *orm) error { stmt := ` SELECT pipeline_runs.* FROM pipeline_runs WHERE id = $1 ` - if err := tx.Get(&run, stmt, id); err != nil { + if err := tx.ds.GetContext(ctx, &run, stmt, id); err != nil { return errors.Wrap(err, "error loading run") } - runs, err := o.loadPipelineRunsRelations([]pipeline.Run{run}, tx) + runs, err := tx.loadPipelineRunsRelations(ctx, []pipeline.Run{run}) run = runs[0] @@ -1163,30 +1215,24 @@ WHERE id = $1 } // CountPipelineRunsByJobID returns the total number of pipeline runs for a job. -func (o *orm) CountPipelineRunsByJobID(jobID int32) (count int32, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - stmt := "SELECT COUNT(*) FROM pipeline_runs JOIN job_pipeline_specs USING (pipeline_spec_id) WHERE job_pipeline_specs.job_id = $1" - if err = tx.Get(&count, stmt, jobID); err != nil { - return errors.Wrap(err, "error counting runs") - } - - return err - }) +func (o *orm) CountPipelineRunsByJobID(ctx context.Context, jobID int32) (count int32, err error) { + stmt := "SELECT COUNT(*) FROM pipeline_runs JOIN job_pipeline_specs USING (pipeline_spec_id) WHERE job_pipeline_specs.job_id = $1" + err = o.ds.GetContext(ctx, &count, stmt, jobID) return count, errors.Wrap(err, "CountPipelineRunsByJobID failed") } -func (o *orm) FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) { +func (o *orm) FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]Job, error) { var jbs []Job - err := o.q.Transaction(func(tx pg.Queryer) error { + err := o.transact(ctx, false, func(tx *orm) error { stmt := `SELECT jobs.*, job_pipeline_specs.pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) WHERE job_pipeline_specs.pipeline_spec_id = ANY($1) ORDER BY jobs.id ASC ` - if err := tx.Select(&jbs, stmt, ids); err != nil { + if err := tx.ds.SelectContext(ctx, &jbs, stmt, ids); err != nil { return errors.Wrap(err, "error fetching jobs by pipeline spec IDs") } - err := LoadAllJobsTypes(tx, jbs) + err := tx.loadAllJobsTypes(ctx, jbs) if err != nil { return err } @@ -1199,20 +1245,20 @@ func (o *orm) FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) { // PipelineRuns returns pipeline runs for a job, with spec and taskruns loaded, latest first // If jobID is nil, returns all pipeline runs -func (o *orm) PipelineRuns(jobID *int32, offset, size int) (runs []pipeline.Run, count int, err error) { +func (o *orm) PipelineRuns(ctx context.Context, jobID *int32, offset, size int) (runs []pipeline.Run, count int, err error) { var filter string if jobID != nil { filter = fmt.Sprintf("JOIN job_pipeline_specs USING(pipeline_spec_id) WHERE job_pipeline_specs.job_id = %d", *jobID) } - err = o.q.Transaction(func(tx pg.Queryer) error { + err = o.transact(ctx, false, func(tx *orm) error { sql := fmt.Sprintf(`SELECT count(*) FROM pipeline_runs %s`, filter) - if err = tx.QueryRowx(sql).Scan(&count); err != nil { + if err = tx.ds.QueryRowxContext(ctx, sql).Scan(&count); err != nil { return errors.Wrap(err, "error counting runs") } var ids []int64 - ids, err = o.loadPipelineRunIDs(jobID, offset, size, tx) - runs, err = o.loadPipelineRunsByID(ids, tx) + ids, err = tx.loadPipelineRunIDs(ctx, jobID, offset, size) + runs, err = tx.loadPipelineRunsByID(ctx, ids) return err }) @@ -1220,7 +1266,7 @@ func (o *orm) PipelineRuns(jobID *int32, offset, size int) (runs []pipeline.Run, return runs, count, errors.Wrap(err, "PipelineRuns failed") } -func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]pipeline.Run, error) { +func (o *orm) loadPipelineRunsRelations(ctx context.Context, runs []pipeline.Run) ([]pipeline.Run, error) { // Postload PipelineSpecs // TODO: We should pull this out into a generic preload function once go has generics specM := make(map[int32]pipeline.Spec) @@ -1235,7 +1281,7 @@ func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]p } stmt := `SELECT pipeline_specs.*, job_pipeline_specs.job_id AS job_id FROM pipeline_specs JOIN job_pipeline_specs ON pipeline_specs.id = job_pipeline_specs.pipeline_spec_id WHERE pipeline_specs.id = ANY($1);` var specs []pipeline.Spec - if err := o.q.Select(&specs, stmt, specIDs); err != nil { + if err := o.ds.SelectContext(ctx, &specs, stmt, specIDs); err != nil { return nil, errors.Wrap(err, "error loading specs") } for _, spec := range specs { @@ -1254,7 +1300,7 @@ func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]p } var taskRuns []pipeline.TaskRun stmt = `SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = ANY($1) ORDER BY pipeline_run_id, created_at, id;` - if err := tx.Select(&taskRuns, stmt, runIDs); err != nil { + if err := o.ds.SelectContext(ctx, &taskRuns, stmt, runIDs); err != nil { return nil, errors.Wrap(err, "error loading pipeline_task_runs") } for _, taskRun := range taskRuns { @@ -1268,9 +1314,9 @@ func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]p // NOTE: N+1 query, be careful of performance // This is not easily fixable without complicating the logic a lot, since we // only use it in the GUI it's probably acceptable -func LoadAllJobsTypes(tx pg.Queryer, jobs []Job) error { +func (o *orm) loadAllJobsTypes(ctx context.Context, jobs []Job) error { for i := range jobs { - err := LoadAllJobTypes(tx, &jobs[i]) + err := o.loadAllJobTypes(ctx, &jobs[i]) if err != nil { return err } @@ -1278,28 +1324,28 @@ func LoadAllJobsTypes(tx pg.Queryer, jobs []Job) error { return nil } -func LoadAllJobTypes(tx pg.Queryer, job *Job) error { +func (o *orm) loadAllJobTypes(ctx context.Context, job *Job) error { return multierr.Combine( - loadJobPipelineSpec(tx, job, &job.PipelineSpecID), - loadJobType(tx, job, "FluxMonitorSpec", "flux_monitor_specs", job.FluxMonitorSpecID), - loadJobType(tx, job, "DirectRequestSpec", "direct_request_specs", job.DirectRequestSpecID), - loadJobType(tx, job, "OCROracleSpec", "ocr_oracle_specs", job.OCROracleSpecID), - loadJobType(tx, job, "OCR2OracleSpec", "ocr2_oracle_specs", job.OCR2OracleSpecID), - loadJobType(tx, job, "KeeperSpec", "keeper_specs", job.KeeperSpecID), - loadJobType(tx, job, "CronSpec", "cron_specs", job.CronSpecID), - loadJobType(tx, job, "WebhookSpec", "webhook_specs", job.WebhookSpecID), - loadVRFJob(tx, job, job.VRFSpecID), - loadBlockhashStoreJob(tx, job, job.BlockhashStoreSpecID), - loadBlockHeaderFeederJob(tx, job, job.BlockHeaderFeederSpecID), - loadLegacyGasStationServerJob(tx, job, job.LegacyGasStationServerSpecID), - loadJobType(tx, job, "LegacyGasStationSidecarSpec", "legacy_gas_station_sidecar_specs", job.LegacyGasStationSidecarSpecID), - loadJobType(tx, job, "BootstrapSpec", "bootstrap_specs", job.BootstrapSpecID), - loadJobType(tx, job, "GatewaySpec", "gateway_specs", job.GatewaySpecID), - loadJobType(tx, job, "WorkflowSpec", "workflow_specs", job.WorkflowSpecID), + o.loadJobPipelineSpec(ctx, job, &job.PipelineSpecID), + o.loadJobType(ctx, job, "FluxMonitorSpec", "flux_monitor_specs", job.FluxMonitorSpecID), + o.loadJobType(ctx, job, "DirectRequestSpec", "direct_request_specs", job.DirectRequestSpecID), + o.loadJobType(ctx, job, "OCROracleSpec", "ocr_oracle_specs", job.OCROracleSpecID), + o.loadJobType(ctx, job, "OCR2OracleSpec", "ocr2_oracle_specs", job.OCR2OracleSpecID), + o.loadJobType(ctx, job, "KeeperSpec", "keeper_specs", job.KeeperSpecID), + o.loadJobType(ctx, job, "CronSpec", "cron_specs", job.CronSpecID), + o.loadJobType(ctx, job, "WebhookSpec", "webhook_specs", job.WebhookSpecID), + o.loadVRFJob(ctx, job, job.VRFSpecID), + o.loadBlockhashStoreJob(ctx, job, job.BlockhashStoreSpecID), + o.loadBlockHeaderFeederJob(ctx, job, job.BlockHeaderFeederSpecID), + o.loadLegacyGasStationServerJob(ctx, job, job.LegacyGasStationServerSpecID), + o.loadJobType(ctx, job, "LegacyGasStationSidecarSpec", "legacy_gas_station_sidecar_specs", job.LegacyGasStationSidecarSpecID), + o.loadJobType(ctx, job, "BootstrapSpec", "bootstrap_specs", job.BootstrapSpecID), + o.loadJobType(ctx, job, "GatewaySpec", "gateway_specs", job.GatewaySpecID), + o.loadJobType(ctx, job, "WorkflowSpec", "workflow_specs", job.WorkflowSpecID), ) } -func loadJobType(tx pg.Queryer, job *Job, field, table string, id *int32) error { +func (o *orm) loadJobType(ctx context.Context, job *Job, field, table string, id *int32) error { if id == nil { return nil } @@ -1312,7 +1358,7 @@ func loadJobType(tx pg.Queryer, job *Job, field, table string, id *int32) error destVal := reflect.New(t) dest := destVal.Interface() - err := tx.Get(dest, fmt.Sprintf(`SELECT * FROM %s WHERE id = $1`, table), *id) + err := o.ds.GetContext(ctx, dest, fmt.Sprintf(`SELECT * FROM %s WHERE id = $1`, table), *id) if err != nil { return errors.Wrapf(err, "failed to load job type %s with id %d", table, *id) @@ -1321,7 +1367,7 @@ func loadJobType(tx pg.Queryer, job *Job, field, table string, id *int32) error return nil } -func loadJobPipelineSpec(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadJobPipelineSpec(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } @@ -1329,7 +1375,8 @@ func loadJobPipelineSpec(tx pg.Queryer, job *Job, id *int32) error { if job.PipelineSpec != nil { pipelineSpecRow = job.PipelineSpec } - err := tx.Get( + err := o.ds.GetContext( + ctx, pipelineSpecRow, `SELECT pipeline_specs.*, job_pipeline_specs.job_id as job_id FROM pipeline_specs @@ -1344,13 +1391,13 @@ func loadJobPipelineSpec(tx pg.Queryer, job *Job, id *int32) error { return nil } -func loadVRFJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadVRFJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row vrfSpecRow - err := tx.Get(&row, `SELECT * FROM vrf_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM vrf_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type VRFSpec with id %d`, *id) } @@ -1383,13 +1430,13 @@ func (r vrfSpecRow) toVRFSpec() *VRFSpec { return r.VRFSpec } -func loadBlockhashStoreJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadBlockhashStoreJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row blockhashStoreSpecRow - err := tx.Get(&row, `SELECT * FROM blockhash_store_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM blockhash_store_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type BlockhashStoreSpec with id %d`, *id) } @@ -1422,13 +1469,13 @@ func (r blockhashStoreSpecRow) toBlockhashStoreSpec() *BlockhashStoreSpec { return r.BlockhashStoreSpec } -func loadBlockHeaderFeederJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadBlockHeaderFeederJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row blockHeaderFeederSpecRow - err := tx.Get(&row, `SELECT * FROM block_header_feeder_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM block_header_feeder_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type BlockHeaderFeederSpec with id %d`, *id) } @@ -1461,13 +1508,13 @@ func (r blockHeaderFeederSpecRow) toBlockHeaderFeederSpec() *BlockHeaderFeederSp return r.BlockHeaderFeederSpec } -func loadLegacyGasStationServerJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadLegacyGasStationServerJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row legacyGasStationServerSpecRow - err := tx.Get(&row, `SELECT * FROM legacy_gas_station_server_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM legacy_gas_station_server_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type LegacyGasStationServerSpec with id %d`, *id) } @@ -1500,6 +1547,6 @@ func (r legacyGasStationServerSpecRow) toLegacyGasStationServerSpec() *LegacyGas return r.LegacyGasStationServerSpec } -func loadJobSpecErrors(tx pg.Queryer, jb *Job) error { - return errors.Wrapf(tx.Select(&jb.JobSpecErrors, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jb.ID), "failed to load job spec errors for job %d", jb.ID) +func (o *orm) loadJobSpecErrors(ctx context.Context, jb *Job) error { + return errors.Wrapf(o.ds.SelectContext(ctx, &jb.JobSpecErrors, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jb.ID), "failed to load job spec errors for job %d", jb.ID) } diff --git a/core/services/job/orm_test.go b/core/services/job/orm_test.go index fb0e846b9d2..11f3e94f2d4 100644 --- a/core/services/job/orm_test.go +++ b/core/services/job/orm_test.go @@ -6,8 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -16,13 +15,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) -func NewTestORM(t *testing.T, db *sqlx.DB, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, cfg pg.QConfig) job.ORM { - o := job.NewORM(db, pipelineORM, bridgeORM, keyStore, logger.TestLogger(t), cfg) +func NewTestORM(t *testing.T, ds sqlutil.DataSource, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master) job.ORM { + o := job.NewORM(ds, pipelineORM, bridgeORM, keyStore, logger.TestLogger(t)) t.Cleanup(func() { assert.NoError(t, o.Close()) }) return o } diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index 26a78a8624e..cdfe39dd17f 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -89,7 +89,7 @@ func TestRunner(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() runner := pipeline.NewRunner(pipelineORM, btORM, config.JobPipeline(), config.WebServer(), legacyChains, nil, nil, logger.TestLogger(t), c, c) - jobORM := NewTestORM(t, db, pipelineORM, btORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, btORM, keyStore) t.Cleanup(func() { assert.NoError(t, jobORM.Close()) }) _, placeHolderAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -121,8 +121,9 @@ func TestRunner(t *testing.T) { // Need a job in order to create a run jb := MakeVoterTurnoutOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, bridgeVT.Name.String(), bridgeER.Name.String()) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), jb)) require.NotNil(t, jb.PipelineSpec) + require.NotZero(t, jb.PipelineSpec.JobID) m, err := bridges.MarshalBridgeMetaData(big.NewInt(10), big.NewInt(100)) require.NoError(t, err) @@ -169,6 +170,7 @@ func TestRunner(t *testing.T) { }) t.Run("must delete job before deleting bridge", func(t *testing.T) { + ctx := testutils.Context(t) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) jb := makeOCRJobSpecFromToml(t, fmt.Sprintf(` type = "offchainreporting" @@ -178,20 +180,21 @@ func TestRunner(t *testing.T) { ds1 [type=bridge name="%s"]; """ `, bridge.Name.String())) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(ctx, jb)) // Should not be able to delete a bridge in use. - jids, err := jobORM.FindJobIDsWithBridge(bridge.Name.String()) + jids, err := jobORM.FindJobIDsWithBridge(ctx, bridge.Name.String()) require.NoError(t, err) require.Equal(t, 1, len(jids)) // But if we delete the job, then we can. - require.NoError(t, jobORM.DeleteJob(jb.ID)) - jids, err = jobORM.FindJobIDsWithBridge(bridge.Name.String()) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) + jids, err = jobORM.FindJobIDsWithBridge(ctx, bridge.Name.String()) require.NoError(t, err) require.Equal(t, 0, len(jids)) }) t.Run("referencing a non-existent bridge should error", func(t *testing.T) { + ctx := testutils.Context(t) // Create a random bridge name _, b := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -223,7 +226,7 @@ func TestRunner(t *testing.T) { `, placeHolderAddress.String())) require.NoError(t, err) // Should error creating it - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.Error(t, err) assert.Contains(t, err.Error(), "not all bridges exist") @@ -258,7 +261,7 @@ answer1 [type=median index=0]; `, placeHolderAddress.String(), b.Name.String()), nil) require.NoError(t, err) // Should error creating it because of the juels per fee coin non-existent bridge - err = jobORM.CreateJob(&jb2) + err = jobORM.CreateJob(ctx, &jb2) require.Error(t, err) assert.Contains(t, err.Error(), "not all bridges exist") @@ -297,11 +300,12 @@ answer1 [type=median index=0]; `, placeHolderAddress, b.Name.String(), b.Name.String(), b.Name.String()), nil) require.NoError(t, err) // Should not error with duplicate bridges - err = jobORM.CreateJob(&jb3) + err = jobORM.CreateJob(ctx, &jb3) require.NoError(t, err) }) t.Run("handles the case where the parsed value is literally null", func(t *testing.T) { + ctx := testutils.Context(t) var httpURL string resp := `{"USD": null}` { @@ -311,7 +315,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, false) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(ctx, jb) require.NoError(t, err) runID, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -357,7 +361,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, false) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(testutils.Context(t), jb) require.NoError(t, err) runID, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -402,7 +406,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, true) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(testutils.Context(t), jb) require.NoError(t, err) runID, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -451,13 +455,13 @@ answer1 [type=median index=0]; err = toml.Unmarshal([]byte(s), &jb) require.NoError(t, err) jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s")) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) lggr := logger.TestLogger(t) _, err = keyStore.P2P().Create(ctx) assert.NoError(t, err) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -487,12 +491,12 @@ answer1 [type=median index=0]; require.NoError(t, err) jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s")) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) assert.Equal(t, jb.MaxTaskDuration, models.Interval(cltest.MustParseDuration(t, "1s"))) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -516,11 +520,11 @@ answer1 [type=median index=0]; require.NoError(t, err) err = toml.Unmarshal([]byte(s), &jb) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -571,12 +575,12 @@ answer1 [type=median index=0]; require.NoError(t, err) jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s")) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) assert.Equal(t, jb.MaxTaskDuration, models.Interval(cltest.MustParseDuration(t, "1s"))) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -617,11 +621,11 @@ answer1 [type=median index=0]; jb := makeOCRJobSpecFromToml(t, spec) // Create an OCR job - err = jobORM.CreateJob(jb) + err = jobORM.CreateJob(ctx, jb) require.NoError(t, err) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -640,6 +644,7 @@ answer1 [type=median index=0]; // Return an error getting the contract code. ethClient.On("CodeAt", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("no such code")) + for _, s := range services { err = s.Start(ctx) require.NoError(t, err) @@ -659,7 +664,7 @@ answer1 [type=median index=0]; } // Ensure we can delete an errored - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) se = []job.SpecError{} err = db.Select(&se, `SELECT * FROM job_spec_errors`) @@ -675,6 +680,7 @@ answer1 [type=median index=0]; }) t.Run("timeouts", func(t *testing.T) { + ctx := testutils.Context(t) // There are 4 timeouts: // - ObservationTimeout = how long the whole OCR time needs to run, or it fails (default 10 seconds) // - config.JobPipelineMaxTaskDuration() = node level maximum time for a pipeline task (default 10 minutes) @@ -689,7 +695,7 @@ answer1 [type=median index=0]; defer serv.Close() jb := makeMinimalHTTPOracleSpec(t, db, config, cltest.NewEIP55Address().String(), transmitterAddress.Hex(), cltest.DefaultOCRKeyBundleID, serv.URL, `timeout="1ns"`) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -700,7 +706,7 @@ answer1 [type=median index=0]; // No task timeout should succeed. jb = makeMinimalHTTPOracleSpec(t, db, config, cltest.NewEIP55Address().String(), transmitterAddress.Hex(), cltest.DefaultOCRKeyBundleID, serv.URL, "") jb.Name = null.NewString("a job 2", true) - err = jobORM.CreateJob(jb) + err = jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err = runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) require.NoError(t, err) @@ -712,7 +718,7 @@ answer1 [type=median index=0]; jb = makeMinimalHTTPOracleSpec(t, db, config, cltest.NewEIP55Address().String(), transmitterAddress.Hex(), cltest.DefaultOCRKeyBundleID, serv.URL, "") jb.MaxTaskDuration = models.Interval(time.Duration(1)) jb.Name = null.NewString("a job 3", true) - err = jobORM.CreateJob(jb) + err = jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err = runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -722,6 +728,7 @@ answer1 [type=median index=0]; }) t.Run("deleting jobs", func(t *testing.T) { + ctx := testutils.Context(t) var httpURL string { resp := `{"USD": 42.42}` @@ -731,7 +738,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, false) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -742,7 +749,7 @@ answer1 [type=median index=0]; assert.Equal(t, "4242", results.Values[0].(decimal.Decimal).String()) // Delete the job - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) // Create another run, it should fail @@ -849,7 +856,7 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) { require.NoError(t, err) bridgeCalled <- struct{}{} })) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) bridgeName = bridge.Name.String() defer bridgeServer.Close() } @@ -879,7 +886,7 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) { """ `, jobUUID, eiName, cltest.MustJSONMarshal(t, eiSpec), bridgeName) - _, err := webhook.ValidatedWebhookSpec(tomlSpec, app.GetExternalInitiatorManager()) + _, err := webhook.ValidatedWebhookSpec(testutils.Context(t), tomlSpec, app.GetExternalInitiatorManager()) require.NoError(t, err) job := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) jobID = job.ID @@ -891,9 +898,9 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) { _ = cltest.CreateJobRunViaExternalInitiatorV2(t, app, jobUUID, *eia, cltest.MustJSONMarshal(t, eiRequest)) - pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(app.GetSqlxDB()) - jobORM := NewTestORM(t, app.GetSqlxDB(), pipelineORM, bridgesORM, app.KeyStore, cfg.Database()) + pipelineORM := pipeline.NewORM(app.GetDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) + bridgesORM := bridges.NewORM(app.GetDB()) + jobORM := NewTestORM(t, app.GetDB(), pipelineORM, bridgesORM, app.KeyStore) // Trigger v2/resume select { @@ -1028,7 +1035,7 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) { require.NoError(t, err) bridgeCalled <- struct{}{} })) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) bridgeName = bridge.Name.String() defer bridgeServer.Close() } @@ -1058,19 +1065,20 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) { """ `, jobUUID, eiName, cltest.MustJSONMarshal(t, eiSpec), bridgeName) - _, err := webhook.ValidatedWebhookSpec(tomlSpec, app.GetExternalInitiatorManager()) + _, err := webhook.ValidatedWebhookSpec(testutils.Context(t), tomlSpec, app.GetExternalInitiatorManager()) require.NoError(t, err) job := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) jobID = job.ID require.Eventually(t, func() bool { return eiNotifiedOfCreate }, 5*time.Second, 10*time.Millisecond, "expected external initiator to be notified of new job") } + t.Run("simulate request from EI -> Core node with erroring callback", func(t *testing.T) { _ = cltest.CreateJobRunViaExternalInitiatorV2(t, app, jobUUID, *eia, cltest.MustJSONMarshal(t, eiRequest)) - pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(app.GetSqlxDB()) - jobORM := NewTestORM(t, app.GetSqlxDB(), pipelineORM, bridgesORM, app.KeyStore, cfg.Database()) + pipelineORM := pipeline.NewORM(app.GetDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) + bridgesORM := bridges.NewORM(app.GetDB()) + jobORM := NewTestORM(t, app.GetDB(), pipelineORM, bridgesORM, app.KeyStore) // Trigger v2/resume select { diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go index 8024424226c..6bb2cdbf76b 100644 --- a/core/services/job/spawner.go +++ b/core/services/job/spawner.go @@ -9,13 +9,11 @@ import ( pkgerrors "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) //go:generate mockery --quiet --name Spawner --output ./mocks/ --case=underscore @@ -29,16 +27,16 @@ type ( // CreateJob creates a new job and starts services. // All services must start without errors for the job to be active. - CreateJob(jb *Job, qopts ...pg.QOpt) (err error) + CreateJob(ctx context.Context, ds sqlutil.DataSource, jb *Job) (err error) // DeleteJob deletes a job and stops any active services. - DeleteJob(jobID int32, qopts ...pg.QOpt) error + DeleteJob(ctx context.Context, ds sqlutil.DataSource, jobID int32) error // ActiveJobs returns a map of jobs with active services (started without error). ActiveJobs() map[int32]Job // StartService starts services for the given job spec. // NOTE: Prefer to use CreateJob, this is only publicly exposed for use in tests // to start a job that was previously manually inserted into DB - StartService(ctx context.Context, spec Job, qopts ...pg.QOpt) error + StartService(ctx context.Context, spec Job) error } Checker interface { @@ -54,7 +52,6 @@ type ( jobTypeDelegates map[Type]Delegate activeJobs map[int32]activeJob activeJobsMu sync.RWMutex - q pg.Q lggr logger.Logger chStop services.StopChan @@ -90,14 +87,13 @@ type ( var _ Spawner = (*spawner)(nil) -func NewSpawner(orm ORM, config Config, checker Checker, jobTypeDelegates map[Type]Delegate, db *sqlx.DB, lggr logger.Logger, lbDependentAwaiters []utils.DependentAwaiter) *spawner { +func NewSpawner(orm ORM, config Config, checker Checker, jobTypeDelegates map[Type]Delegate, lggr logger.Logger, lbDependentAwaiters []utils.DependentAwaiter) *spawner { namedLogger := lggr.Named("JobSpawner") s := &spawner{ orm: orm, config: config, checker: checker, jobTypeDelegates: jobTypeDelegates, - q: pg.NewQ(db, namedLogger, config), lggr: namedLogger, activeJobs: make(map[int32]activeJob), chStop: make(services.StopChan), @@ -134,7 +130,7 @@ func (js *spawner) HealthReport() map[string]error { func (js *spawner) startAllServices(ctx context.Context) { // TODO: rename to find AllJobs - specs, _, err := js.orm.FindJobs(0, math.MaxUint32) + specs, _, err := js.orm.FindJobs(ctx, 0, math.MaxUint32) if err != nil { werr := fmt.Errorf("couldn't fetch unclaimed jobs: %v", err) js.lggr.Critical(werr.Error()) @@ -191,7 +187,7 @@ func (js *spawner) stopService(jobID int32) { delete(js.activeJobs, jobID) } -func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) error { +func (js *spawner) StartService(ctx context.Context, jb Job) error { lggr := js.lggr.With("jobID", jb.ID) js.activeJobsMu.Lock() defer js.activeJobsMu.Unlock() @@ -220,7 +216,7 @@ func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) e lggr.Errorw("Error creating services for job", "err", err) cctx, cancel := js.chStop.NewCtx() defer cancel() - js.orm.TryRecordError(jb.ID, err.Error(), pg.WithParentCtx(cctx)) + js.orm.TryRecordError(cctx, jb.ID, err.Error()) js.activeJobs[jb.ID] = aj return pkgerrors.Wrapf(err, "failed to create services for job: %d", jb.ID) } @@ -249,7 +245,11 @@ func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) e } // Should not get called before Start() -func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { +func (js *spawner) CreateJob(ctx context.Context, ds sqlutil.DataSource, jb *Job) (err error) { + orm := js.orm + if ds != nil { + orm = orm.WithDataSource(ds) + } delegate, exists := js.jobTypeDelegates[jb.Type] if !exists { js.lggr.Errorf("job type '%s' has not been registered with the job.Spawner", jb.Type) @@ -257,15 +257,7 @@ func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { return } - q := js.q.WithOpts(qopts...) - pctx, cancel := js.chStop.Ctx(q.ParentCtx) - defer cancel() - q.ParentCtx = pctx - - ctx, cancel := q.Context() - defer cancel() - - err = js.orm.CreateJob(jb, pg.WithQueryer(q.Queryer), pg.WithParentCtx(ctx)) + err = orm.CreateJob(ctx, jb) if err != nil { js.lggr.Errorw("Error creating job", "type", jb.Type, "err", err) return @@ -273,7 +265,7 @@ func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { js.lggr.Infow("Created job", "type", jb.Type, "jobID", jb.ID) delegate.BeforeJobCreated(*jb) - err = js.StartService(pctx, *jb, pg.WithQueryer(q.Queryer)) + err = js.StartService(ctx, *jb) if err != nil { js.lggr.Errorw("Error starting job services", "type", jb.Type, "jobID", jb.ID, "err", err) } else { @@ -286,7 +278,10 @@ func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { } // Should not get called before Start() -func (js *spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { +func (js *spawner) DeleteJob(ctx context.Context, ds sqlutil.DataSource, jobID int32) error { + if ds == nil { + ds = js.orm.DataSource() + } if jobID == 0 { return pkgerrors.New("will not delete job with 0 ID") } @@ -302,15 +297,8 @@ func (js *spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { aj, exists = js.activeJobs[jobID] }() - q := js.q.WithOpts(qopts...) - pctx, cancel := js.chStop.Ctx(q.ParentCtx) - defer cancel() - q.ParentCtx = pctx - ctx, cancel := q.Context() - defer cancel() - if !exists { // inactive, so look up the spec and delegate - jb, err := js.orm.FindJob(ctx, jobID) + jb, err := js.orm.WithDataSource(ds).FindJob(ctx, jobID) if err != nil { return pkgerrors.Wrapf(err, "job %d not found", jobID) } @@ -330,8 +318,8 @@ func (js *spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { aj.delegate.BeforeJobDeleted(aj.spec) lggr.Debugw("Callback: BeforeDeleteJob done") - err := q.Transaction(func(tx pg.Queryer) error { - err := js.orm.DeleteJob(jobID, pg.WithQueryer(tx)) + err := sqlutil.Transact(ctx, js.orm.WithDataSource, ds, nil, func(tx ORM) error { + err := tx.DeleteJob(ctx, jobID) if err != nil { js.lggr.Errorw("Error deleting job", "jobID", jobID, "err", err) return err diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index ae8ffaa2161..7b4ab138e7c 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -101,10 +101,10 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) t.Run("should respect its dependents", func(t *testing.T) { lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) a := utils.NewDependentAwaiter() a.AddDependents(1) - spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{}, db, lggr, []utils.DependentAwaiter{a}) + spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{}, lggr, []utils.DependentAwaiter{a}) // Starting the spawner should signal to the dependents result := make(chan bool) go func() { @@ -124,7 +124,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { jobB := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) eventuallyA := cltest.NewAwaiter() serviceA1 := mocks.NewServiceCtx(t) @@ -146,9 +146,10 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobA.Type: delegateA, jobB.Type: delegateB, - }, db, lggr, nil) - require.NoError(t, spawner.Start(testutils.Context(t))) - err := spawner.CreateJob(jobA) + }, lggr, nil) + ctx := testutils.Context(t) + require.NoError(t, spawner.Start(ctx)) + err := spawner.CreateJob(ctx, nil, jobA) require.NoError(t, err) jobSpecIDA := jobA.ID delegateA.jobID = jobSpecIDA @@ -156,7 +157,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { eventuallyA.AwaitOrFail(t, 20*time.Second) - err = spawner.CreateJob(jobB) + err = spawner.CreateJob(ctx, nil, jobB) require.NoError(t, err) jobSpecIDB := jobB.ID delegateB.jobID = jobSpecIDB @@ -166,12 +167,12 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA1.On("Close").Return(nil).Once() serviceA2.On("Close").Return(nil).Once() - err = spawner.DeleteJob(jobSpecIDA) + err = spawner.DeleteJob(ctx, nil, jobSpecIDA) require.NoError(t, err) serviceB1.On("Close").Return(nil).Once() serviceB2.On("Close").Return(nil).Once() - err = spawner.DeleteJob(jobSpecIDB) + err = spawner.DeleteJob(ctx, nil, jobSpecIDB) require.NoError(t, err) require.NoError(t, spawner.Close()) @@ -189,19 +190,20 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA2.On("Start", mock.Anything).Return(nil).Once().Run(func(mock.Arguments) { eventually.ItHappened() }) lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config, mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobA.Type: delegateA, - }, db, lggr, nil) + }, lggr, nil) - err := orm.CreateJob(jobA) + ctx := testutils.Context(t) + err := orm.CreateJob(ctx, jobA) require.NoError(t, err) delegateA.jobID = jobA.ID - require.NoError(t, spawner.Start(testutils.Context(t))) + require.NoError(t, spawner.Start(ctx)) eventually.AwaitOrFail(t) @@ -223,20 +225,21 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA2.On("Start", mock.Anything).Return(nil).Once().Run(func(mock.Arguments) { eventuallyStart.ItHappened() }) lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config, mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobA.Type: delegateA, - }, db, lggr, nil) + }, lggr, nil) - err := orm.CreateJob(jobA) + ctx := testutils.Context(t) + err := orm.CreateJob(ctx, jobA) require.NoError(t, err) jobSpecIDA := jobA.ID delegateA.jobID = jobSpecIDA - require.NoError(t, spawner.Start(testutils.Context(t))) + require.NoError(t, spawner.Start(ctx)) defer func() { assert.NoError(t, spawner.Close()) }() eventuallyStart.AwaitOrFail(t) @@ -252,7 +255,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA1.On("Close").Return(nil).Once() serviceA2.On("Close").Return(nil).Once().Run(func(mock.Arguments) { eventuallyClose.ItHappened() }) - err = spawner.DeleteJob(jobSpecIDA) + err = spawner.DeleteJob(ctx, nil, jobSpecIDA) require.NoError(t, err) eventuallyClose.AwaitOrFail(t) @@ -287,9 +290,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { chain := evmtest.MustGetDefaultChain(t, legacyChains) evmRelayer, err := evmrelayer.NewRelayer(lggr, chain, evmrelayer.RelayerOpts{ - DB: db, DS: db, - QConfig: testopts.GeneralConfig.Database(), CSAETHKeystore: keyStore, }) assert.NoError(t, err) @@ -299,23 +300,24 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { r: evmRelayer, } - jobOCR2VRF := makeOCR2VRFJobSpec(t, keyStore, config, address, chain.ID(), 2) + jobOCR2VRF := makeOCR2VRFJobSpec(t, keyStore, address, chain.ID(), 2) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) processConfig := plugins.NewRegistrarConfig(loop.GRPCOpts{}, func(name string) (*plugins.RegisteredLoop, error) { return nil, nil }, func(loopId string) {}) - ocr2DelegateConfig := ocr2.NewDelegateConfig(config.OCR2(), config.Mercury(), config.Threshold(), config.Insecure(), config.JobPipeline(), config.Database(), processConfig) + ocr2DelegateConfig := ocr2.NewDelegateConfig(config.OCR2(), config.Mercury(), config.Threshold(), config.Insecure(), config.JobPipeline(), processConfig) - d := ocr2.NewDelegate(nil, nil, orm, nil, nil, nil, nil, nil, monitoringEndpoint, legacyChains, lggr, ocr2DelegateConfig, + d := ocr2.NewDelegate(nil, orm, nil, nil, nil, nil, nil, monitoringEndpoint, legacyChains, lggr, ocr2DelegateConfig, keyStore.OCR2(), keyStore.DKGSign(), keyStore.DKGEncrypt(), ethKeyStore, testRelayGetter, mailMon, capabilities.NewRegistry(lggr)) delegateOCR2 := &delegate{jobOCR2VRF.Type, []job.ServiceCtx{}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobOCR2VRF.Type: delegateOCR2, - }, db, lggr, nil) + }, lggr, nil) - err = spawner.CreateJob(jobOCR2VRF) + ctx := testutils.Context(t) + err = spawner.CreateJob(ctx, nil, jobOCR2VRF) require.NoError(t, err) jobSpecID := jobOCR2VRF.ID delegateOCR2.jobID = jobOCR2VRF.ID @@ -324,7 +326,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { lggr.Debugf("Got here, with args %v", args) }) - err = spawner.DeleteJob(jobSpecID) + err = spawner.DeleteJob(ctx, nil, jobSpecID) require.NoError(t, err) lp.AssertNumberOfCalls(t, "UnregisterFilter", 3) diff --git a/core/services/job/testdata/compact.toml b/core/services/job/testdata/compact.toml index 9f0f54027d2..5517c69ffa1 100644 --- a/core/services/job/testdata/compact.toml +++ b/core/services/job/testdata/compact.toml @@ -30,5 +30,12 @@ LatestTransmissionDetails = "{\n \"chainSpecificName\": \"latestTransmissionDet [relayConfig.codec.configs.MedianReport] typeABI = "[\n {\n \"Name\": \"Timestamp\",\n \"Type\": \"uint32\"\n },\n {\n \"Name\": \"Observers\",\n \"Type\": \"bytes32\"\n },\n {\n \"Name\": \"Observations\",\n \"Type\": \"int192[]\"\n },\n {\n \"Name\": \"JuelsPerFeeCoin\",\n \"Type\": \"int192\"\n }\n]\n" +[onchainSigningStrategy] +strategyName = 'single-chain' + +[onchainSigningStrategy.config] +evm = '' +publicKey = '0xdeadbeef' + [pluginConfig] juelsPerFeeCoinSource = " // data source 1\n ds1 [type=bridge name=\"%s\"];\n ds1_parse [type=jsonparse path=\"data\"];\n ds1_multiply [type=multiply times=2];\n\n // data source 2\n ds2 [type=http method=GET url=\"%s\"];\n ds2_parse [type=jsonparse path=\"data\"];\n ds2_multiply [type=multiply times=2];\n\n ds1 -> ds1_parse -> ds1_multiply -> answer1;\n ds2 -> ds2_parse -> ds2_multiply -> answer1;\n\n answer1 [type=median index=0];\n" diff --git a/core/services/job/testdata/pretty.toml b/core/services/job/testdata/pretty.toml index 88bacff7db2..1bed3efac0d 100644 --- a/core/services/job/testdata/pretty.toml +++ b/core/services/job/testdata/pretty.toml @@ -130,6 +130,13 @@ typeABI = ''' ] ''' +[onchainSigningStrategy] +strategyName = 'single-chain' + +[onchainSigningStrategy.config] +evm = '' +publicKey = '0xdeadbeef' + [pluginConfig] juelsPerFeeCoinSource = """ // data source 1 diff --git a/core/services/keeper/delegate.go b/core/services/keeper/delegate.go index 184a61e1e1a..71a0c5c43a9 100644 --- a/core/services/keeper/delegate.go +++ b/core/services/keeper/delegate.go @@ -5,8 +5,7 @@ import ( "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/config" @@ -25,7 +24,7 @@ type DelegateConfig interface { type Delegate struct { cfg DelegateConfig logger logger.Logger - db *sqlx.DB + ds sqlutil.DataSource jrm job.ORM pr pipeline.Runner legacyChains legacyevm.LegacyChainContainer @@ -35,7 +34,7 @@ type Delegate struct { // NewDelegate is the constructor of Delegate func NewDelegate( cfg DelegateConfig, - db *sqlx.DB, + ds sqlutil.DataSource, jrm job.ORM, pr pipeline.Runner, logger logger.Logger, @@ -45,7 +44,7 @@ func NewDelegate( return &Delegate{ cfg: cfg, logger: logger, - db: db, + ds: ds, jrm: jrm, pr: pr, legacyChains: legacyChains, @@ -58,10 +57,10 @@ func (d *Delegate) JobType() job.Type { return job.Keeper } -func (d *Delegate) BeforeJobCreated(spec job.Job) {} -func (d *Delegate) AfterJobCreated(spec job.Job) {} -func (d *Delegate) BeforeJobDeleted(spec job.Job) {} -func (d *Delegate) OnDeleteJob(context.Context, job.Job) error { return nil } +func (d *Delegate) BeforeJobCreated(spec job.Job) {} +func (d *Delegate) AfterJobCreated(spec job.Job) {} +func (d *Delegate) BeforeJobDeleted(spec job.Job) {} +func (d *Delegate) OnDeleteJob(ctx context.Context, spec job.Job) error { return nil } // ServicesForSpec satisfies the job.Delegate interface. func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services []job.ServiceCtx, err error) { @@ -73,7 +72,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services return nil, err } registryAddress := spec.KeeperSpec.ContractAddress - orm := NewORM(d.db, d.logger) + orm := NewORM(d.ds, d.logger) svcLogger := d.logger.With( "jobID", spec.ID, "registryAddress", registryAddress.Hex(), diff --git a/core/services/keeper/helpers_test.go b/core/services/keeper/helpers_test.go index 3fb9d7760a4..a10c3a48aff 100644 --- a/core/services/keeper/helpers_test.go +++ b/core/services/keeper/helpers_test.go @@ -12,6 +12,10 @@ func (rs *RegistrySynchronizer) ExportedFullSync(ctx context.Context) { rs.fullSync(ctx) } +func (rs *RegistrySynchronizer) ExportedProcessLogs(ctx context.Context) { + rs.processLogs(ctx) +} + func (rw *RegistryWrapper) GetUpkeepIdFromRawRegistrationLog(rawLog types.Log) (*big.Int, error) { switch rw.Version { case RegistryVersion_1_0, RegistryVersion_1_1: diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go index 08699d3d835..9e4cf5f9041 100644 --- a/core/services/keeper/integration_test.go +++ b/core/services/keeper/integration_test.go @@ -284,7 +284,7 @@ func TestKeeperEthIntegration(t *testing.T) { require.NoError(t, err) backend.Commit() - cltest.WaitForCount(t, app.GetSqlxDB(), "upkeep_registrations", 0) + cltest.WaitForCount(t, app.GetDB(), "upkeep_registrations", 0) // add new upkeep (same target contract) registrationTx, err = registryWrapper.RegisterUpkeep(steve, upkeepAddr, 2_500_000, carrol.From, []byte{}) @@ -308,8 +308,8 @@ func TestKeeperEthIntegration(t *testing.T) { require.NoError(t, err) var registry keeper.Registry - require.NoError(t, app.GetSqlxDB().Get(®istry, `SELECT * FROM keeper_registries`)) - cltest.AssertRecordEventually(t, app.GetSqlxDB(), ®istry, fmt.Sprintf("SELECT * FROM keeper_registries WHERE id = %d", registry.ID), func() bool { + require.NoError(t, app.GetDB().GetContext(ctx, ®istry, `SELECT * FROM keeper_registries`)) + cltest.AssertRecordEventually(t, app.GetDB(), ®istry, fmt.Sprintf("SELECT * FROM keeper_registries WHERE id = %d", registry.ID), func() bool { return registry.KeeperIndex == -1 }) runs, err := app.PipelineORM().GetAllRuns(ctx) @@ -435,7 +435,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { SchemaVersion: 1, ForwardingAllowed: true, } - err = app.JobORM().CreateJob(&jb) + err = app.JobORM().CreateJob(testutils.Context(t), &jb) require.NoError(t, err) registry := keeper.Registry{ diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go index 2726c9a754d..73a3cb88166 100644 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ b/core/services/keeper/registry_synchronizer_helper_test.go @@ -46,7 +46,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, LogBroadcaster: lbMock, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), cfg.Database(), legacyChains, db, keyStore, nil, nil) + jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) contractAddress := j.KeeperSpec.ContractAddress.Address() switch version { diff --git a/core/services/keeper/registry_synchronizer_process_logs.go b/core/services/keeper/registry_synchronizer_process_logs.go index a1bdcd8db0b..5aaddb6f1e4 100644 --- a/core/services/keeper/registry_synchronizer_process_logs.go +++ b/core/services/keeper/registry_synchronizer_process_logs.go @@ -82,6 +82,9 @@ func (rs *RegistrySynchronizer) processLogs(ctx context.Context) { } if err != nil { + if ctx.Err() != nil { + return + } rs.logger.Error(err) } diff --git a/core/services/keeper/registry_synchronizer_sync.go b/core/services/keeper/registry_synchronizer_sync.go index 6c0e12d844b..6615d376e2b 100644 --- a/core/services/keeper/registry_synchronizer_sync.go +++ b/core/services/keeper/registry_synchronizer_sync.go @@ -30,7 +30,7 @@ func (rs *RegistrySynchronizer) fullSync(ctx context.Context) { } func (rs *RegistrySynchronizer) syncRegistry(ctx context.Context) (Registry, error) { - registry, err := rs.newRegistryFromChain() + registry, err := rs.newRegistryFromChain(ctx) if err != nil { return Registry{}, errors.Wrap(err, "failed to get new registry from chain") } @@ -138,13 +138,13 @@ func (rs *RegistrySynchronizer) syncUpkeep(ctx context.Context, getter upkeepGet } // newRegistryFromChain returns a Registry struct with fields synched from those on chain -func (rs *RegistrySynchronizer) newRegistryFromChain() (Registry, error) { +func (rs *RegistrySynchronizer) newRegistryFromChain(ctx context.Context) (Registry, error) { fromAddress := rs.effectiveKeeperAddress contractAddress := rs.job.KeeperSpec.ContractAddress registryConfig, err := rs.registryWrapper.GetConfig(nil) if err != nil { - rs.jrm.TryRecordError(rs.job.ID, err.Error()) + rs.jrm.TryRecordError(ctx, rs.job.ID, err.Error()) return Registry{}, errors.Wrap(err, "failed to get contract config") } diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index ec23331f904..cd02fc27d11 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -83,7 +83,7 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain txm := txmmocks.NewMockEvmTxManager(t) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{TxManager: txm, DB: db, Client: ethClient, KeyStore: keyStore.Eth(), GeneralConfig: cfg, GasEstimator: estimator}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), cfg.Database(), legacyChains, db, keyStore, nil, nil) + jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) ch := evmtest.MustGetDefaultChain(t, legacyChains) orm := keeper.NewORM(db, logger.TestLogger(t)) registry, jb := cltest.MustInsertKeeperRegistry(t, db, orm, keyStore.Eth(), 0, 1, 20) diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index 07a41599f7d..4a9c8a952ff 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -13,8 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -29,9 +27,7 @@ import ( func Test_EthKeyStore(t *testing.T) { t.Parallel() - db := sqlutil.WrapDataSource(pgtest.NewSqlxDB(t), logger.Test(t), sqlutil.TimeoutHook(func() time.Duration { - return 5 * time.Minute - }), sqlutil.MonitorHook(func() bool { return true })) + db := pgtest.NewSqlxDB(t) keyStore := keystore.ExposedNewMaster(t, db) err := keyStore.Unlock(testutils.Context(t), cltest.Password) diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index 2bab0ab12a2..6cdad6290fc 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -13,13 +13,13 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) @@ -43,11 +43,11 @@ type delegate struct { } type DelegateConfig struct { - Logger logger.Logger - Queryer pg.Queryer - Runner streams.Runner - Registry Registry - JobName null.String + Logger logger.Logger + DataSource sqlutil.DataSource + Runner streams.Runner + Registry Registry + JobName null.String // LLO ChannelDefinitionCache llotypes.ChannelDefinitionCache @@ -67,8 +67,8 @@ type DelegateConfig struct { } func NewDelegate(cfg DelegateConfig) (job.ServiceCtx, error) { - if cfg.Queryer == nil { - return nil, errors.New("Queryer must not be nil") + if cfg.DataSource == nil { + return nil, errors.New("DataSource must not be nil") } if cfg.Runner == nil { return nil, errors.New("Runner must not be nil") diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index 5746f97cd38..f7c7a9940b5 100644 --- a/core/services/ocr/contract_tracker.go +++ b/core/services/ocr/contract_tracker.go @@ -90,8 +90,9 @@ type ( } OCRContractTrackerDB interface { - SaveLatestRoundRequested(ctx context.Context, tx sqlutil.DataSource, rr offchainaggregator.OffchainAggregatorRoundRequested) error + SaveLatestRoundRequested(ctx context.Context, rr offchainaggregator.OffchainAggregatorRoundRequested) error LoadLatestRoundRequested(ctx context.Context) (rr offchainaggregator.OffchainAggregatorRoundRequested, err error) + WithDataSource(sqlutil.DataSource) OCRContractTrackerDB } ) @@ -293,7 +294,7 @@ func (t *OCRContractTracker) HandleLog(ctx context.Context, lb log.Broadcast) { } if IsLaterThan(raw, t.latestRoundRequested.Raw) { err = sqlutil.TransactDataSource(ctx, t.ds, nil, func(tx sqlutil.DataSource) error { - if err = t.ocrDB.SaveLatestRoundRequested(ctx, tx, *rr); err != nil { + if err = t.ocrDB.WithDataSource(tx).SaveLatestRoundRequested(ctx, *rr); err != nil { return err } return t.logBroadcaster.MarkConsumed(ctx, tx, lb) diff --git a/core/services/ocr/contract_tracker_test.go b/core/services/ocr/contract_tracker_test.go index 6f8b05c6436..d8fd8a01a11 100644 --- a/core/services/ocr/contract_tracker_test.go +++ b/core/services/ocr/contract_tracker_test.go @@ -224,9 +224,10 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) uni.lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { return rr.Epoch == 1 && rr.Round == 1 })).Return(nil) + uni.db.On("WithDataSource", mock.Anything).Return(uni.db) uni.tracker.HandleLog(testutils.Context(t), logBroadcast) @@ -244,7 +245,7 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) uni.lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { return rr.Epoch == 1 && rr.Round == 9 })).Return(nil) @@ -273,7 +274,7 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) uni.lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { return rr.Epoch == 2 && rr.Round == 1 })).Return(nil) @@ -295,7 +296,8 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin logBroadcast.On("String").Return("").Maybe() uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("something exploded")) + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything).Return(errors.New("something exploded")) + uni.db.On("WithDataSource", mock.Anything).Return(uni.db) uni.tracker.HandleLog(testutils.Context(t), logBroadcast) diff --git a/core/services/ocr/database.go b/core/services/ocr/database.go index 95993de9d5c..b5f890565f1 100644 --- a/core/services/ocr/database.go +++ b/core/services/ocr/database.go @@ -38,6 +38,9 @@ func NewDB(ds sqlutil.DataSource, oracleSpecID int32, lggr logger.Logger) *db { lggr: logger.Sugared(lggr), } } +func (d *db) WithDataSource(ds sqlutil.DataSource) OCRContractTrackerDB { + return NewDB(ds, d.oracleSpecID, d.lggr) +} func (d *db) ReadState(ctx context.Context, cd ocrtypes.ConfigDigest) (ps *ocrtypes.PersistentState, err error) { stmt := ` @@ -293,12 +296,12 @@ WHERE ocr_oracle_spec_id = $1 AND time < $2 return } -func (d *db) SaveLatestRoundRequested(ctx context.Context, tx sqlutil.DataSource, rr offchainaggregator.OffchainAggregatorRoundRequested) error { +func (d *db) SaveLatestRoundRequested(ctx context.Context, rr offchainaggregator.OffchainAggregatorRoundRequested) error { rawLog, err := json.Marshal(rr.Raw) if err != nil { return errors.Wrap(err, "could not marshal log as JSON") } - _, err = tx.ExecContext(ctx, ` + _, err = d.ds.ExecContext(ctx, ` INSERT INTO ocr_latest_round_requested (ocr_oracle_spec_id, requester, config_digest, epoch, round, raw) VALUES ($1,$2,$3,$4,$5,$6) ON CONFLICT (ocr_oracle_spec_id) DO UPDATE SET requester = EXCLUDED.requester, diff --git a/core/services/ocr/database_test.go b/core/services/ocr/database_test.go index a2559ca2a87..12f9309450c 100644 --- a/core/services/ocr/database_test.go +++ b/core/services/ocr/database_test.go @@ -407,7 +407,7 @@ func Test_DB_LatestRoundRequested(t *testing.T) { t.Run("saves latest round requested", func(t *testing.T) { ctx := testutils.Context(t) - err := odb.SaveLatestRoundRequested(ctx, sqlDB, rr) + err := odb.SaveLatestRoundRequested(ctx, rr) require.NoError(t, err) rawLog.Index = 42 @@ -421,7 +421,7 @@ func Test_DB_LatestRoundRequested(t *testing.T) { Raw: rawLog, } - err = odb.SaveLatestRoundRequested(ctx, sqlDB, rr) + err = odb.SaveLatestRoundRequested(ctx, rr) require.NoError(t, err) }) diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go index 88561bd1c3a..690e9ad7c71 100644 --- a/core/services/ocr/delegate.go +++ b/core/services/ocr/delegate.go @@ -10,13 +10,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" ocr "github.com/smartcontractkit/libocr/offchainreporting" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" @@ -35,7 +34,7 @@ import ( ) type Delegate struct { - db *sqlx.DB + ds sqlutil.DataSource jobORM job.ORM keyStore keystore.Master pipelineRunner pipeline.Runner @@ -52,7 +51,7 @@ var _ job.Delegate = (*Delegate)(nil) const ConfigOverriderPollInterval = 30 * time.Second func NewDelegate( - db *sqlx.DB, + ds sqlutil.DataSource, jobORM job.ORM, keyStore keystore.Master, pipelineRunner pipeline.Runner, @@ -64,7 +63,7 @@ func NewDelegate( mailMon *mailbox.Monitor, ) *Delegate { return &Delegate{ - db: db, + ds: ds, jobORM: jobORM, keyStore: keyStore, pipelineRunner: pipelineRunner, @@ -120,7 +119,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] return nil, errors.Wrap(err, "could not instantiate NewOffchainAggregatorCaller") } - ocrDB := NewDB(d.db, concreteSpec.ID, lggr) + ocrDB := NewDB(d.ds, concreteSpec.ID, lggr) tracker := NewOCRContractTracker( contract, @@ -130,7 +129,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] chain.LogBroadcaster(), jb.ID, lggr, - d.db, + d.ds, ocrDB, chain.Config().EVM(), chain.HeadBroadcaster(), @@ -157,7 +156,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] } ocrLogger := commonlogger.NewOCRWrapper(lggr, d.cfg.OCR().TraceLogging(), func(msg string) { - d.jobORM.TryRecordError(jb.ID, msg) + d.jobORM.TryRecordError(ctx, jb.ID, msg) }) lc := toLocalConfig(chain.Config().EVM(), chain.Config().EVM().OCR(), d.cfg.Insecure(), *concreteSpec, d.cfg.OCR()) diff --git a/core/services/ocr/helpers_internal_test.go b/core/services/ocr/helpers_internal_test.go index c6a3d1ac401..a8c656f636c 100644 --- a/core/services/ocr/helpers_internal_test.go +++ b/core/services/ocr/helpers_internal_test.go @@ -3,8 +3,7 @@ package ocr import ( "testing" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -12,6 +11,6 @@ func (c *ConfigOverriderImpl) ExportedUpdateFlagsStatus() error { return c.updateFlagsStatus() } -func NewTestDB(t *testing.T, sqldb *sqlx.DB, oracleSpecID int32) *db { - return NewDB(sqldb, oracleSpecID, logger.TestLogger(t)) +func NewTestDB(t *testing.T, ds sqlutil.DataSource, oracleSpecID int32) *db { + return NewDB(ds, oracleSpecID, logger.TestLogger(t)) } diff --git a/core/services/ocr/mocks/ocr_contract_tracker_db.go b/core/services/ocr/mocks/ocr_contract_tracker_db.go index ed47d87cd1e..d3dcce2641b 100644 --- a/core/services/ocr/mocks/ocr_contract_tracker_db.go +++ b/core/services/ocr/mocks/ocr_contract_tracker_db.go @@ -5,6 +5,7 @@ package mocks import ( context "context" + ocr "github.com/smartcontractkit/chainlink/v2/core/services/ocr" mock "github.com/stretchr/testify/mock" offchainaggregator "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" @@ -45,17 +46,17 @@ func (_m *OCRContractTrackerDB) LoadLatestRoundRequested(ctx context.Context) (o return r0, r1 } -// SaveLatestRoundRequested provides a mock function with given fields: ctx, tx, rr -func (_m *OCRContractTrackerDB) SaveLatestRoundRequested(ctx context.Context, tx sqlutil.DataSource, rr offchainaggregator.OffchainAggregatorRoundRequested) error { - ret := _m.Called(ctx, tx, rr) +// SaveLatestRoundRequested provides a mock function with given fields: ctx, rr +func (_m *OCRContractTrackerDB) SaveLatestRoundRequested(ctx context.Context, rr offchainaggregator.OffchainAggregatorRoundRequested) error { + ret := _m.Called(ctx, rr) if len(ret) == 0 { panic("no return value specified for SaveLatestRoundRequested") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, sqlutil.DataSource, offchainaggregator.OffchainAggregatorRoundRequested) error); ok { - r0 = rf(ctx, tx, rr) + if rf, ok := ret.Get(0).(func(context.Context, offchainaggregator.OffchainAggregatorRoundRequested) error); ok { + r0 = rf(ctx, rr) } else { r0 = ret.Error(0) } @@ -63,6 +64,26 @@ func (_m *OCRContractTrackerDB) SaveLatestRoundRequested(ctx context.Context, tx return r0 } +// WithDataSource provides a mock function with given fields: _a0 +func (_m *OCRContractTrackerDB) WithDataSource(_a0 sqlutil.DataSource) ocr.OCRContractTrackerDB { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for WithDataSource") + } + + var r0 ocr.OCRContractTrackerDB + if rf, ok := ret.Get(0).(func(sqlutil.DataSource) ocr.OCRContractTrackerDB); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ocr.OCRContractTrackerDB) + } + } + + return r0 +} + // NewOCRContractTrackerDB creates a new instance of OCRContractTrackerDB. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewOCRContractTrackerDB(t interface { diff --git a/core/services/ocr2/database.go b/core/services/ocr2/database.go index 1d449047578..83ee3240a46 100644 --- a/core/services/ocr2/database.go +++ b/core/services/ocr2/database.go @@ -6,18 +6,17 @@ import ( "encoding/binary" "time" - "github.com/jmoiron/sqlx" "github.com/lib/pq" "github.com/pkg/errors" ocrcommon "github.com/smartcontractkit/libocr/commontypes" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type db struct { - q pg.Q + ds sqlutil.DataSource oracleSpecID int32 pluginID int32 lggr logger.SugaredLogger @@ -28,11 +27,9 @@ var ( ) // NewDB returns a new DB scoped to this oracleSpecID -func NewDB(sqlxDB *sqlx.DB, oracleSpecID int32, pluginID int32, lggr logger.Logger, cfg pg.QConfig) *db { - namedLogger := lggr.Named("OCR2.DB") - +func NewDB(ds sqlutil.DataSource, oracleSpecID int32, pluginID int32, lggr logger.Logger) *db { return &db{ - q: pg.NewQ(sqlxDB, namedLogger, cfg), + ds: ds, oracleSpecID: oracleSpecID, pluginID: pluginID, lggr: logger.Sugared(lggr), @@ -51,7 +48,7 @@ func (d *db) ReadState(ctx context.Context, cd ocrtypes.ConfigDigest) (ps *ocrty var tmp []int64 var highestSentEpochTmp int64 - err = d.q.QueryRowxContext(ctx, stmt, d.oracleSpecID, cd).Scan(&ps.Epoch, &highestSentEpochTmp, pq.Array(&tmp)) + err = d.ds.QueryRowxContext(ctx, stmt, d.oracleSpecID, cd).Scan(&ps.Epoch, &highestSentEpochTmp, pq.Array(&tmp)) if errors.Is(err, sql.ErrNoRows) { return nil, nil } @@ -98,7 +95,9 @@ func (d *db) WriteState(ctx context.Context, cd ocrtypes.ConfigDigest, state ocr NOW() )` - _, err := d.q.WithOpts(pg.WithLongQueryTimeout()).ExecContext( + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() + _, err := d.ds.ExecContext( ctx, stmt, d.oracleSpecID, cd, state.Epoch, state.HighestSentEpoch, pq.Array(&highestReceivedEpoch), ) @@ -126,7 +125,7 @@ func (d *db) ReadConfig(ctx context.Context) (c *ocrtypes.ContractConfig, err er signers := [][]byte{} transmitters := [][]byte{} - err = d.q.QueryRowx(stmt, d.oracleSpecID, d.pluginID).Scan( + err = d.ds.QueryRowxContext(ctx, stmt, d.oracleSpecID, d.pluginID).Scan( &digest, &c.ConfigCount, (*pq.ByteaArray)(&signers), @@ -191,7 +190,7 @@ func (d *db) WriteConfig(ctx context.Context, c ocrtypes.ContractConfig) error { offchain_config = EXCLUDED.offchain_config, updated_at = NOW() ` - _, err := d.q.ExecContext(ctx, stmt, + _, err := d.ds.ExecContext(ctx, stmt, d.oracleSpecID, d.pluginID, c.ConfigDigest, @@ -252,7 +251,7 @@ func (d *db) StorePendingTransmission(ctx context.Context, t ocrtypes.ReportTime updated_at = NOW() ` - _, err := d.q.ExecContext(ctx, stmt, + _, err := d.ds.ExecContext(ctx, stmt, d.oracleSpecID, digest, t.Epoch, @@ -279,7 +278,7 @@ func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtyp FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 ` - rows, err := d.q.QueryxContext(ctx, stmt, d.oracleSpecID, cd) //nolint sqlclosecheck false positive + rows, err := d.ds.QueryxContext(ctx, stmt, d.oracleSpecID, cd) //nolint sqlclosecheck false positive if err != nil { return nil, errors.Wrap(err, "PendingTransmissionsWithConfigDigest failed to query rows") } @@ -325,7 +324,9 @@ func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtyp } func (d *db) DeletePendingTransmission(ctx context.Context, t ocrtypes.ReportTimestamp) (err error) { - _, err = d.q.WithOpts(pg.WithLongQueryTimeout()).ExecContext(ctx, ` + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() + _, err = d.ds.ExecContext(ctx, ` DELETE FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 AND epoch = $3 AND round = $4 `, d.oracleSpecID, t.ConfigDigest, t.Epoch, t.Round) @@ -336,7 +337,9 @@ WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 AND epoch = $3 AND round } func (d *db) DeletePendingTransmissionsOlderThan(ctx context.Context, t time.Time) (err error) { - _, err = d.q.WithOpts(pg.WithLongQueryTimeout()).ExecContext(ctx, ` + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() + _, err = d.ds.ExecContext(ctx, ` DELETE FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND time < $2 `, d.oracleSpecID, t) @@ -347,7 +350,7 @@ WHERE ocr2_oracle_spec_id = $1 AND time < $2 } func (d *db) ReadProtocolState(ctx context.Context, configDigest ocrtypes.ConfigDigest, key string) (value []byte, err error) { - err = d.q.GetContext(ctx, &value, ` + err = d.ds.GetContext(ctx, &value, ` SELECT value FROM ocr_protocol_states WHERE config_digest = $1 AND key = $2; `, configDigest, key) @@ -363,9 +366,9 @@ WHERE config_digest = $1 AND key = $2; func (d *db) WriteProtocolState(ctx context.Context, configDigest ocrtypes.ConfigDigest, key string, value []byte) (err error) { if value == nil { - _, err = d.q.ExecContext(ctx, `DELETE FROM ocr_protocol_states WHERE config_digest = $1 AND key = $2;`, configDigest, key) + _, err = d.ds.ExecContext(ctx, `DELETE FROM ocr_protocol_states WHERE config_digest = $1 AND key = $2;`, configDigest, key) } else { - _, err = d.q.ExecContext(ctx, ` + _, err = d.ds.ExecContext(ctx, ` INSERT INTO ocr_protocol_states (config_digest, key, value) VALUES ($1, $2, $3) ON CONFLICT (config_digest, key) DO UPDATE SET value = $3;`, configDigest, key, value) } diff --git a/core/services/ocr2/database_test.go b/core/services/ocr2/database_test.go index 6e4f8f5dd66..3d3eec22a6d 100644 --- a/core/services/ocr2/database_test.go +++ b/core/services/ocr2/database_test.go @@ -16,7 +16,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -41,9 +40,9 @@ func MustInsertOCROracleSpec(t *testing.T, db *sqlx.DB, transmitterAddress types require.NoError(t, db.Get(&spec, `INSERT INTO ocr2_oracle_specs ( relay, relay_config, contract_id, p2pv2_bootstrappers, ocr_key_bundle_id, monitoring_endpoint, transmitter_id, -blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, plugin_type, plugin_config, created_at, updated_at) VALUES ( +blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, plugin_type, plugin_config, onchain_signing_strategy, created_at, updated_at) VALUES ( 'ethereum', '{}', $1, '{}', $2, $3, $4, -0, 0, 0, 'median', $5, NOW(), NOW() +0, 0, 0, 'median', $5, '{}', NOW(), NOW() ) RETURNING *`, cltest.NewEIP55Address().String(), cltest.DefaultOCR2KeyBundleID, "chain.link:1234", transmitterAddress.String(), jsonConfig)) return spec } @@ -60,14 +59,13 @@ func Test_DB_ReadWriteState(t *testing.T) { sqlDB := setupDB(t) configDigest := testhelpers.MakeConfigDigest(t) - cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) lggr := logger.TestLogger(t) t.Run("reads and writes state", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) state := ocrtypes.PersistentState{ Epoch: 1, HighestSentEpoch: 2, @@ -84,7 +82,7 @@ func Test_DB_ReadWriteState(t *testing.T) { }) t.Run("updates state", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) newState := ocrtypes.PersistentState{ Epoch: 2, HighestSentEpoch: 3, @@ -101,7 +99,7 @@ func Test_DB_ReadWriteState(t *testing.T) { }) t.Run("does not return result for wrong spec", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) state := ocrtypes.PersistentState{ Epoch: 3, HighestSentEpoch: 4, @@ -112,7 +110,7 @@ func Test_DB_ReadWriteState(t *testing.T) { require.NoError(t, err) // odb with different spec - db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr, cfg.Database()) + db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr) readState, err := db.ReadState(testutils.Context(t), configDigest) require.NoError(t, err) @@ -121,7 +119,7 @@ func Test_DB_ReadWriteState(t *testing.T) { }) t.Run("does not return result for wrong config digest", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) state := ocrtypes.PersistentState{ Epoch: 4, HighestSentEpoch: 5, @@ -151,14 +149,13 @@ func Test_DB_ReadWriteConfig(t *testing.T) { OffchainConfigVersion: 111, OffchainConfig: []byte{0x03, 0x04}, } - cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) lggr := logger.TestLogger(t) t.Run("reads and writes config", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) @@ -170,7 +167,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("updates config", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) newConfig := ocrtypes.ContractConfig{ ConfigDigest: testhelpers.MakeConfigDigest(t), @@ -188,12 +185,12 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("does not return result for wrong spec", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) - db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr, cfg.Database()) + db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr) readConfig, err := db.ReadConfig(testutils.Context(t)) require.NoError(t, err) @@ -203,8 +200,8 @@ func Test_DB_ReadWriteConfig(t *testing.T) { t.Run("reads and writes config for multiple plugins", func(t *testing.T) { otherPluginID := int32(2) - db1 := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) - db2 := ocr2.NewDB(sqlDB, spec.ID, otherPluginID, lggr, cfg.Database()) + db1 := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) + db2 := ocr2.NewDB(sqlDB, spec.ID, otherPluginID, lggr) otherConfig := ocrtypes.ContractConfig{ ConfigDigest: testhelpers.MakeConfigDigest(t), @@ -238,15 +235,14 @@ func assertPendingTransmissionEqual(t *testing.T, pt1, pt2 ocrtypes.PendingTrans func Test_DB_PendingTransmissions(t *testing.T) { sqlDB := setupDB(t) - cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) lggr := logger.TestLogger(t) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) spec2 := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) - db2 := ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) + db2 := ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr) configDigest := testhelpers.MakeConfigDigest(t) k := ocrtypes.ReportTimestamp{ @@ -436,7 +432,7 @@ func Test_DB_PendingTransmissions(t *testing.T) { require.Len(t, m, 1) // Didn't affect other oracleSpecIDs - db = ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr, cfg.Database()) + db = ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr) m, err = db.PendingTransmissionsWithConfigDigest(testutils.Context(t), configDigest) require.NoError(t, err) require.Len(t, m, 1) @@ -446,10 +442,8 @@ func Test_DB_PendingTransmissions(t *testing.T) { func Test_DB_ReadWriteProtocolState(t *testing.T) { sqlDB := setupDB(t) - cfg := configtest.NewTestGeneralConfig(t) - lggr := logger.TestLogger(t) - db := ocr2.NewDB(sqlDB, 0, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, 0, defaultPluginID, lggr) cd1 := testhelpers.MakeConfigDigest(t) cd2 := testhelpers.MakeConfigDigest(t) ctx := testutils.Context(t) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 7a2ef532fd2..4e1eb0cc623 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -9,7 +9,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" @@ -28,6 +27,7 @@ import ( ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink-vrf/altbn_128" @@ -70,7 +70,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/promwrapper" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -111,7 +110,6 @@ type RelayGetter interface { Get(id types.RelayID) (loop.Relayer, error) } type Delegate struct { - db *sqlx.DB // legacy: prefer to use ds instead ds sqlutil.DataSource jobORM job.ORM bridgeORM bridges.ORM @@ -138,7 +136,6 @@ type DelegateConfig interface { plugins.RegistrarConfig OCR2() ocr2Config JobPipeline() jobPipelineConfig - Database() pg.QConfig Insecure() insecureConfig Mercury() coreconfig.Mercury Threshold() coreconfig.Threshold @@ -149,7 +146,6 @@ type delegateConfig struct { plugins.RegistrarConfig ocr2 ocr2Config jobPipeline jobPipelineConfig - database pg.QConfig insecure insecureConfig mercury mercuryConfig threshold thresholdConfig @@ -159,10 +155,6 @@ func (d *delegateConfig) JobPipeline() jobPipelineConfig { return d.jobPipeline } -func (d *delegateConfig) Database() pg.QConfig { - return d.database -} - func (d *delegateConfig) Insecure() insecureConfig { return d.insecure } @@ -206,18 +198,18 @@ type mercuryConfig interface { Credentials(credName string) *types.MercuryCredentials Cache() coreconfig.MercuryCache TLS() coreconfig.MercuryTLS + Transmitter() coreconfig.MercuryTransmitter } type thresholdConfig interface { ThresholdKeyShare() string } -func NewDelegateConfig(ocr2Cfg ocr2Config, m coreconfig.Mercury, t coreconfig.Threshold, i insecureConfig, jp jobPipelineConfig, qconf pg.QConfig, pluginProcessCfg plugins.RegistrarConfig) DelegateConfig { +func NewDelegateConfig(ocr2Cfg ocr2Config, m coreconfig.Mercury, t coreconfig.Threshold, i insecureConfig, jp jobPipelineConfig, pluginProcessCfg plugins.RegistrarConfig) DelegateConfig { return &delegateConfig{ ocr2: ocr2Cfg, RegistrarConfig: pluginProcessCfg, jobPipeline: jp, - database: qconf, insecure: i, mercury: m, threshold: t, @@ -227,7 +219,6 @@ func NewDelegateConfig(ocr2Cfg ocr2Config, m coreconfig.Mercury, t coreconfig.Th var _ job.Delegate = (*Delegate)(nil) func NewDelegate( - db *sqlx.DB, ds sqlutil.DataSource, jobORM job.ORM, bridgeORM bridges.ORM, @@ -248,7 +239,6 @@ func NewDelegate( capabilitiesRegistry core.CapabilitiesRegistry, ) *Delegate { return &Delegate{ - db: db, ds: ds, jobORM: jobORM, bridgeORM: bridgeORM, @@ -382,7 +372,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi } lggr := logger.Sugared(d.lggr.Named(jb.ExternalJobID.String()).With(lggrCtx.Args()...)) - kvStore := job.NewKVStore(jb.ID, d.db, d.cfg.Database(), lggr) + kvStore := job.NewKVStore(jb.ID, d.ds, lggr) rid, err := spec.RelayID() if err != nil { @@ -404,7 +394,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi spec.RelayConfig["effectiveTransmitterID"] = effectiveTransmitterID spec.RelayConfig.ApplyDefaultsOCR2(d.cfg.OCR2()) - ocrDB := NewDB(d.db, spec.ID, 0, lggr, d.cfg.Database()) + ocrDB := NewDB(d.ds, spec.ID, 0, lggr) if d.peerWrapper == nil { return nil, errors.New("cannot setup OCR2 job service, libp2p peer was missing") } else if !d.peerWrapper.IsStarted() { @@ -412,7 +402,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi } ocrLogger := commonlogger.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(msg string) { - lggr.ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) lc, err := validate.ToLocalConfig(d.cfg.OCR2(), d.cfg.Insecure(), *spec) @@ -475,8 +465,8 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi thresholdPluginId s4PluginId ) - thresholdPluginDB := NewDB(d.db, spec.ID, thresholdPluginId, lggr, d.cfg.Database()) - s4PluginDB := NewDB(d.db, spec.ID, s4PluginId, lggr, d.cfg.Database()) + thresholdPluginDB := NewDB(d.ds, spec.ID, thresholdPluginId, lggr) + s4PluginDB := NewDB(d.ds, spec.ID, s4PluginId, lggr) return d.newServicesOCR2Functions(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, thresholdPluginDB, s4PluginDB, lc, ocrLogger) case types.GenericPlugin: @@ -551,6 +541,13 @@ func (d *Delegate) newServicesGenericPlugin( if err != nil { return nil, err } + // NOTE: we don't need to validate the strategy, since that happens as part of creating the job. + // See: validate/validate.go's `validateSpec`. + onchainSigningStrategy := validate.OCR2OnchainSigningStrategy{} + err = json.Unmarshal(spec.OnchainSigningStrategy.Bytes(), &onchainSigningStrategy) + if err != nil { + return nil, err + } plugEnv := env.NewPlugin(pCfg.PluginName) @@ -772,6 +769,11 @@ func (d *Delegate) newServicesMercury( return nil, errors.New("could not coerce PluginProvider to MercuryProvider") } + // HACK: We need fast config switchovers because they create downtime. This + // won't be properly resolved until we implement blue-green deploys: + // https://smartcontract-it.atlassian.net/browse/MERC-3386 + lc.ContractConfigTrackerPollInterval = 1 * time.Second // Mercury requires a fast poll interval, this is the fastest that libocr supports. See: https://github.com/smartcontractkit/offchain-reporting/pull/520 + oracleArgsNoPlugin := libocr2.MercuryOracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -904,10 +906,10 @@ func (d *Delegate) newServicesLLO( kr := llo.NewOnchainKeyring(lggr, kbm) cfg := llo.DelegateConfig{ - Logger: lggr, - Queryer: pg.NewQ(d.db, lggr, d.cfg.Database()), - Runner: d.pipelineRunner, - Registry: d.streamRegistry, + Logger: lggr, + DataSource: d.ds, + Runner: d.pipelineRunner, + Registry: d.streamRegistry, JobName: jb.Name, @@ -1010,7 +1012,7 @@ func (d *Delegate) newServicesDKG( if err2 != nil { return nil, fmt.Errorf("DKG services: failed to get chain %s: %w", rid.ChainID, err2) } - ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(d.db, chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) + ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) dkgProvider, err2 := ocr2vrfRelayer.NewDKGProvider( types.RelayArgs{ ExternalJobID: jb.ExternalJobID, @@ -1041,20 +1043,7 @@ func (d *Delegate) newServicesDKG( OnchainKeyring: kb, MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": jb.Name.ValueOrZero()}, prometheus.DefaultRegisterer), } - return dkg.NewDKGServices( - jb, - dkgProvider, - lggr, - ocrLogger, - d.dkgSignKs, - d.dkgEncryptKs, - chain.Client(), - oracleArgsNoPlugin, - d.db, - d.cfg.Database(), - chain.ID(), - spec.Relay, - ) + return dkg.NewDKGServices(jb, dkgProvider, lggr, ocrLogger, d.dkgSignKs, d.dkgEncryptKs, chain.Client(), oracleArgsNoPlugin, d.ds, chain.ID(), spec.Relay) } func (d *Delegate) newServicesOCR2VRF( @@ -1094,7 +1083,7 @@ func (d *Delegate) newServicesOCR2VRF( return nil, errors.Wrap(err2, "validate ocr2vrf plugin config") } - ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(d.db, chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) + ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) transmitterID := spec.TransmitterID.String vrfProvider, err2 := ocr2vrfRelayer.NewOCR2VRFProvider( @@ -1179,11 +1168,11 @@ func (d *Delegate) newServicesOCR2VRF( ) vrfLogger := commonlogger.NewOCRWrapper(l.With( "vrfContractID", spec.ContractID), d.cfg.OCR2().TraceLogging(), func(msg string) { - lggr.ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) dkgLogger := commonlogger.NewOCRWrapper(l.With( "dkgContractID", cfg.DKGContractAddress), d.cfg.OCR2().TraceLogging(), func(msg string) { - lggr.ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) dkgReportingPluginFactoryDecorator := func(wrapped ocrtypes.ReportingPluginFactory) ocrtypes.ReportingPluginFactory { return promwrapper.NewPromFactory(wrapped, "DKG", string(types.NetworkEVM), chain.ID()) @@ -1222,7 +1211,7 @@ func (d *Delegate) newServicesOCR2VRF( KeyID: keyID, DKGReportingPluginFactoryDecorator: dkgReportingPluginFactoryDecorator, VRFReportingPluginFactoryDecorator: vrfReportingPluginFactoryDecorator, - DKGSharePersistence: persistence.NewShareDB(d.db, lggr.Named("DKGShareDB"), d.cfg.Database(), chain.ID(), spec.Relay), + DKGSharePersistence: persistence.NewShareDB(d.ds, lggr.Named("DKGShareDB"), chain.ID(), spec.Relay), }) if err2 != nil { return nil, errors.Wrap(err2, "new ocr2vrf") @@ -1449,7 +1438,7 @@ func (d *Delegate) newServicesOCR2Keepers20( return nil, fmt.Errorf("keepers2.0 services: failed to get chain (%s): %w", rid.ChainID, err2) } - keeperProvider, rgstry, encoder, logProvider, err2 := ocr2keeper.EVMDependencies20(ctx, jb, d.db, lggr, chain, d.ethKs, d.cfg.Database()) + keeperProvider, rgstry, encoder, logProvider, err2 := ocr2keeper.EVMDependencies20(ctx, jb, d.ds, lggr, chain, d.ethKs) if err2 != nil { return nil, errors.Wrap(err2, "could not build dependencies for ocr2 keepers") } @@ -1699,11 +1688,11 @@ func (d *Delegate) newServicesOCR2Functions( // errorLog implements [loop.ErrorLog] type errorLog struct { jobID int32 - recordError func(jobID int32, description string, qopts ...pg.QOpt) error + recordError func(ctx context.Context, jobID int32, description string) error } func (l *errorLog) SaveError(ctx context.Context, msg string) error { - return l.recordError(l.jobID, msg) + return l.recordError(ctx, l.jobID, msg) } type logWriter struct { diff --git a/core/services/ocr2/plugins/dkg/persistence/db.go b/core/services/ocr2/plugins/dkg/persistence/db.go index b8ecfbaceb4..07dad494ed7 100644 --- a/core/services/ocr2/plugins/dkg/persistence/db.go +++ b/core/services/ocr2/plugins/dkg/persistence/db.go @@ -16,11 +16,11 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" "github.com/smartcontractkit/chainlink-vrf/types/hash" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) var ( @@ -52,16 +52,16 @@ var ( ) type shareDB struct { - q pg.Q + ds sqlutil.DataSource lggr logger.Logger chainID *big.Int chainType string } // NewShareDB creates a new DKG share database. -func NewShareDB(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, chainID *big.Int, chainType string) ocr2vrftypes.DKGSharePersistence { +func NewShareDB(ds sqlutil.DataSource, lggr logger.Logger, chainID *big.Int, chainType string) ocr2vrftypes.DKGSharePersistence { return &shareDB{ - q: pg.NewQ(db, lggr, cfg), + ds: ds, lggr: lggr, chainID: chainID, chainType: chainType, @@ -134,13 +134,13 @@ func (s *shareDB) WriteShareRecords( // Always upsert because we want the number of rows in the table to match // the number of members of the committee. - query := ` + _, err := s.ds.NamedExecContext(ctx, ` INSERT INTO dkg_shares (config_digest, key_id, dealer, marshaled_share_record, record_hash) VALUES (:config_digest, :key_id, :dealer, :marshaled_share_record, :record_hash) ON CONFLICT ON CONSTRAINT dkg_shares_pkey DO UPDATE SET marshaled_share_record = EXCLUDED.marshaled_share_record, record_hash = EXCLUDED.record_hash -` - return s.q.ExecQNamed(query, named[:]) +`, named[:]) + return err } // ReadShareRecords retrieves any share records in the database that correspond @@ -152,6 +152,7 @@ func (s *shareDB) ReadShareRecords( retrievedShares []ocr2vrftypes.PersistentShareSetRecord, err error, ) { + ctx := context.Background() //TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 lggr := s.lggr.With( "configDigest", hexutil.Encode(cfgDgst[:]), "keyID", hexutil.Encode(keyID[:])) @@ -177,9 +178,9 @@ WHERE config_digest = :config_digest if err != nil { return nil, errors.Wrap(err, "sqlx Named") } - query = s.q.Rebind(query) + query = s.ds.Rebind(query) var dkgShares []dkgShare - err = s.q.Select(&dkgShares, query, args...) + err = s.ds.SelectContext(ctx, &dkgShares, query, args...) if errors.Is(err, sql.ErrNoRows) { return nil, nil } diff --git a/core/services/ocr2/plugins/dkg/persistence/db_test.go b/core/services/ocr2/plugins/dkg/persistence/db_test.go index a3949ea70dc..dbc400a3468 100644 --- a/core/services/ocr2/plugins/dkg/persistence/db_test.go +++ b/core/services/ocr2/plugins/dkg/persistence/db_test.go @@ -22,7 +22,7 @@ import ( func setup(t testing.TB) (ocr2vrftypes.DKGSharePersistence, *sqlx.DB) { db := pgtest.NewSqlxDB(t) lggr := logger.TestLogger(t) - return NewShareDB(db, lggr, pgtest.NewQConfig(true), big.NewInt(1337), types.NetworkEVM), db + return NewShareDB(db, lggr, big.NewInt(1337), types.NetworkEVM), db } func TestShareDB_WriteShareRecords(t *testing.T) { diff --git a/core/services/ocr2/plugins/dkg/plugin.go b/core/services/ocr2/plugins/dkg/plugin.go index 65216ac1115..0364c5d9ab0 100644 --- a/core/services/ocr2/plugins/dkg/plugin.go +++ b/core/services/ocr2/plugins/dkg/plugin.go @@ -6,12 +6,12 @@ import ( "fmt" "math/big" - "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/smartcontractkit/libocr/commontypes" libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-vrf/altbn_128" "github.com/smartcontractkit/chainlink-vrf/dkg" @@ -21,7 +21,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/persistence" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) @@ -34,8 +33,7 @@ func NewDKGServices( dkgEncryptKs keystore.DKGEncrypt, ethClient evmclient.Client, oracleArgsNoPlugin libocr2.OCR2OracleArgs, - db *sqlx.DB, - qConfig pg.QConfig, + ds sqlutil.DataSource, chainID *big.Int, network string, ) ([]job.ServiceCtx, error) { @@ -68,7 +66,7 @@ func NewDKGServices( if err != nil { return nil, errors.Wrap(err, "decode key ID") } - shareDB := persistence.NewShareDB(db, lggr.Named("DKGShareDB"), qConfig, chainID, network) + shareDB := persistence.NewShareDB(ds, lggr.Named("DKGShareDB"), chainID, network) oracleArgsNoPlugin.ReportingPluginFactory = dkg.NewReportingPluginFactory( encryptKey.KyberScalar(), signKey.KyberScalar(), diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go index 0d6bc02e198..a33ab2a1bd2 100644 --- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go +++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go @@ -47,7 +47,7 @@ func TestAdapter_Integration(t *testing.T) { keystore := keystore.NewInMemory(db, utils.FastScryptParams, logger) pipelineORM := pipeline.NewORM(db, logger, cfg.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := job.NewORM(db, pipelineORM, bridgesORM, keystore, logger, cfg.Database()) + jobORM := job.NewORM(db, pipelineORM, bridgesORM, keystore, logger) pr := pipeline.NewRunner( pipelineORM, bridgesORM, @@ -75,7 +75,7 @@ func TestAdapter_Integration(t *testing.T) { jb.Name = null.StringFrom("Job 1") jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) pra := generic.NewPipelineRunnerAdapter(logger, jb, pr) results, err := pra.ExecuteRun(testutils.Context(t), spec, core.Vars{Vars: map[string]interface{}{"val": 1}}, core.Options{}) diff --git a/core/services/ocr2/plugins/median/config/config.go b/core/services/ocr2/plugins/median/config/config.go index 9cfda641552..310662ef6c0 100644 --- a/core/services/ocr2/plugins/median/config/config.go +++ b/core/services/ocr2/plugins/median/config/config.go @@ -20,6 +20,7 @@ type PluginConfig struct { } type JuelsPerFeeCoinCache struct { + Disable bool `json:"disable"` UpdateInterval models.Interval `json:"updateInterval"` StalenessAlertThreshold models.Interval `json:"stalenessAlertThreshold"` } diff --git a/core/services/ocr2/plugins/median/services.go b/core/services/ocr2/plugins/median/services.go index 779ea4f346c..e2b8da13407 100644 --- a/core/services/ocr2/plugins/median/services.go +++ b/core/services/ocr2/plugins/median/services.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-feeds/median" - "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -127,9 +126,9 @@ func NewMedianServices(ctx context.Context, CreatedAt: time.Now(), }, lggr) - if pluginConfig.JuelsPerFeeCoinCache != nil { + if pluginConfig.JuelsPerFeeCoinCache == nil || (pluginConfig.JuelsPerFeeCoinCache != nil && !pluginConfig.JuelsPerFeeCoinCache.Disable) { lggr.Infof("juelsPerFeeCoin data source caching is enabled") - juelsPerFeeCoinSourceCache, err2 := ocrcommon.NewInMemoryDataSourceCache(juelsPerFeeCoinSource, kvStore, *pluginConfig.JuelsPerFeeCoinCache) + juelsPerFeeCoinSourceCache, err2 := ocrcommon.NewInMemoryDataSourceCache(juelsPerFeeCoinSource, kvStore, pluginConfig.JuelsPerFeeCoinCache) if err2 != nil { return nil, err2 } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go index b07b08d3354..e2c1a1531e2 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go @@ -42,7 +42,7 @@ var ( readJobQueueSize = 64 readLogsTimeout = 10 * time.Second - readMaxBatchSize = 32 + readMaxBatchSize = 56 // reorgBuffer is the number of blocks to add as a buffer to the block range when reading logs. reorgBuffer = int64(32) readerThreads = 4 diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go index 35bd62eeed8..339d8a89dfb 100644 --- a/core/services/ocr2/plugins/ocr2keeper/util.go +++ b/core/services/ocr2/plugins/ocr2keeper/util.go @@ -4,12 +4,11 @@ import ( "context" "fmt" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/jmoiron/sqlx" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocr2keepers20 "github.com/smartcontractkit/chainlink-automation/pkg/v2" @@ -25,7 +24,6 @@ import ( evmregistry20 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20" evmregistry21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" evmregistry21transmit "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type Encoder20 interface { @@ -44,9 +42,9 @@ var ( ErrNoChainFromSpec = fmt.Errorf("could not create chain from spec") ) -func EVMProvider(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, ethKeystore keystore.Eth, dbCfg pg.QConfig) (evmrelay.OCR2KeeperProvider, error) { +func EVMProvider(ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, ethKeystore keystore.Eth) (evmrelay.OCR2KeeperProvider, error) { oSpec := spec.OCR2OracleSpec - ocr2keeperRelayer := evmrelay.NewOCR2KeeperRelayer(db, chain, lggr.Named("OCR2KeeperRelayer"), ethKeystore, dbCfg) + ocr2keeperRelayer := evmrelay.NewOCR2KeeperRelayer(ds, chain, lggr.Named("OCR2KeeperRelayer"), ethKeystore) keeperProvider, err := ocr2keeperRelayer.NewOCR2KeeperProvider( types.RelayArgs{ @@ -70,11 +68,10 @@ func EVMProvider(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, spec jo func EVMDependencies20( ctx context.Context, spec job.Job, - db *sqlx.DB, + ds sqlutil.DataSource, lggr logger.Logger, chain legacyevm.Chain, ethKeystore keystore.Eth, - dbCfg pg.QConfig, ) (evmrelay.OCR2KeeperProvider, *evmregistry20.EvmRegistry, Encoder20, *evmregistry20.LogProvider, error) { var err error @@ -82,7 +79,7 @@ func EVMDependencies20( var registry *evmregistry20.EvmRegistry // the provider will be returned as a dependency - if keeperProvider, err = EVMProvider(db, chain, lggr, spec, ethKeystore, dbCfg); err != nil { + if keeperProvider, err = EVMProvider(ds, chain, lggr, spec, ethKeystore); err != nil { return nil, nil, nil, nil, err } diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go index 4adede8d121..e7688556124 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go @@ -28,13 +28,13 @@ import ( "github.com/smartcontractkit/chainlink-vrf/dkg" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" - vrf_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" - dkg_wrapper "github.com/smartcontractkit/chainlink-vrf/gethwrappers/dkg" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + dkg_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" + vrf_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" ocr2vrfconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/config" diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go index 1e21227a11e..beee01eaf7a 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go @@ -29,12 +29,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" - dkg_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" lp_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + dkg_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go index 278fe573439..1aeb0ea85c4 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go @@ -16,7 +16,7 @@ import ( types "github.com/ethereum/go-ethereum/core/types" - vrf_beacon "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" + vrf_beacon "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" ) // VRFBeaconInterface is an autogenerated mock type for the VRFBeaconInterface type diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go index 7dddf15a322..268dff05237 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go @@ -16,7 +16,7 @@ import ( types "github.com/ethereum/go-ethereum/core/types" - vrf_coordinator "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" + vrf_coordinator "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) // VRFCoordinatorInterface is an autogenerated mock type for the VRFCoordinatorInterface type diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go index dd7fd5e1ec2..77384a085ab 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go @@ -8,10 +8,10 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/logger" ) diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go index c65dcb15a8f..7135fa862e3 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks" ) diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go index f8fae150c06..370f0c5fd00 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go @@ -3,8 +3,8 @@ package coordinator import ( "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) type topics struct { diff --git a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go index ac2695dc632..2e1e15fd058 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -32,11 +32,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" - dkg_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/load_test_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon_consumer" - vrf_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -44,6 +39,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" + dkg_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer" + vrf_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go index 59f7053de56..9a85d7993a4 100644 --- a/core/services/ocr2/validate/validate.go +++ b/core/services/ocr2/validate/validate.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/services/job" dkgconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/config" @@ -172,6 +173,40 @@ func (o *OCR2GenericPluginConfig) UnmarshalJSON(data []byte) error { return nil } +type onchainSigningStrategyInner struct { + StrategyName string `json:"strategyName"` + Config job.JSONConfig `json:"config"` +} + +type OCR2OnchainSigningStrategy struct { + onchainSigningStrategyInner +} + +func (o *OCR2OnchainSigningStrategy) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, &o.onchainSigningStrategyInner) + if err != nil { + return err + } + + return nil +} + +func (o *OCR2OnchainSigningStrategy) IsMultiChain() bool { + return o.StrategyName == "multi-chain" +} + +func (o *OCR2OnchainSigningStrategy) PublicKey() (string, error) { + pk, ok := o.Config["publicKey"] + if !ok { + return "", nil + } + name, ok := pk.(string) + if !ok { + return "", fmt.Errorf("expected string publicKey value, but got: %T", pk) + } + return name, nil +} + func validateGenericPluginSpec(ctx context.Context, spec *job.OCR2OracleSpec, rc plugins.RegistrarConfig) error { p := OCR2GenericPluginConfig{} err := json.Unmarshal(spec.PluginConfig.Bytes(), &p) @@ -187,6 +222,19 @@ func validateGenericPluginSpec(ctx context.Context, spec *job.OCR2OracleSpec, rc return errors.New("generic config invalid: only OCR version 2 and 3 are supported") } + onchainSigningStrategy := OCR2OnchainSigningStrategy{} + err = json.Unmarshal(spec.OnchainSigningStrategy.Bytes(), &onchainSigningStrategy) + if err != nil { + return err + } + pk, err := onchainSigningStrategy.PublicKey() + if err != nil { + return err + } + if pk == "" { + return errors.New("generic config invalid: must provide public key for the onchain signing strategy") + } + plugEnv := env.NewPlugin(p.PluginName) command := p.Command diff --git a/core/services/ocr2/validate/validate_test.go b/core/services/ocr2/validate/validate_test.go index 305a727d030..05881187ba4 100644 --- a/core/services/ocr2/validate/validate_test.go +++ b/core/services/ocr2/validate/validate_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -44,6 +45,11 @@ answer1 [type=median index=0]; """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -66,6 +72,8 @@ answer1 [type=median index=0]; var pc medianconfig.PluginConfig require.NoError(t, json.Unmarshal(r.PluginConfig.Bytes(), &pc)) require.NoError(t, medianconfig.ValidatePluginConfig(pc)) + var oss validate.OCR2OnchainSigningStrategy + require.NoError(t, json.Unmarshal(r.OnchainSigningStrategy.Bytes(), &oss)) }, }, { @@ -93,6 +101,11 @@ answer1 [type=median index=0]; """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -133,6 +146,11 @@ answer1 [type=median index=0]; """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -152,6 +170,11 @@ p2pPeerID = "12D3KooWHfYFQ8hGttAYbMCevQVESEQhzJAqFZokMVtom8bNxwGq" p2pv2Bootstrappers = [] [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -173,6 +196,11 @@ observationSource = """ """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -194,6 +222,11 @@ blah """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -216,6 +249,11 @@ blah """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -237,6 +275,11 @@ blah """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -256,6 +299,11 @@ p2pv2Bootstrappers = [] monitoringEndpoint = "\t/fd\2ff )(*&^%$#@" [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -292,6 +340,11 @@ ds1_multiply [type=multiply times=1.23]; ds1 -> ds1_parse -> ds1_multiply -> answer1; answer1 [type=median index=0]; """ +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -326,6 +379,11 @@ ds1_multiply [type=multiply times=1.23]; ds1 -> ds1_parse -> ds1_multiply -> answer1; answer1 [type=median index=0]; """ +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ -> @@ -353,6 +411,11 @@ ds1_multiply [type=multiply times=1.23]; ds1 -> ds1_parse -> ds1_multiply -> answer1; answer1 [type=median index=0]; """ +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -386,6 +449,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -415,6 +484,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "frog" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -446,6 +521,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b10606" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -477,6 +558,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "frog" @@ -508,6 +595,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc24" @@ -539,6 +632,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -570,6 +669,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -581,6 +686,46 @@ KeyID = "6f3b82406688b8ddb944c6f2e6d808f014c8fa8d568d639c25019568c require.Contains(t, err.Error(), "validation error for keyID") }, }, + { + name: "Generic public onchain signing strategy with no public key", + toml: ` +type = "offchainreporting2" +pluginType = "plugin" +schemaVersion = 1 +relay = "evm" +contractID = "0x613a38AC1659769640aaE063C651F48E0250454C" +p2pPeerID = "12D3KooWHfYFQ8hGttAYbMCevQVESEQhzJAqFZokMVtom8bNxwGq" +p2pv2Bootstrappers = [ +"12D3KooWHfYFQ8hGttAYbMCevQVESEQhzJAqFZokMVtom8bNxwGq@127.0.0.1:5001", +] +ocrKeyBundleID = "73e8966a78ca09bb912e9565cfb79fbe8a6048fab1f0cf49b18047c3895e0447" +monitoringEndpoint = "chain.link:4321" +transmitterID = "0xF67D0290337bca0847005C7ffD1BC75BA9AAE6e4" +observationTimeout = "10s" +observationSource = """ +ds1 [type=bridge name=voter_turnout]; +ds1_parse [type=jsonparse path="one,two"]; +ds1_multiply [type=multiply times=1.23]; +ds1 -> ds1_parse -> ds1_multiply -> answer1; +answer1 [type=median index=0]; +""" +[relayConfig] +chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "" +[pluginConfig] +pluginName = "median" +telemetryType = "median" +OCRVersion=2 +`, + assertion: func(t *testing.T, os job.Job, err error) { + require.Error(t, err) + require.Contains(t, err.Error(), "must provide public key for the onchain signing strategy") + }, + }, { name: "Generic plugin config validation - nothing provided", toml: ` @@ -601,6 +746,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -627,6 +778,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] PluginName="some random name" `, @@ -655,6 +812,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] PluginName="some random name" OCRVersion=2 @@ -684,6 +847,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] PluginName="some random name" OCRVersion=2 @@ -693,6 +862,47 @@ Command="some random command" require.Error(t, err) require.ErrorContains(t, err, "failed to find binary") }, + }, { + name: "minimal OCR2 oracle spec with JuelsPerFeeCoinCache", + toml: ` +type = "offchainreporting2" +pluginType = "median" +schemaVersion = 1 +relay = "evm" +contractID = "0x613a38AC1659769640aaE063C651F48E0250454C" +observationSource = """ +ds1 [type=bridge name=voter_turnout]; +ds1_parse [type=jsonparse path="one,two"]; +ds1_multiply [type=multiply times=1.23]; +ds1 -> ds1_parse -> ds1_multiply -> answer1; +answer1 [type=median index=0]; +""" +[relayConfig] +chainID = 1337 +[pluginConfig] +juelsPerFeeCoinSource = """ +ds1 [type=bridge name=voter_turnout]; +ds1_parse [type=jsonparse path="one,two"]; +ds1_multiply [type=multiply times=1.23]; +ds1 -> ds1_parse -> ds1_multiply -> answer1; +answer1 [type=median index=0]; +""" +[pluginConfig.JuelsPerFeeCoinCache] +Disable=false +UpdateInterval="1m" +`, + assertion: func(t *testing.T, os job.Job, err error) { + require.NoError(t, err) + b, err := jsonapi.Marshal(os.OCR2OracleSpec) + require.NoError(t, err) + var r job.OCR2OracleSpec + err = jsonapi.Unmarshal(b, &r) + require.NoError(t, err) + assert.Equal(t, "median", string(r.PluginType)) + var pc medianconfig.PluginConfig + require.NoError(t, json.Unmarshal(r.PluginConfig.Bytes(), &pc)) + require.NoError(t, medianconfig.ValidatePluginConfig(pc)) + }, }, } diff --git a/core/services/ocrbootstrap/database.go b/core/services/ocrbootstrap/database.go index 86ade39a05d..ef63b75dd39 100644 --- a/core/services/ocrbootstrap/database.go +++ b/core/services/ocrbootstrap/database.go @@ -8,11 +8,12 @@ import ( "github.com/pkg/errors" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" ) type db struct { - *sql.DB + ds sqlutil.DataSource oracleSpecID int32 lggr logger.Logger } @@ -20,12 +21,12 @@ type db struct { var _ ocrtypes.ConfigDatabase = &db{} // NewDB returns a new DB scoped to this oracleSpecID -func NewDB(sqldb *sql.DB, bootstrapSpecID int32, lggr logger.Logger) *db { - return &db{sqldb, bootstrapSpecID, lggr} +func NewDB(ds sqlutil.DataSource, bootstrapSpecID int32, lggr logger.Logger) *db { + return &db{ds, bootstrapSpecID, lggr} } func (d *db) ReadConfig(ctx context.Context) (c *ocrtypes.ContractConfig, err error) { - q := d.QueryRowContext(ctx, ` + q := d.ds.QueryRowxContext(ctx, ` SELECT config_digest, config_count, @@ -82,7 +83,7 @@ func (d *db) WriteConfig(ctx context.Context, c ocrtypes.ContractConfig) error { for _, s := range c.Signers { signers = append(signers, []byte(s)) } - _, err := d.ExecContext(ctx, ` + _, err := d.ds.ExecContext(ctx, ` INSERT INTO bootstrap_contract_configs ( bootstrap_spec_id, config_digest, diff --git a/core/services/ocrbootstrap/database_test.go b/core/services/ocrbootstrap/database_test.go index e00e318c69c..eaad863c88b 100644 --- a/core/services/ocrbootstrap/database_test.go +++ b/core/services/ocrbootstrap/database_test.go @@ -52,7 +52,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { lggr := logger.TestLogger(t) t.Run("reads and writes config", func(t *testing.T) { - db := ocrbootstrap.NewDB(sqlDB.DB, spec.ID, lggr) + db := ocrbootstrap.NewDB(sqlDB, spec.ID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) @@ -64,7 +64,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("updates config", func(t *testing.T) { - db := ocrbootstrap.NewDB(sqlDB.DB, spec.ID, lggr) + db := ocrbootstrap.NewDB(sqlDB, spec.ID, lggr) newConfig := ocrtypes.ContractConfig{ ConfigDigest: testhelpers.MakeConfigDigest(t), @@ -82,12 +82,12 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("does not return result for wrong spec", func(t *testing.T) { - db := ocrbootstrap.NewDB(sqlDB.DB, spec.ID, lggr) + db := ocrbootstrap.NewDB(sqlDB, spec.ID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) - db = ocrbootstrap.NewDB(sqlDB.DB, -1, lggr) + db = ocrbootstrap.NewDB(sqlDB, -1, lggr) readConfig, err := db.ReadConfig(testutils.Context(t)) require.NoError(t, err) diff --git a/core/services/ocrbootstrap/delegate.go b/core/services/ocrbootstrap/delegate.go index 84f473088bb..0bb7a0ca2ba 100644 --- a/core/services/ocrbootstrap/delegate.go +++ b/core/services/ocrbootstrap/delegate.go @@ -7,12 +7,11 @@ import ( "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - ocr "github.com/smartcontractkit/libocr/offchainreporting2plus" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -27,7 +26,7 @@ type RelayGetter interface { // Delegate creates Bootstrap jobs type Delegate struct { - db *sqlx.DB + ds sqlutil.DataSource jobORM job.ORM peerWrapper *ocrcommon.SingletonPeerWrapper ocr2Cfg validate.OCR2Config @@ -48,7 +47,7 @@ type relayConfig struct { // NewDelegateBootstrap creates a new Delegate func NewDelegateBootstrap( - db *sqlx.DB, + ds sqlutil.DataSource, jobORM job.ORM, peerWrapper *ocrcommon.SingletonPeerWrapper, lggr logger.Logger, @@ -57,7 +56,7 @@ func NewDelegateBootstrap( relayers RelayGetter, ) *Delegate { return &Delegate{ - db: db, + ds: ds, jobORM: jobORM, peerWrapper: peerWrapper, lggr: logger.Sugared(lggr), @@ -166,10 +165,10 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] bootstrapNodeArgs := ocr.BootstrapperArgs{ BootstrapperFactory: d.peerWrapper.Peer2, ContractConfigTracker: configProvider.ContractConfigTracker(), - Database: NewDB(d.db.DB, spec.ID, lggr), + Database: NewDB(d.ds, spec.ID, lggr), LocalConfig: lc, Logger: commonlogger.NewOCRWrapper(lggr.Named("OCRBootstrap"), d.ocr2Cfg.TraceLogging(), func(msg string) { - logger.Sugared(lggr).ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + logger.Sugared(lggr).ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }), OffchainConfigDigester: configProvider.OffchainConfigDigester(), } diff --git a/core/services/ocrcommon/data_source.go b/core/services/ocrcommon/data_source.go index 9ca111dea68..cb544e01639 100644 --- a/core/services/ocrcommon/data_source.go +++ b/core/services/ocrcommon/data_source.go @@ -113,18 +113,23 @@ type DataSourceCacheService interface { median.DataSource } -func NewInMemoryDataSourceCache(ds median.DataSource, kvStore job.KVStore, cacheCfg config.JuelsPerFeeCoinCache) (DataSourceCacheService, error) { +func NewInMemoryDataSourceCache(ds median.DataSource, kvStore job.KVStore, cacheCfg *config.JuelsPerFeeCoinCache) (DataSourceCacheService, error) { inMemoryDS, ok := ds.(*inMemoryDataSource) if !ok { return nil, errors.Errorf("unsupported data source type: %T, only inMemoryDataSource supported", ds) } - - updateInterval, stalenessAlertThreshold := cacheCfg.UpdateInterval.Duration(), cacheCfg.StalenessAlertThreshold.Duration() - if updateInterval == 0 { + var updateInterval, stalenessAlertThreshold time.Duration + if cacheCfg == nil { updateInterval = defaultUpdateInterval - } - if stalenessAlertThreshold == 0 { stalenessAlertThreshold = defaultStalenessAlertThreshold + } else { + updateInterval, stalenessAlertThreshold = cacheCfg.UpdateInterval.Duration(), cacheCfg.StalenessAlertThreshold.Duration() + if updateInterval == 0 { + updateInterval = defaultUpdateInterval + } + if stalenessAlertThreshold == 0 { + stalenessAlertThreshold = defaultStalenessAlertThreshold + } } dsCache := &inMemoryDataSourceCache{ diff --git a/core/services/ocrcommon/data_source_test.go b/core/services/ocrcommon/data_source_test.go index 05ba0f4aa42..a62852eaced 100644 --- a/core/services/ocrcommon/data_source_test.go +++ b/core/services/ocrcommon/data_source_test.go @@ -80,7 +80,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { mockKVStore := mocks.KVStore{} mockKVStore.On("Store", mock.Anything, mock.Anything, mock.Anything).Return(nil) mockKVStore.On("Get", mock.Anything, mock.Anything).Return(nil, nil) - dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Second * 2)}) + dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, &config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Second * 2)}) require.NoError(t, err) servicetest.Run(t, dsCache) @@ -114,7 +114,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { mockKVStore.On("Get", mock.Anything, mock.Anything).Return(result, nil) // set updater to a long time so that it doesn't log errors after the test is done - dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) + dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, &config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) require.NoError(t, err) changeResultValue(runner, "-1", true, false) servicetest.Run(t, dsCache) @@ -133,7 +133,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { mockKVStore.On("Get", mock.Anything, mock.Anything).Return(nil, assert.AnError) // set updater to a long time so that it doesn't log errors after the test is done - dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) + dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, &config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) require.NoError(t, err) changeResultValue(runner, "-1", true, false) servicetest.Run(t, dsCache) diff --git a/core/services/ocrcommon/discoverer_database.go b/core/services/ocrcommon/discoverer_database.go index 9413b11ad07..ea75f9e6d21 100644 --- a/core/services/ocrcommon/discoverer_database.go +++ b/core/services/ocrcommon/discoverer_database.go @@ -2,25 +2,26 @@ package ocrcommon import ( "context" - "database/sql" "github.com/lib/pq" "github.com/pkg/errors" "go.uber.org/multierr" ocrnetworking "github.com/smartcontractkit/libocr/networking/types" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) var _ ocrnetworking.DiscovererDatabase = &DiscovererDatabase{} type DiscovererDatabase struct { - db *sql.DB + ds sqlutil.DataSource peerID string } -func NewDiscovererDatabase(db *sql.DB, peerID string) *DiscovererDatabase { +func NewDiscovererDatabase(ds sqlutil.DataSource, peerID string) *DiscovererDatabase { return &DiscovererDatabase{ - db, + ds, peerID, } } @@ -28,7 +29,7 @@ func NewDiscovererDatabase(db *sql.DB, peerID string) *DiscovererDatabase { // StoreAnnouncement has key-value-store semantics and stores a peerID (key) and an associated serialized // announcement (value). func (d *DiscovererDatabase) StoreAnnouncement(ctx context.Context, peerID string, ann []byte) error { - _, err := d.db.ExecContext(ctx, ` + _, err := d.ds.ExecContext(ctx, ` INSERT INTO ocr_discoverer_announcements (local_peer_id, remote_peer_id, ann, created_at, updated_at) VALUES ($1,$2,$3,NOW(),NOW()) ON CONFLICT (local_peer_id, remote_peer_id) DO UPDATE SET ann = EXCLUDED.ann, @@ -40,7 +41,7 @@ updated_at = EXCLUDED.updated_at // ReadAnnouncements returns one serialized announcement (if available) for each of the peerIDs in the form of a map // keyed by each announcement's corresponding peer ID. func (d *DiscovererDatabase) ReadAnnouncements(ctx context.Context, peerIDs []string) (results map[string][]byte, err error) { - rows, err := d.db.QueryContext(ctx, ` + rows, err := d.ds.QueryContext(ctx, ` SELECT remote_peer_id, ann FROM ocr_discoverer_announcements WHERE remote_peer_id = ANY($1) AND local_peer_id = $2`, pq.Array(peerIDs), d.peerID) if err != nil { return nil, errors.Wrap(err, "DiscovererDatabase failed to ReadAnnouncements") diff --git a/core/services/ocrcommon/discoverer_database_test.go b/core/services/ocrcommon/discoverer_database_test.go index b7a79e92bce..23d5ad661a4 100644 --- a/core/services/ocrcommon/discoverer_database_test.go +++ b/core/services/ocrcommon/discoverer_database_test.go @@ -16,7 +16,7 @@ import ( ) func Test_DiscovererDatabase(t *testing.T) { - db := pgtest.NewSqlDB(t) + db := pgtest.NewSqlxDB(t) localPeerID1 := mustRandomP2PPeerID(t) localPeerID2 := mustRandomP2PPeerID(t) diff --git a/core/services/ocrcommon/peer_wrapper.go b/core/services/ocrcommon/peer_wrapper.go index 02bdd9cee7d..97c429f9a5f 100644 --- a/core/services/ocrcommon/peer_wrapper.go +++ b/core/services/ocrcommon/peer_wrapper.go @@ -4,7 +4,6 @@ import ( "context" "io" - "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" @@ -14,12 +13,12 @@ import ( commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type PeerWrapperOCRConfig interface { @@ -43,8 +42,7 @@ type ( keyStore keystore.Master p2pCfg config.P2P ocrCfg PeerWrapperOCRConfig - dbConfig pg.QConfig - db *sqlx.DB + ds sqlutil.DataSource lggr logger.Logger PeerID p2pkey.PeerID @@ -69,13 +67,12 @@ func ValidatePeerWrapperConfig(config config.P2P) error { // NewSingletonPeerWrapper creates a new peer based on the p2p keys in the keystore // It currently only supports one peerID/key // It should be fairly easy to modify it to support multiple peerIDs/keys using e.g. a map -func NewSingletonPeerWrapper(keyStore keystore.Master, p2pCfg config.P2P, ocrCfg PeerWrapperOCRConfig, dbConfig pg.QConfig, db *sqlx.DB, lggr logger.Logger) *SingletonPeerWrapper { +func NewSingletonPeerWrapper(keyStore keystore.Master, p2pCfg config.P2P, ocrCfg PeerWrapperOCRConfig, ds sqlutil.DataSource, lggr logger.Logger) *SingletonPeerWrapper { return &SingletonPeerWrapper{ keyStore: keyStore, p2pCfg: p2pCfg, ocrCfg: ocrCfg, - dbConfig: dbConfig, - db: db, + ds: ds, lggr: lggr.Named("SingletonPeerWrapper"), } } @@ -120,7 +117,7 @@ func (p *SingletonPeerWrapper) peerConfig() (ocrnetworking.PeerConfig, error) { } p.PeerID = key.PeerID() - discovererDB := NewDiscovererDatabase(p.db.DB, p.PeerID.Raw()) + discovererDB := NewDiscovererDatabase(p.ds, p.PeerID.Raw()) config := p.p2pCfg peerConfig := ocrnetworking.PeerConfig{ diff --git a/core/services/ocrcommon/peer_wrapper_test.go b/core/services/ocrcommon/peer_wrapper_test.go index e87f211fd21..a47ed19ec56 100644 --- a/core/services/ocrcommon/peer_wrapper_test.go +++ b/core/services/ocrcommon/peer_wrapper_test.go @@ -34,7 +34,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { c.P2P.V2.Enabled = ptr(true) }) keyStore := cltest.NewKeyStore(t, db) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.Contains(t, pw.Start(testutils.Context(t)).Error(), "No P2P keys found in keystore. Peer wrapper will not be fully initialized") }) @@ -49,7 +49,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} c.P2P.PeerID = ptr(k.PeerID()) }) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) servicetest.Run(t, pw) require.Equal(t, k.PeerID(), pw.PeerID) @@ -66,7 +66,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { _, err := keyStore.P2P().Create(ctx) require.NoError(t, err) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.Contains(t, pw.Start(testutils.Context(t)).Error(), "unable to find P2P key with id") }) @@ -83,7 +83,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { c.P2P.PeerID = ptr(k2.PeerID()) }) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) servicetest.Run(t, pw) require.Equal(t, k2.PeerID(), pw.PeerID) @@ -101,7 +101,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { _, err := keyStore.P2P().Create(ctx) require.NoError(t, err) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.Contains(t, pw.Start(testutils.Context(t)).Error(), "unable to find P2P key with id") }) @@ -131,7 +131,7 @@ func Test_SingletonPeerWrapper_Close(t *testing.T) { }) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.NoError(t, pw.Start(testutils.Context(t))) require.True(t, pw.IsStarted(), "Should have started successfully") @@ -139,7 +139,7 @@ func Test_SingletonPeerWrapper_Close(t *testing.T) { /* If peer is still stuck in listenLoop, we will get a bind error trying to start on the same port */ require.False(t, pw.IsStarted()) - pw = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.NoError(t, pw.Start(testutils.Context(t)), "Should have shut down gracefully, and be able to re-use same port") require.True(t, pw.IsStarted(), "Should have started successfully") require.NoError(t, pw.Close()) diff --git a/core/services/pg/connection.go b/core/services/pg/connection.go index 79d74c6e610..e8b6f3af429 100644 --- a/core/services/pg/connection.go +++ b/core/services/pg/connection.go @@ -1,6 +1,7 @@ package pg import ( + "database/sql" "fmt" "log" "os" @@ -18,6 +19,10 @@ import ( "github.com/XSAM/otelsql" ) +// NOTE: This is the default level in Postgres anyway, we just make it +// explicit here +const defaultIsolation = sql.LevelReadCommitted + var MinRequiredPGVersion = 110000 func init() { diff --git a/core/services/pg/lease_lock.go b/core/services/pg/lease_lock.go index 58ec2781245..885115d26c7 100644 --- a/core/services/pg/lease_lock.go +++ b/core/services/pg/lease_lock.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -248,10 +249,12 @@ func (l *leaseLock) getLease(ctx context.Context, isInitial bool) (gotLease bool // NOTE: Uses database time for all calculations since it's conceivable // that node local times might be skewed compared to each other - err = sqlxTransactionQ(ctx, l.conn, l.logger, func(tx Queryer) error { + err = sqlutil.TransactConn(ctx, func(ds sqlutil.DataSource) sqlutil.DataSource { + return ds + }, l.conn, nil, func(tx sqlutil.DataSource) error { if isInitial { for _, query := range initialSQL { - if _, err = tx.Exec(query); err != nil { + if _, err = tx.ExecContext(ctx, query); err != nil { return errors.Wrap(err, "failed to create initial lease_lock table") } } @@ -259,7 +262,7 @@ func (l *leaseLock) getLease(ctx context.Context, isInitial bool) (gotLease bool // Upsert the lease_lock, only overwriting an existing one if the existing one has expired var res sql.Result - res, err = tx.Exec(` + res, err = tx.ExecContext(ctx, ` INSERT INTO lease_lock (client_id, expires_at) VALUES ($1, NOW()+$2::interval) ON CONFLICT ((client_id IS NOT NULL)) DO UPDATE SET client_id = EXCLUDED.client_id, expires_at = EXCLUDED.expires_at diff --git a/core/services/pg/q.go b/core/services/pg/q.go deleted file mode 100644 index 433023ddbc9..00000000000 --- a/core/services/pg/q.go +++ /dev/null @@ -1,384 +0,0 @@ -package pg - -import ( - "context" - "database/sql" - "fmt" - "strconv" - "strings" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" - "github.com/lib/pq" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" -) - -// QOpt is deprecated. Use [sqlutil.DataSource] with [sqlutil.QueryHook]s instead. -// -// QOpt pattern for ORM methods aims to clarify usage and remove some common footguns, notably: -// -// 1. It should be easy and obvious how to pass a parent context or a transaction into an ORM method -// 2. Simple queries should not be cluttered -// 3. It should have compile-time safety and be explicit -// 4. It should enforce some sort of context deadline on all queries by default -// 5. It should optimise for clarity and readability -// 6. It should mandate using sqlx everywhere, gorm is forbidden in new code -// 7. It should make using sqlx a little more convenient by wrapping certain methods -// 8. It allows easier mocking of DB calls (Queryer is an interface) -// -// The two main concepts introduced are: -// -// A `Q` struct that wraps a `sqlx.DB` or `sqlx.Tx` and implements the `pg.Queryer` interface. -// -// This struct is initialised with `QOpts` which define how the queryer should behave. `QOpts` can define a parent context, an open transaction or other options to configure the Queryer. -// -// A sample ORM method looks like this: -// -// func (o *orm) GetFoo(id int64, qopts ...pg.QOpt) (Foo, error) { -// q := pg.NewQ(q, qopts...) -// return q.Exec(...) -// } -// -// Now you can call it like so: -// -// orm.GetFoo(1) // will automatically have default query timeout context set -// orm.GetFoo(1, pg.WithParentCtx(ctx)) // will wrap the supplied parent context with the default query context -// orm.GetFoo(1, pg.WithQueryer(tx)) // allows to pass in a running transaction or anything else that implements Queryer -// orm.GetFoo(q, pg.WithQueryer(tx), pg.WithParentCtx(ctx)) // options can be combined -type QOpt func(*Q) - -// WithQueryer sets the queryer -func WithQueryer(queryer Queryer) QOpt { - return func(q *Q) { - if q.Queryer != nil { - panic("queryer already set") - } - q.Queryer = queryer - } -} - -// WithParentCtx sets or overwrites the parent ctx -func WithParentCtx(ctx context.Context) QOpt { - return func(q *Q) { - q.ParentCtx = ctx - } -} - -// If the parent has a timeout, just use that instead of DefaultTimeout -func WithParentCtxInheritTimeout(ctx context.Context) QOpt { - return func(q *Q) { - q.ParentCtx = ctx - deadline, ok := q.ParentCtx.Deadline() - if ok { - q.QueryTimeout = time.Until(deadline) - } - } -} - -// WithLongQueryTimeout prevents the usage of the `DefaultQueryTimeout` duration and uses `OneMinuteQueryTimeout` instead -// Some queries need to take longer when operating over big chunks of data, like deleting jobs, but we need to keep some upper bound timeout -func WithLongQueryTimeout() QOpt { - return func(q *Q) { - q.QueryTimeout = longQueryTimeout - } -} - -var _ Queryer = Q{} - -type QConfig interface { - LogSQL() bool - DefaultQueryTimeout() time.Duration -} - -// Q wraps an underlying queryer (either a *sqlx.DB or a *sqlx.Tx) -// -// It is designed to make handling *sqlx.Tx or *sqlx.DB a little bit safer by -// preventing footguns such as having no deadline on contexts. -// -// It also handles nesting transactions. -// -// It automatically adds the default context deadline to all non-context -// queries (if you _really_ want to issue a query without a context, use the -// underlying Queryer) -// -// This is not the prettiest construct but without macros its about the best we -// can do. -// Deprecated: Use a `sqlutil.DataSource` with `sqlutil.QueryHook`s instead -type Q struct { - Queryer - ParentCtx context.Context - db *sqlx.DB - logger logger.SugaredLogger - config QConfig - QueryTimeout time.Duration -} - -func NewQ(db *sqlx.DB, lggr logger.Logger, config QConfig, qopts ...QOpt) (q Q) { - for _, opt := range qopts { - opt(&q) - } - - q.db = db - // skip two levels since we use internal helpers and also want to point up the stack to the caller of the Q method. - q.logger = logger.Sugared(logger.Helper(lggr, 2)) - q.config = config - - if q.Queryer == nil { - q.Queryer = db - } - if q.ParentCtx == nil { - q.ParentCtx = context.Background() - } - if q.QueryTimeout <= 0 { - q.QueryTimeout = q.config.DefaultQueryTimeout() - } - return -} - -func (q Q) originalLogger() logger.Logger { - return logger.Helper(q.logger, -2) -} - -func PrepareQueryRowx(q Queryer, sql string, dest interface{}, arg interface{}) error { - stmt, err := q.PrepareNamed(sql) - if err != nil { - return errors.Wrap(err, "error preparing named statement") - } - defer stmt.Close() - return errors.Wrap(stmt.QueryRowx(arg).Scan(dest), "error querying row") -} - -func (q Q) WithOpts(qopts ...QOpt) Q { - return NewQ(q.db, q.originalLogger(), q.config, qopts...) -} - -func (q Q) Context() (context.Context, context.CancelFunc) { - return context.WithTimeout(q.ParentCtx, q.QueryTimeout) -} - -func (q Q) Transaction(fc func(q Queryer) error, txOpts ...TxOption) error { - ctx, cancel := q.Context() - defer cancel() - return SqlxTransaction(ctx, q.Queryer, q.originalLogger(), fc, txOpts...) -} - -// CAUTION: A subtle problem lurks here, because the following code is buggy: -// -// ctx, cancel := context.WithCancel(context.Background()) -// rows, err := db.QueryContext(ctx, "SELECT foo") -// cancel() // canceling here "poisons" the scan below -// for rows.Next() { -// rows.Scan(...) -// } -// -// We must cancel the context only after we have completely finished using the -// returned rows or result from the query/exec -// -// For this reasons, the following functions return a context.CancelFunc and it -// is up to the caller to ensure that cancel is called after it has finished -// -// Generally speaking, it makes more sense to use Get/Select in most cases, -// which avoids this problem -func (q Q) ExecQIter(query string, args ...interface{}) (sql.Result, context.CancelFunc, error) { - ctx, cancel := q.Context() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - res, err := q.Queryer.ExecContext(ctx, query, args...) - return res, cancel, ql.withLogError(err) -} -func (q Q) ExecQWithRowsAffected(query string, args ...interface{}) (int64, error) { - res, cancel, err := q.ExecQIter(query, args...) - defer cancel() - if err != nil { - return 0, err - } - - rowsDeleted, err := res.RowsAffected() - return rowsDeleted, err -} -func (q Q) ExecQ(query string, args ...interface{}) error { - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - _, err := q.Queryer.ExecContext(ctx, query, args...) - return ql.withLogError(err) -} -func (q Q) ExecQNamed(query string, arg interface{}) (err error) { - query, args, err := q.BindNamed(query, arg) - if err != nil { - return errors.Wrap(err, "error binding arg") - } - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - _, err = q.Queryer.ExecContext(ctx, query, args...) - return ql.withLogError(err) -} - -// Select and Get are safe to wrap the context cancellation because the rows -// are entirely consumed within the call -func (q Q) Select(dest interface{}, query string, args ...interface{}) error { - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - return ql.withLogError(q.Queryer.SelectContext(ctx, dest, query, args...)) -} - -func (q Q) SelectNamed(dest interface{}, query string, arg interface{}) error { - query, args, err := q.BindNamed(query, arg) - if err != nil { - return errors.Wrap(err, "error binding arg") - } - return q.Select(dest, query, args...) -} - -func (q Q) Get(dest interface{}, query string, args ...interface{}) error { - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - return ql.withLogError(q.Queryer.GetContext(ctx, dest, query, args...)) -} - -func (q Q) GetNamed(sql string, dest interface{}, arg interface{}) error { - query, args, err := q.BindNamed(sql, arg) - if err != nil { - return errors.Wrap(err, "error binding arg") - } - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - return ql.withLogError(errors.Wrap(q.GetContext(ctx, dest, query, args...), "error in get query")) -} - -func (q Q) newQueryLogger(query string, args []interface{}) *queryLogger { - return &queryLogger{Q: q, query: query, args: args, str: sync.OnceValue(func() string { - return sprintQ(query, args) - })} -} - -// sprintQ formats the query with the given args and returns the resulting string. -func sprintQ(query string, args []interface{}) string { - if args == nil { - return query - } - var pairs []string - for i, arg := range args { - // We print by type so one can directly take the logged query string and execute it manually in pg. - // Annoyingly it seems as though the logger itself will add an extra \, so you still have to remove that. - switch v := arg.(type) { - case []byte: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'\\x%x'", v)) - case common.Address: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'\\x%x'", v.Bytes())) - case common.Hash: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'\\x%x'", v.Bytes())) - case pq.ByteaArray: - pairs = append(pairs, fmt.Sprintf("$%d", i+1)) - if v == nil { - pairs = append(pairs, "NULL") - continue - } - if len(v) == 0 { - pairs = append(pairs, "ARRAY[]") - continue - } - var s strings.Builder - fmt.Fprintf(&s, "ARRAY['\\x%x'", v[0]) - for j := 1; j < len(v); j++ { - fmt.Fprintf(&s, ",'\\x%x'", v[j]) - } - pairs = append(pairs, fmt.Sprintf("%s]", s.String())) - case string: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'%s'", v)) - default: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("%v", v)) - } - } - replacer := strings.NewReplacer(pairs...) - queryWithVals := replacer.Replace(query) - return strings.ReplaceAll(strings.ReplaceAll(queryWithVals, "\n", " "), "\t", " ") -} - -// queryLogger extends Q with logging helpers for a particular query w/ args. -type queryLogger struct { - Q - - query string - args []interface{} - - str func() string -} - -func (q *queryLogger) String() string { - return q.str() -} - -func (q *queryLogger) logSqlQuery() { - if q.config != nil && q.config.LogSQL() { - q.logger.Debugw("SQL QUERY", "sql", q) - } -} - -func (q *queryLogger) withLogError(err error) error { - if err != nil && !errors.Is(err, sql.ErrNoRows) && q.config != nil && q.config.LogSQL() { - q.logger.Errorw("SQL ERROR", "err", err, "sql", q) - } - return err -} - -// postSqlLog logs about context cancellation and timing after a query returns. -// Queries which use their full timeout log critical level. More than 50% log error, and 10% warn. -func (q *queryLogger) postSqlLog(ctx context.Context, begin time.Time) { - elapsed := time.Since(begin) - if ctx.Err() != nil { - q.logger.Debugw("SQL CONTEXT CANCELLED", "ms", elapsed.Milliseconds(), "err", ctx.Err(), "sql", q) - } - - timeout := q.QueryTimeout - if timeout <= 0 { - timeout = DefaultQueryTimeout - } - - pct := float64(elapsed) / float64(timeout) - pct *= 100 - - kvs := []any{"ms", elapsed.Milliseconds(), "timeout", timeout.Milliseconds(), "percent", strconv.FormatFloat(pct, 'f', 1, 64), "sql", q} - - if elapsed >= timeout { - q.logger.Criticalw("SLOW SQL QUERY", kvs...) - } else if errThreshold := timeout / 5; errThreshold > 0 && elapsed > errThreshold { - q.logger.Errorw("SLOW SQL QUERY", kvs...) - } else if warnThreshold := timeout / 10; warnThreshold > 0 && elapsed > warnThreshold { - q.logger.Warnw("SLOW SQL QUERY", kvs...) - } - - sqlutil.PromSQLQueryTime.Observe(pct) -} diff --git a/core/services/pg/q_test.go b/core/services/pg/q_test.go deleted file mode 100644 index 81a883789df..00000000000 --- a/core/services/pg/q_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package pg - -import ( - "testing" - - "github.com/google/uuid" - "github.com/jmoiron/sqlx" - "github.com/lib/pq" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/store/dialects" -) - -func Test_sprintQ(t *testing.T) { - for _, tt := range []struct { - name string - query string - args []interface{} - exp string - }{ - {"none", - "SELECT * FROM table;", - nil, - "SELECT * FROM table;"}, - {"one", - "SELECT $1 FROM table;", - []interface{}{"foo"}, - "SELECT 'foo' FROM table;"}, - {"two", - "SELECT $1 FROM table WHERE bar = $2;", - []interface{}{"foo", 1}, - "SELECT 'foo' FROM table WHERE bar = 1;"}, - {"limit", - "SELECT $1 FROM table LIMIT $2;", - []interface{}{"foo", Limit(10)}, - "SELECT 'foo' FROM table LIMIT 10;"}, - {"limit-all", - "SELECT $1 FROM table LIMIT $2;", - []interface{}{"foo", Limit(-1)}, - "SELECT 'foo' FROM table LIMIT NULL;"}, - {"bytea", - "SELECT $1 FROM table WHERE b = $2;", - []interface{}{"foo", []byte{0x0a}}, - "SELECT 'foo' FROM table WHERE b = '\\x0a';"}, - {"bytea[]", - "SELECT $1 FROM table WHERE b = $2;", - []interface{}{"foo", pq.ByteaArray([][]byte{{0xa}, {0xb}})}, - "SELECT 'foo' FROM table WHERE b = ARRAY['\\x0a','\\x0b'];"}, - } { - t.Run(tt.name, func(t *testing.T) { - got := sprintQ(tt.query, tt.args) - t.Log(tt.query, tt.args) - t.Log(got) - require.Equal(t, tt.exp, got) - }) - } -} - -func Test_ExecQWithRowsAffected(t *testing.T) { - testutils.SkipShortDB(t) - db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) - require.NoError(t, err) - q := NewQ(db, logger.NullLogger, NewQConfig(false)) - - require.NoError(t, q.ExecQ("CREATE TABLE testtable (a TEXT, b TEXT)")) - - rows, err := q.ExecQWithRowsAffected("INSERT INTO testtable (a, b) VALUES ($1, $2)", "foo", "bar") - require.NoError(t, err) - assert.Equal(t, int64(1), rows) - - rows, err = q.ExecQWithRowsAffected("INSERT INTO testtable (a, b) VALUES ($1, $1), ($2, $2), ($1, $2)", "foo", "bar") - require.NoError(t, err) - assert.Equal(t, int64(3), rows) - - rows, err = q.ExecQWithRowsAffected("delete from testtable") - require.NoError(t, err) - assert.Equal(t, int64(4), rows) - - rows, err = q.ExecQWithRowsAffected("delete from testtable") - require.NoError(t, err) - assert.Equal(t, int64(0), rows) -} diff --git a/core/services/pg/sqlx.go b/core/services/pg/sqlx.go index 76eae792cbf..9c99142e5c9 100644 --- a/core/services/pg/sqlx.go +++ b/core/services/pg/sqlx.go @@ -4,12 +4,8 @@ import ( "context" "database/sql" - "github.com/pkg/errors" - mapper "github.com/scylladb/go-reflectx" - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/scylladb/go-reflectx" ) // Queryer is deprecated. Use sqlutil.DataSource instead @@ -32,22 +28,6 @@ type Queryer interface { func WrapDbWithSqlx(rdb *sql.DB) *sqlx.DB { db := sqlx.NewDb(rdb, "postgres") - db.MapperFunc(mapper.CamelToSnakeASCII) + db.MapperFunc(reflectx.CamelToSnakeASCII) return db } - -func SqlxTransaction(ctx context.Context, q Queryer, lggr logger.Logger, fc func(q Queryer) error, txOpts ...TxOption) (err error) { - switch db := q.(type) { - case *sqlx.Tx: - // nested transaction: just use the outer transaction - err = fc(db) - case *sqlx.DB: - err = sqlxTransactionQ(ctx, db, lggr, fc, txOpts...) - case Q: - err = sqlxTransactionQ(ctx, db.db, lggr, fc, txOpts...) - default: - err = errors.Errorf("invalid db type: %T", q) - } - - return -} diff --git a/core/services/pg/transaction.go b/core/services/pg/transaction.go deleted file mode 100644 index d60270b4fe8..00000000000 --- a/core/services/pg/transaction.go +++ /dev/null @@ -1,95 +0,0 @@ -package pg - -import ( - "context" - "database/sql" - "fmt" - "time" - - "github.com/getsentry/sentry-go" - "github.com/jmoiron/sqlx" - "github.com/pkg/errors" - "go.uber.org/multierr" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// NOTE: This is the default level in Postgres anyway, we just make it -// explicit here -const defaultIsolation = sql.LevelReadCommitted - -// TxOption is a functional option for SQL transactions. -type TxOption func(*sql.TxOptions) - -func OptReadOnlyTx() TxOption { - return func(opts *sql.TxOptions) { - opts.ReadOnly = true - } -} - -func SqlTransaction(ctx context.Context, rdb *sql.DB, lggr logger.Logger, fn func(tx *sqlx.Tx) error, opts ...TxOption) (err error) { - db := WrapDbWithSqlx(rdb) - wrapFn := func(q Queryer) error { - tx, ok := q.(*sqlx.Tx) - if !ok { - panic(fmt.Sprintf("expected q to be %T but got %T", tx, q)) - } - return fn(tx) - } - return sqlxTransactionQ(ctx, db, lggr, wrapFn, opts...) -} - -// txBeginner can be a db or a conn, anything that implements BeginTxx -type txBeginner interface { - BeginTxx(context.Context, *sql.TxOptions) (*sqlx.Tx, error) -} - -func sqlxTransactionQ(ctx context.Context, db txBeginner, lggr logger.Logger, fn func(q Queryer) error, opts ...TxOption) (err error) { - var txOpts sql.TxOptions - for _, o := range opts { - o(&txOpts) - } - - var tx *sqlx.Tx - tx, err = db.BeginTxx(ctx, &txOpts) - if err != nil { - return errors.Wrap(err, "failed to begin transaction") - } - - defer func() { - if p := recover(); p != nil { - sentry.CurrentHub().Recover(p) - sentry.Flush(corelogger.SentryFlushDeadline) - - // A panic occurred, rollback and repanic - lggr.Errorf("Panic in transaction, rolling back: %s", p) - done := make(chan struct{}) - go func() { - if rerr := tx.Rollback(); rerr != nil { - lggr.Errorf("Failed to rollback on panic: %s", rerr) - } - close(done) - }() - select { - case <-done: - panic(p) - case <-time.After(10 * time.Second): - panic(fmt.Sprintf("panic in transaction; aborting rollback that took longer than 10s: %s", p)) - } - } else if err != nil { - lggr.Warnf("Error in transaction, rolling back: %s", err) - // An error occurred, rollback and return error - if rerr := tx.Rollback(); rerr != nil { - err = multierr.Combine(err, errors.WithStack(rerr)) - } - } else { - // All good! Time to commit. - err = errors.WithStack(tx.Commit()) - } - }() - - err = fn(tx) - - return -} diff --git a/core/services/pg/utils.go b/core/services/pg/utils.go deleted file mode 100644 index eb53c261296..00000000000 --- a/core/services/pg/utils.go +++ /dev/null @@ -1,50 +0,0 @@ -package pg - -import ( - "database/sql/driver" - "strconv" - "time" -) - -const ( - // DefaultQueryTimeout is a reasonable upper bound for how long a SQL query should take. - // The configured value should be used instead of this if possible. - DefaultQueryTimeout = 10 * time.Second - // longQueryTimeout is a bigger upper bound for how long a SQL query should take - longQueryTimeout = 1 * time.Minute -) - -var _ driver.Valuer = Limit(-1) - -// Limit is a helper driver.Valuer for LIMIT queries which uses nil/NULL for negative values. -type Limit int - -func (l Limit) String() string { - if l < 0 { - return "NULL" - } - return strconv.Itoa(int(l)) -} - -func (l Limit) Value() (driver.Value, error) { - if l < 0 { - return nil, nil - } - return l, nil -} - -var _ QConfig = &qConfig{} - -// qConfig implements pg.QCOnfig -type qConfig struct { - logSQL bool - defaultQueryTimeout time.Duration -} - -func NewQConfig(logSQL bool) QConfig { - return &qConfig{logSQL, DefaultQueryTimeout} -} - -func (p *qConfig) LogSQL() bool { return p.logSQL } - -func (p *qConfig) DefaultQueryTimeout() time.Duration { return p.defaultQueryTimeout } diff --git a/core/services/pipeline/helpers_test.go b/core/services/pipeline/helpers_test.go index 0bbdef7a7f2..97d81f56f74 100644 --- a/core/services/pipeline/helpers_test.go +++ b/core/services/pipeline/helpers_test.go @@ -5,7 +5,6 @@ import ( "github.com/google/uuid" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" ) @@ -65,4 +64,4 @@ func (t *ETHTxTask) HelperSetDependencies(legacyChains legacyevm.LegacyChainCont t.jobType = jobType } -func (o *orm) Prune(ds sqlutil.DataSource, pipelineSpecID int32) { o.prune(ds, pipelineSpecID) } +func (o *orm) Prune(pipelineSpecID int32) { o.prune(o.ds, pipelineSpecID) } diff --git a/core/services/pipeline/mocks/orm.go b/core/services/pipeline/mocks/orm.go index 2fa6d8681e8..9bd5ddfbdea 100644 --- a/core/services/pipeline/mocks/orm.go +++ b/core/services/pipeline/mocks/orm.go @@ -58,9 +58,9 @@ func (_m *ORM) CreateRun(ctx context.Context, run *pipeline.Run) error { return r0 } -// CreateSpec provides a mock function with given fields: ctx, ds, _a2, maxTaskTimeout -func (_m *ORM) CreateSpec(ctx context.Context, ds pipeline.CreateDataSource, _a2 pipeline.Pipeline, maxTaskTimeout models.Interval) (int32, error) { - ret := _m.Called(ctx, ds, _a2, maxTaskTimeout) +// CreateSpec provides a mock function with given fields: ctx, _a1, maxTaskTimeout +func (_m *ORM) CreateSpec(ctx context.Context, _a1 pipeline.Pipeline, maxTaskTimeout models.Interval) (int32, error) { + ret := _m.Called(ctx, _a1, maxTaskTimeout) if len(ret) == 0 { panic("no return value specified for CreateSpec") @@ -68,17 +68,17 @@ func (_m *ORM) CreateSpec(ctx context.Context, ds pipeline.CreateDataSource, _a2 var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(context.Context, pipeline.CreateDataSource, pipeline.Pipeline, models.Interval) (int32, error)); ok { - return rf(ctx, ds, _a2, maxTaskTimeout) + if rf, ok := ret.Get(0).(func(context.Context, pipeline.Pipeline, models.Interval) (int32, error)); ok { + return rf(ctx, _a1, maxTaskTimeout) } - if rf, ok := ret.Get(0).(func(context.Context, pipeline.CreateDataSource, pipeline.Pipeline, models.Interval) int32); ok { - r0 = rf(ctx, ds, _a2, maxTaskTimeout) + if rf, ok := ret.Get(0).(func(context.Context, pipeline.Pipeline, models.Interval) int32); ok { + r0 = rf(ctx, _a1, maxTaskTimeout) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(context.Context, pipeline.CreateDataSource, pipeline.Pipeline, models.Interval) error); ok { - r1 = rf(ctx, ds, _a2, maxTaskTimeout) + if rf, ok := ret.Get(1).(func(context.Context, pipeline.Pipeline, models.Interval) error); ok { + r1 = rf(ctx, _a1, maxTaskTimeout) } else { r1 = ret.Error(1) } diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go index 3bebfb8cbad..0a96a7e08d5 100644 --- a/core/services/pipeline/orm.go +++ b/core/services/pipeline/orm.go @@ -11,8 +11,6 @@ import ( "github.com/google/uuid" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -81,8 +79,7 @@ type CreateDataSource interface { type ORM interface { services.Service - // ds is optional and to be removed after completing https://smartcontract-it.atlassian.net/browse/BCF-2978 - CreateSpec(ctx context.Context, ds CreateDataSource, pipeline Pipeline, maxTaskTimeout models.Interval) (int32, error) + CreateSpec(ctx context.Context, pipeline Pipeline, maxTaskTimeout models.Interval) (int32, error) CreateRun(ctx context.Context, run *Run) (err error) InsertRun(ctx context.Context, run *Run) error DeleteRun(ctx context.Context, id int64) error @@ -163,6 +160,9 @@ func (o *orm) Transact(ctx context.Context, fn func(ORM) error) error { return sqlutil.Transact(ctx, func(tx sqlutil.DataSource) ORM { return o.withDataSource(tx) }, o.ds, nil, func(tx ORM) error { + if err := tx.Start(ctx); err != nil { + return fmt.Errorf("failed to start tx orm: %w", err) + } defer func() { if err := tx.Close(); err != nil { o.lggr.Warnw("Error closing temporary transactional ORM", "err", err) @@ -191,14 +191,11 @@ func (o *orm) transact(ctx context.Context, fn func(*orm) error) error { return sqlutil.Transact(ctx, o.withDataSource, o.ds, nil, fn) } -func (o *orm) CreateSpec(ctx context.Context, ds CreateDataSource, pipeline Pipeline, maxTaskDuration models.Interval) (id int32, err error) { +func (o *orm) CreateSpec(ctx context.Context, pipeline Pipeline, maxTaskDuration models.Interval) (id int32, err error) { sql := `INSERT INTO pipeline_specs (dot_dag_source, max_task_duration, created_at) VALUES ($1, $2, NOW()) RETURNING id;` - if ds == nil { - ds = o.ds - } - err = ds.GetContext(ctx, &id, sql, pipeline.Source, maxTaskDuration) + err = o.ds.GetContext(ctx, &id, sql, pipeline.Source, maxTaskDuration) return id, errors.WithStack(err) } @@ -254,13 +251,13 @@ func (o *orm) StoreRun(ctx context.Context, run *Run) (restart bool, err error) // Lock the current run. This prevents races with /v2/resume sql := `SELECT id FROM pipeline_runs WHERE id = $1 FOR UPDATE;` if _, err = tx.ds.ExecContext(ctx, sql, run.ID); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to select pipeline run %d: %w", run.ID, err) } taskRuns := []TaskRun{} // Reload task runs, we want to check for any changes while the run was ongoing if err = tx.ds.SelectContext(ctx, &taskRuns, `SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = $1`, run.ID); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to select piepline task run %d: %w", run.ID, err) } // Construct a temporary run so we can use r.ByDotID @@ -287,17 +284,17 @@ func (o *orm) StoreRun(ctx context.Context, run *Run) (restart bool, err error) // Suspend the run run.State = RunStatusSuspended if _, err = tx.ds.NamedExecContext(ctx, `UPDATE pipeline_runs SET state = :state WHERE id = :id`, run); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to update pipeline run %d to %s: %w", run.ID, run.State, err) } } else { defer o.prune(tx.ds, run.PruningKey) // Simply finish the run, no need to do any sort of locking if run.Outputs.Val == nil || len(run.FatalErrors)+len(run.AllErrors) == 0 { - return errors.Errorf("run must have both Outputs and Errors, got Outputs: %#v, FatalErrors: %#v, AllErrors: %#v", run.Outputs.Val, run.FatalErrors, run.AllErrors) + return fmt.Errorf("run must have both Outputs and Errors, got Outputs: %#v, FatalErrors: %#v, AllErrors: %#v", run.Outputs.Val, run.FatalErrors, run.AllErrors) } sql := `UPDATE pipeline_runs SET state = :state, finished_at = :finished_at, all_errors= :all_errors, fatal_errors= :fatal_errors, outputs = :outputs WHERE id = :id` if _, err = tx.ds.NamedExecContext(ctx, sql, run); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to update pipeline run %d: %w", run.ID, err) } } @@ -309,18 +306,15 @@ func (o *orm) StoreRun(ctx context.Context, run *Run) (restart bool, err error) RETURNING *; ` - // NOTE: can't use Select() to auto scan because we're using NamedQuery, - // sqlx.Named + Select is possible but it's about the same amount of code - var rows *sqlx.Rows - rows, err = sqlx.NamedQueryContext(ctx, tx.ds, sql, run.PipelineTaskRuns) + taskRuns := []TaskRun{} + query, args, err := tx.ds.BindNamed(sql, run.PipelineTaskRuns) if err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to prepare named query: %w", err) } - taskRuns := []TaskRun{} - if err = sqlx.StructScan(rows, &taskRuns); err != nil { - return errors.Wrap(err, "StoreRun") + err = tx.ds.SelectContext(ctx, &taskRuns, query, args...) + if err != nil { + return fmt.Errorf("failed to insert pipeline task runs: %w", err) } - // replace with new task run data run.PipelineTaskRuns = taskRuns return nil }) @@ -383,19 +377,18 @@ VALUES (:pipeline_spec_id, :pruning_key, :meta, :all_errors, :fatal_errors, :inputs, :outputs, :created_at, :finished_at, :state) RETURNING id ` - rows, errQ := sqlx.NamedQueryContext(ctx, tx.ds, pipelineRunsQuery, runs) - if errQ != nil { - return errors.Wrap(errQ, "inserting finished pipeline runs") - } - defer rows.Close() var runIDs []int64 - for rows.Next() { + err := sqlutil.NamedQueryContext(ctx, tx.ds, pipelineRunsQuery, runs, func(row sqlutil.RowScanner) error { var runID int64 - if errS := rows.Scan(&runID); errS != nil { + if errS := row.Scan(&runID); errS != nil { return errors.Wrap(errS, "scanning pipeline runs id row") } runIDs = append(runIDs, runID) + return nil + }) + if err != nil { + return errors.Wrap(err, "inserting finished pipeline runs") } pruningKeysm := make(map[int32]struct{}) @@ -717,13 +710,13 @@ const syncLimit = 1000 // // Note this does not guarantee the pipeline_runs table is kept to exactly the // max length, rather that it doesn't excessively larger than it. -func (o *orm) prune(ds sqlutil.DataSource, jobID int32) { +func (o *orm) prune(tx sqlutil.DataSource, jobID int32) { if jobID == 0 { o.lggr.Panic("expected a non-zero job ID") } // For small maxSuccessfulRuns its fast enough to prune every time if o.maxSuccessfulRuns < syncLimit { - o.execPrune(o.ctx, ds, jobID) + o.withDataSource(tx).execPrune(o.ctx, jobID) return } // for large maxSuccessfulRuns we do it async on a sampled basis @@ -736,11 +729,11 @@ func (o *orm) prune(ds sqlutil.DataSource, jobID int32) { go func() { o.lggr.Debugw("Pruning runs", "jobID", jobID, "count", val, "every", every, "maxSuccessfulRuns", o.maxSuccessfulRuns) defer o.wg.Done() - // Must not use ds here since it's async and the transaction - // could be stale ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(o.ctx), time.Minute) defer cancel() - o.execPrune(ctx, o.ds, jobID) + + // Must not use tx here since it could be stale by the time we execute async. + o.execPrune(ctx, jobID) }() }) if !ok { @@ -750,8 +743,8 @@ func (o *orm) prune(ds sqlutil.DataSource, jobID int32) { } } -func (o *orm) execPrune(ctx context.Context, ds sqlutil.DataSource, jobID int32) { - res, err := ds.ExecContext(o.ctx, `DELETE FROM pipeline_runs WHERE pruning_key = $1 AND state = $2 AND id NOT IN ( +func (o *orm) execPrune(ctx context.Context, jobID int32) { + res, err := o.ds.ExecContext(o.ctx, `DELETE FROM pipeline_runs WHERE pruning_key = $1 AND state = $2 AND id NOT IN ( SELECT id FROM pipeline_runs WHERE pruning_key = $1 AND state = $2 ORDER BY id DESC @@ -769,7 +762,7 @@ LIMIT $3 if rowsAffected == 0 { // check the spec still exists and garbage collect if necessary var exists bool - if err := ds.GetContext(ctx, &exists, `SELECT EXISTS(SELECT ps.* FROM pipeline_specs ps JOIN job_pipeline_specs jps ON (ps.id=jps.pipeline_spec_id) WHERE jps.job_id = $1)`, jobID); err != nil { + if err := o.ds.GetContext(ctx, &exists, `SELECT EXISTS(SELECT ps.* FROM pipeline_specs ps JOIN job_pipeline_specs jps ON (ps.id=jps.pipeline_spec_id) WHERE jps.job_id = $1)`, jobID); err != nil { o.lggr.Errorw("Failed check existence of pipeline_spec while pruning runs", "err", err, "jobID", jobID) return } diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index bba928534ba..6ff32e15cc7 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -1,6 +1,7 @@ package pipeline_test import ( + "context" "testing" "time" @@ -12,6 +13,7 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" @@ -25,41 +27,34 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) -type ormconfig struct { - pg.QConfig -} - -func (ormconfig) JobPipelineMaxSuccessfulRuns() uint64 { return 123456 } - type testOnlyORM interface { pipeline.ORM - AddJobPipelineSpecWithoutConstraints(jobID, pipelineSpecID int32) error + AddJobPipelineSpecWithoutConstraints(ctx context.Context, jobID, pipelineSpecID int32) error } type testORM struct { pipeline.ORM - db *sqlx.DB + ds sqlutil.DataSource } -func (torm *testORM) AddJobPipelineSpecWithoutConstraints(jobID, pipelineSpecID int32) error { - _, err := torm.db.Exec(`SET CONSTRAINTS fk_job_pipeline_spec_job DEFERRED`) +func (torm *testORM) AddJobPipelineSpecWithoutConstraints(ctx context.Context, jobID, pipelineSpecID int32) error { + _, err := torm.ds.ExecContext(ctx, `SET CONSTRAINTS fk_job_pipeline_spec_job DEFERRED`) if err != nil { return err } - _, err = torm.db.Exec(`INSERT INTO job_pipeline_specs (job_id,pipeline_spec_id, is_primary) VALUES ($1, $2, false)`, jobID, pipelineSpecID) + _, err = torm.ds.ExecContext(ctx, `INSERT INTO job_pipeline_specs (job_id,pipeline_spec_id, is_primary) VALUES ($1, $2, false)`, jobID, pipelineSpecID) if err != nil { return err } return nil } -func newTestORM(orm pipeline.ORM, db *sqlx.DB) testOnlyORM { - return &testORM{ORM: orm, db: db} +func newTestORM(orm pipeline.ORM, ds sqlutil.DataSource) testOnlyORM { + return &testORM{ORM: orm, ds: ds} } func setupORM(t *testing.T, heavy bool) (db *sqlx.DB, orm pipeline.ORM, jorm job.ORM) { @@ -70,14 +65,12 @@ func setupORM(t *testing.T, heavy bool) (db *sqlx.DB, orm pipeline.ORM, jorm job } else { db = pgtest.NewSqlxDB(t) } - cfg := ormconfig{pgtest.NewQConfig(true)} - orm = pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipelineMaxSuccessfulRuns()) - config := configtest.NewTestGeneralConfig(t) + orm = pipeline.NewORM(db, logger.TestLogger(t), 123456) lggr := logger.TestLogger(t) keyStore := cltest.NewKeyStore(t, db) bridgeORM := bridges.NewORM(db) - jorm = job.NewORM(db, orm, bridgeORM, keyStore, lggr, config.Database()) + jorm = job.NewORM(db, orm, bridgeORM, keyStore, lggr) return } @@ -103,7 +96,7 @@ func Test_PipelineORM_CreateSpec(t *testing.T) { Source: source, } - id, err := orm.CreateSpec(ctx, nil, p, maxTaskDuration) + id, err := orm.CreateSpec(ctx, p, maxTaskDuration) require.NoError(t, err) actual := pipeline.Spec{} @@ -171,7 +164,7 @@ answer2 [type=bridge name=election_winner index=1]; DotDagSource: s, }, } - err := jobORM.CreateJob(&jb) + err := jobORM.CreateJob(ctx, &jb) require.NoError(t, err) run := &pipeline.Run{ @@ -274,7 +267,7 @@ answer2 [type=bridge name=election_winner index=1]; DotDagSource: s, }, } - err := jorm.CreateJob(&jb) + err := jorm.CreateJob(ctx, &jb) require.NoError(t, err) spec := pipeline.Spec{ DotDagSource: s, @@ -665,7 +658,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) { porm := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db) - jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr, config.Database()) + jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr) defer func() { assert.NoError(t, jorm.Close()) }() timestamp := time.Now() @@ -689,7 +682,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) { MaxTaskDuration: models.Interval(1 * time.Minute), } - err := jorm.CreateJob(&keeperJob) + err := jorm.CreateJob(ctx, &keeperJob) require.NoError(t, err) require.Equal(t, job.Keeper, keeperJob.Type) @@ -768,7 +761,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { porm := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db) - jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr, config.Database()) + jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr) defer func() { assert.NoError(t, jorm.Close()) }() timestamp := time.Now() @@ -791,7 +784,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { MaxTaskDuration: models.Interval(1 * time.Minute), } - err := jorm.CreateJob(&drJob) + err := jorm.CreateJob(ctx, &drJob) require.NoError(t, err) require.Equal(t, job.DirectRequest, drJob.Type) @@ -865,13 +858,13 @@ func Test_Prune(t *testing.T) { ps1 := cltest.MustInsertPipelineSpec(t, db) // We need a job_pipeline_specs entry to test the pruning mechanism - err := torm.AddJobPipelineSpecWithoutConstraints(ps1.ID, ps1.ID) + err := torm.AddJobPipelineSpecWithoutConstraints(testutils.Context(t), ps1.ID, ps1.ID) require.NoError(t, err) jobID := ps1.ID t.Run("when there are no runs to prune, does nothing", func(t *testing.T) { - porm.Prune(db, jobID) + porm.Prune(jobID) // no error logs; it did nothing assert.Empty(t, observed.All()) @@ -907,7 +900,7 @@ func Test_Prune(t *testing.T) { cltest.MustInsertPipelineRunWithStatus(t, db, ps2.ID, pipeline.RunStatusSuspended, jobID2) } - porm.Prune(db, jobID2) + porm.Prune(jobID2) cnt := pgtest.MustCount(t, db, "SELECT count(*) FROM pipeline_runs WHERE pipeline_spec_id = $1 AND state = $2", ps1.ID, pipeline.RunStatusCompleted) assert.Equal(t, cnt, 20) diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index 862d2f49178..2de27b3d008 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -661,7 +661,7 @@ func (r *runner) Run(ctx context.Context, run *Run, l logger.Logger, saveSuccess } if err = r.orm.InsertFinishedRun(ctx, run, saveSuccessfulTaskRuns); err != nil { - return false, pkgerrors.Wrapf(err, "error storing run for spec ID %v", run.PipelineSpec.ID) + return false, pkgerrors.Wrapf(err, "error inserting finished run for spec ID %v", run.PipelineSpec.ID) } } diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go index e086d5297ef..44d7acadd27 100644 --- a/core/services/pipeline/runner_test.go +++ b/core/services/pipeline/runner_test.go @@ -33,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -42,14 +41,10 @@ import ( ) func newRunner(t testing.TB, db *sqlx.DB, bridgeORM bridges.ORM, cfg chainlink.GeneralConfig) (pipeline.Runner, *mocks.ORM) { - lggr := logger.TestLogger(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) orm := mocks.NewORM(t) - q := pg.NewQ(db, lggr, cfg.Database()) - - orm.On("GetQ").Return(q).Maybe() c := clhttptest.NewTestLocalOnlyHTTPClient() r := pipeline.NewRunner(orm, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ethKeyStore, nil, logger.TestLogger(t), c, c) return r, orm @@ -250,8 +245,7 @@ func Test_PipelineRunner_ExecuteTaskRunsWithVars(t *testing.T) { "times": "1000000000000000000", }, }, - }, - cfg.Database()) + }) defer ds1.Close() btORM.On("FindBridge", mock.Anything, bridge.Name).Return(bridge, nil).Once() @@ -269,7 +263,7 @@ func Test_PipelineRunner_ExecuteTaskRunsWithVars(t *testing.T) { defer ds4.Close() // 3. Setup final bridge task - submit, submitBt := makeBridge(t, db, expectedRequestSubmit, map[string]interface{}{"ok": true}, cfg.Database()) + submit, submitBt := makeBridge(t, db, expectedRequestSubmit, map[string]interface{}{"ok": true}) defer submit.Close() btORM.On("FindBridge", mock.Anything, submitBt.Name).Return(submitBt, nil).Once() @@ -419,10 +413,7 @@ func Test_PipelineRunner_HandleFaults(t *testing.T) { // but a sufficient number of them still complete within the desired time frame // and so we can still obtain a median. db := pgtest.NewSqlxDB(t) - orm := mocks.NewORM(t) - q := pg.NewQ(db, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - orm.On("GetQ").Return(q).Maybe() m1 := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { time.Sleep(100 * time.Millisecond) res.WriteHeader(http.StatusOK) @@ -472,8 +463,7 @@ func Test_PipelineRunner_HandleFaultsPersistRun(t *testing.T) { db := pgtest.NewSqlxDB(t) orm := mocks.NewORM(t) btORM := bridgesMocks.NewORM(t) - q := pg.NewQ(db, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - orm.On("GetQ").Return(q).Maybe() + orm.On("InsertFinishedRun", mock.Anything, mock.Anything, mock.Anything). Run(func(args mock.Arguments) { args.Get(1).(*pipeline.Run).ID = 1 @@ -513,8 +503,7 @@ func Test_PipelineRunner_ExecuteAndInsertFinishedRun_SavingTheSpec(t *testing.T) db := pgtest.NewSqlxDB(t) orm := mocks.NewORM(t) btORM := bridgesMocks.NewORM(t) - q := pg.NewQ(db, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - orm.On("GetQ").Return(q).Maybe() + orm.On("InsertFinishedRunWithSpec", mock.Anything, mock.Anything, mock.Anything). Run(func(args mock.Arguments) { args.Get(1).(*pipeline.Run).ID = 1 diff --git a/core/services/pipeline/task.bridge_test.go b/core/services/pipeline/task.bridge_test.go index 029c6c78ca8..e95aef4984c 100644 --- a/core/services/pipeline/task.bridge_test.go +++ b/core/services/pipeline/task.bridge_test.go @@ -29,7 +29,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/internal/eautils" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -217,7 +216,7 @@ func TestBridgeTask_Happy(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -259,7 +258,7 @@ func TestBridgeTask_HandlesIntermittentFailure(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) result, runInfo := task.Run(testutils.Context(t), logger.TestLogger(t), @@ -300,18 +299,19 @@ func TestBridgeTask_HandlesIntermittentFailure(t *testing.T) { func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.WebServer.BridgeCacheTTL = commonconfig.MustNewDuration(30 * time.Second) }) - queryer := pg.NewQ(db, logger.TestLogger(t), cfg.Database()) + s1 := httptest.NewServer(fakeIntermittentlyFailingPriceResponder(t, utils.MustUnmarshalToMap(btcUSDPairing), decimal.NewFromInt(9700), "", nil)) defer s1.Close() feedURL, err := url.ParseRequestURI(s1.URL) require.NoError(t, err) + db := pgtest.NewSqlxDB(t) orm := bridges.NewORM(db) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{URL: feedURL.String()}) @@ -322,12 +322,12 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) // Insert entry 1m in the past, stale value, should not be used in case of EA failure. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-1*time.Minute)) require.NoError(t, err) @@ -348,7 +348,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { require.Nil(t, result2.Value) // Insert entry 10s in the past, under 30 seconds and should be used in case of failure. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-10*time.Second)) require.NoError(t, err) @@ -398,7 +398,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { task2.HelperSetDependencies(cfg2.JobPipeline(), cfg2.WebServer(), orm, specID, uuid.UUID{}, c) // Insert entry 32m in the past, under cacheTTL of 35m but more than stalenessCap of 30m. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task2.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-32*time.Minute)) require.NoError(t, err) @@ -420,7 +420,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { require.Nil(t, result2.Value) // Insert entry 25m in the past, under stalenessCap - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task2.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-25*time.Minute)) require.NoError(t, err) @@ -482,7 +482,7 @@ func TestBridgeTask_AsyncJobPendingState(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, id, c) @@ -660,7 +660,7 @@ func TestBridgeTask_Variables(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -729,7 +729,7 @@ func TestBridgeTask_Meta(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -783,7 +783,7 @@ func TestBridgeTask_IncludeInputAtKey(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -839,7 +839,7 @@ func TestBridgeTask_ErrorMessage(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -878,7 +878,7 @@ func TestBridgeTask_OnlyErrorMessage(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -903,7 +903,7 @@ func TestBridgeTask_ErrorIfBridgeMissing(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() orm := bridges.NewORM(db) trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -993,7 +993,7 @@ func TestBridgeTask_Headers(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -1015,7 +1015,7 @@ func TestBridgeTask_Headers(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -1037,7 +1037,7 @@ func TestBridgeTask_Headers(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -1052,6 +1052,7 @@ func TestBridgeTask_Headers(t *testing.T) { func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -1062,7 +1063,6 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { Data: adapterResponseData{Result: &decimal.Zero}, } - queryer := pg.NewQ(db, logger.TestLogger(t), cfg.Database()) s1 := httptest.NewServer( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := json.NewEncoder(w).Encode(testAdapterResponse) @@ -1083,12 +1083,12 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(ctx, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) // Insert entry 1m in the past, stale value, should not be used in case of EA failure. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task.DotID(), specID, big.NewInt(9700).Bytes(), time.Now()) require.NoError(t, err) @@ -1105,7 +1105,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { // expect all external adapter response status failures to be served from the cache testAdapterResponse.SetStatusCode(http.StatusBadRequest) - result, runInfo := task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo := task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) @@ -1114,7 +1114,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { testAdapterResponse.SetStatusCode(http.StatusOK) testAdapterResponse.SetProviderStatusCode(http.StatusBadRequest) - result, runInfo = task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo = task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) @@ -1124,7 +1124,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { testAdapterResponse.SetStatusCode(http.StatusOK) testAdapterResponse.SetProviderStatusCode(http.StatusOK) testAdapterResponse.SetError("some error") - result, runInfo = task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo = task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) @@ -1132,7 +1132,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { require.False(t, runInfo.IsPending) testAdapterResponse.SetStatusCode(http.StatusInternalServerError) - result, runInfo = task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo = task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) diff --git a/core/services/pipeline/task.http_test.go b/core/services/pipeline/task.http_test.go index 6264d1e591b..4098ce50d2a 100644 --- a/core/services/pipeline/task.http_test.go +++ b/core/services/pipeline/task.http_test.go @@ -177,7 +177,7 @@ func TestHTTPTask_Variables(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) diff --git a/core/services/pipeline/test_helpers_test.go b/core/services/pipeline/test_helpers_test.go index fc87942e073..d890afc33df 100644 --- a/core/services/pipeline/test_helpers_test.go +++ b/core/services/pipeline/test_helpers_test.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/jmoiron/sqlx" @@ -39,7 +38,7 @@ func fakeExternalAdapter(t *testing.T, expectedRequest, response interface{}) ht }) } -func makeBridge(t *testing.T, db *sqlx.DB, expectedRequest, response interface{}, cfg pg.QConfig) (*httptest.Server, bridges.BridgeType) { +func makeBridge(t *testing.T, db *sqlx.DB, expectedRequest, response interface{}) (*httptest.Server, bridges.BridgeType) { t.Helper() server := httptest.NewServer(fakeExternalAdapter(t, expectedRequest, response)) diff --git a/core/services/promreporter/prom_reporter.go b/core/services/promreporter/prom_reporter.go index a302a6fa220..92e674aac44 100644 --- a/core/services/promreporter/prom_reporter.go +++ b/core/services/promreporter/prom_reporter.go @@ -2,12 +2,12 @@ package promreporter import ( "context" - "database/sql" "fmt" "math/big" "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -28,7 +28,7 @@ import ( type ( promReporter struct { services.StateMachine - db *sql.DB + ds sqlutil.DataSource chains legacyevm.LegacyChainContainer lggr logger.Logger backend PrometheusBackend @@ -92,7 +92,7 @@ func (defaultBackend) SetPipelineTaskRunsQueued(n int) { promPipelineRunsQueued.Set(float64(n)) } -func NewPromReporter(db *sql.DB, chainContainer legacyevm.LegacyChainContainer, lggr logger.Logger, opts ...interface{}) *promReporter { +func NewPromReporter(ds sqlutil.DataSource, chainContainer legacyevm.LegacyChainContainer, lggr logger.Logger, opts ...interface{}) *promReporter { var backend PrometheusBackend = defaultBackend{} period := 15 * time.Second for _, opt := range opts { @@ -106,7 +106,7 @@ func NewPromReporter(db *sql.DB, chainContainer legacyevm.LegacyChainContainer, chStop := make(chan struct{}) return &promReporter{ - db: db, + ds: ds, chains: chainContainer, lggr: lggr.Named("PromReporter"), backend: backend, @@ -242,7 +242,7 @@ func (pr *promReporter) reportMaxUnconfirmedBlocks(ctx context.Context, head *ev } func (pr *promReporter) reportPipelineRunStats(ctx context.Context) (err error) { - rows, err := pr.db.QueryContext(ctx, ` + rows, err := pr.ds.QueryContext(ctx, ` SELECT pipeline_run_id FROM pipeline_task_runs WHERE finished_at IS NULL `) if err != nil { diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index bb09b86df95..f17b4aafed2 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -48,7 +48,6 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), ethClient, lggr, lpOpts) txm, err := txmgr.NewTxm( - db, db, evmConfig, evmConfig.GasEstimator(), @@ -72,7 +71,7 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { db := pgtest.NewSqlxDB(t) backend := mocks.NewPrometheusBackend(t) - reporter := promreporter.NewPromReporter(db.DB, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) var subscribeCalls atomic.Int32 @@ -114,7 +113,7 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { subscribeCalls.Add(1) }). Return() - reporter := promreporter.NewPromReporter(db.DB, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) servicetest.Run(t, reporter) etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) @@ -133,7 +132,7 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { pgtest.MustExec(t, db, `SET CONSTRAINTS pipeline_task_runs_pipeline_run_id_fkey DEFERRED`) backend := mocks.NewPrometheusBackend(t) - reporter := promreporter.NewPromReporter(db.DB, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index e7035f4716f..df46e7636d2 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -16,8 +16,6 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -41,11 +39,11 @@ type chainReader struct { // NewChainReaderService is a constructor for ChainReader, returns nil if there is any error // Note that the ChainReaderService returned does not support anonymous events. -func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller.LogPoller, chain legacyevm.Chain, config types.ChainReaderConfig) (ChainReaderService, error) { +func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller.LogPoller, client evmclient.Client, config types.ChainReaderConfig) (ChainReaderService, error) { cr := &chainReader{ lggr: lggr.Named("ChainReader"), lp: lp, - client: chain.Client(), + client: client, contractBindings: contractBindings{}, parsed: &parsedTypes{encoderDefs: map[string]types.CodecEntry{}, decoderDefs: map[string]types.CodecEntry{}}, } diff --git a/core/services/relay/evm/chain_reader_test.go b/core/services/relay/evm/chain_reader_test.go index edca5c19b60..3a0d45b67c5 100644 --- a/core/services/relay/evm/chain_reader_test.go +++ b/core/services/relay/evm/chain_reader_test.go @@ -32,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_example" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -120,7 +119,7 @@ func triggerFourTopics(t *testing.T, it *chainReaderInterfaceTester, i1, i2, i3 } type chainReaderInterfaceTester struct { - chain *mocks.Chain + client client.Client address string address2 string chainConfig types.ChainReaderConfig @@ -157,12 +156,11 @@ func (it *chainReaderInterfaceTester) Setup(t *testing.T) { }) // can re-use the same chain for tests, just make new contract for each test - if it.chain != nil { + if it.client != nil { it.deployNewContracts(t) return } - it.chain = &mocks.Chain{} it.setupChainNoClient(t) testStruct := CreateTestStruct(0, it) @@ -240,7 +238,7 @@ func (it *chainReaderInterfaceTester) Setup(t *testing.T) { }, }, } - it.chain.On("Client").Return(client.NewSimulatedBackendClient(t, it.sim, big.NewInt(1337))) + it.client = client.NewSimulatedBackendClient(t, it.sim, big.NewInt(1337)) it.deployNewContracts(t) } @@ -270,10 +268,9 @@ func (it *chainReaderInterfaceTester) GetChainReader(t *testing.T) clcommontypes RpcBatchSize: 1, KeepFinalizedBlocksDepth: 10000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), it.chain.Client(), lggr, lpOpts) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), it.client, lggr, lpOpts) require.NoError(t, lp.Start(ctx)) - it.chain.On("LogPoller").Return(lp) - cr, err := evm.NewChainReaderService(ctx, lggr, lp, it.chain, it.chainConfig) + cr, err := evm.NewChainReaderService(ctx, lggr, lp, it.client, it.chainConfig) require.NoError(t, err) require.NoError(t, cr.Start(ctx)) it.cr = cr @@ -288,7 +285,7 @@ func (it *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *Tes it.sendTxWithTestStruct(t, testStruct, (*chain_reader_example.LatestValueHolderTransactor).TriggerEvent) } -func (it *chainReaderInterfaceTester) GetBindings(t *testing.T) []clcommontypes.BoundContract { +func (it *chainReaderInterfaceTester) GetBindings(_ *testing.T) []clcommontypes.BoundContract { return []clcommontypes.BoundContract{ {Name: AnyContractName, Address: it.address, Pending: true}, {Name: AnySecondContractName, Address: it.address2, Pending: true}, diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index e9aaa7e0a8e..737a8e7561e 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/jmoiron/sqlx" pkgerrors "github.com/pkg/errors" "golang.org/x/exp/maps" @@ -35,7 +34,6 @@ import ( lloconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/llo/config" mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" @@ -71,18 +69,17 @@ func init() { var _ commontypes.Relayer = &Relayer{} //nolint:staticcheck type Relayer struct { - db *sqlx.DB // legacy: prefer to use ds instead ds sqlutil.DataSource chain legacyevm.Chain lggr logger.Logger ks CSAETHKeystore mercuryPool wsrpc.Pool - pgCfg pg.QConfig chainReader commontypes.ChainReader codec commontypes.Codec // Mercury - mercuryORM mercury.ORM + mercuryORM mercury.ORM + transmitterCfg mercury.TransmitterConfig // LLO/data streams cdcFactory llo.ChannelDefinitionCacheFactory @@ -95,24 +92,17 @@ type CSAETHKeystore interface { } type RelayerOpts struct { - *sqlx.DB // legacy: prefer to use ds instead - DS sqlutil.DataSource - pg.QConfig + DS sqlutil.DataSource CSAETHKeystore - MercuryPool wsrpc.Pool + MercuryPool wsrpc.Pool + TransmitterConfig mercury.TransmitterConfig } func (c RelayerOpts) Validate() error { var err error - if c.DB == nil { - err = errors.Join(err, errors.New("nil DB")) - } if c.DS == nil { err = errors.Join(err, errors.New("nil DataSource")) } - if c.QConfig == nil { - err = errors.Join(err, errors.New("nil QConfig")) - } if c.CSAETHKeystore == nil { err = errors.Join(err, errors.New("nil Keystore")) } @@ -134,16 +124,15 @@ func NewRelayer(lggr logger.Logger, chain legacyevm.Chain, opts RelayerOpts) (*R lloORM := llo.NewORM(opts.DS, chain.ID()) cdcFactory := llo.NewChannelDefinitionCacheFactory(lggr, lloORM, chain.LogPoller()) return &Relayer{ - db: opts.DB, - ds: opts.DS, - chain: chain, - lggr: lggr, - ks: opts.CSAETHKeystore, - mercuryPool: opts.MercuryPool, - pgCfg: opts.QConfig, - cdcFactory: cdcFactory, - lloORM: lloORM, - mercuryORM: mercuryORM, + ds: opts.DS, + chain: chain, + lggr: lggr, + ks: opts.CSAETHKeystore, + mercuryPool: opts.MercuryPool, + cdcFactory: cdcFactory, + lloORM: lloORM, + mercuryORM: mercuryORM, + transmitterCfg: opts.TransmitterConfig, }, nil } @@ -260,7 +249,7 @@ func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commonty default: return nil, fmt.Errorf("invalid feed version %d", feedID.Version()) } - transmitter := mercury.NewTransmitter(lggr, clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec) + transmitter := mercury.NewTransmitter(lggr, r.transmitterCfg, clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec) return NewMercuryProvider(cp, r.chainReader, r.codec, NewMercuryChainReader(r.chain.HeadTracker()), transmitter, reportCodecV1, reportCodecV2, reportCodecV3, lggr), nil } @@ -610,7 +599,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp // allow fallback until chain reader is default and median contract is removed, but still log just in case var chainReaderService ChainReaderService if relayConfig.ChainReader != nil { - if chainReaderService, err = NewChainReaderService(ctx, lggr, r.chain.LogPoller(), r.chain, *relayConfig.ChainReader); err != nil { + if chainReaderService, err = NewChainReaderService(ctx, lggr, r.chain.LogPoller(), r.chain.Client(), *relayConfig.ChainReader); err != nil { return nil, err } @@ -637,7 +626,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp func (r *Relayer) NewAutomationProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.AutomationProvider, error) { lggr := r.lggr.Named("AutomationProvider").Named(rargs.ExternalJobID.String()) - ocr2keeperRelayer := NewOCR2KeeperRelayer(r.db, r.chain, lggr.Named("OCR2KeeperRelayer"), r.ks.Eth(), r.pgCfg) + ocr2keeperRelayer := NewOCR2KeeperRelayer(r.ds, r.chain, lggr.Named("OCR2KeeperRelayer"), r.ks.Eth()) return ocr2keeperRelayer.NewOCR2KeeperProvider(rargs, pargs) } diff --git a/core/services/relay/evm/evm_test.go b/core/services/relay/evm/evm_test.go index d53fe910bc3..ab60ff2a128 100644 --- a/core/services/relay/evm/evm_test.go +++ b/core/services/relay/evm/evm_test.go @@ -5,20 +5,13 @@ import ( "github.com/stretchr/testify/assert" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) func TestRelayerOpts_Validate(t *testing.T) { - cfg := configtest.NewTestGeneralConfig(t) type fields struct { - DB *sqlx.DB DS sqlutil.DataSource - QConfig pg.QConfig CSAETHKeystore evm.CSAETHKeystore } tests := []struct { @@ -29,33 +22,25 @@ func TestRelayerOpts_Validate(t *testing.T) { { name: "all invalid", fields: fields{ - DB: nil, DS: nil, - QConfig: nil, CSAETHKeystore: nil, }, - wantErrContains: `nil DB -nil DataSource -nil QConfig + wantErrContains: `nil DataSource nil Keystore`, }, { - name: "missing db, ds, keystore", + name: "missing ds, keystore", fields: fields{ - DB: nil, - QConfig: cfg.Database(), + DS: nil, }, - wantErrContains: `nil DB -nil DataSource + wantErrContains: `nil DataSource nil Keystore`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := evm.RelayerOpts{ - DB: tt.fields.DB, DS: tt.fields.DS, - QConfig: tt.fields.QConfig, CSAETHKeystore: tt.fields.CSAETHKeystore, } err := c.Validate() diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go index 6f49ca91bfc..82a76450e5f 100644 --- a/core/services/relay/evm/mercury/transmitter.go +++ b/core/services/relay/evm/mercury/transmitter.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" @@ -33,12 +34,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils" ) -var ( - maxTransmitQueueSize = 10_000 - maxDeleteQueueSize = 10_000 - transmitTimeout = 5 * time.Second -) - const ( // Mercury server error codes DuplicateReport = 2 @@ -104,9 +99,15 @@ type TransmitterReportDecoder interface { var _ Transmitter = (*mercuryTransmitter)(nil) +type TransmitterConfig interface { + TransmitQueueMaxSize() uint32 + TransmitTimeout() commonconfig.Duration +} + type mercuryTransmitter struct { services.StateMachine lggr logger.Logger + cfg TransmitterConfig servers map[string]*server @@ -142,6 +143,8 @@ func getPayloadTypes() abi.Arguments { type server struct { lggr logger.Logger + transmitTimeout time.Duration + c wsrpc.Client pm *PersistenceManager q *TransmitQueue @@ -221,7 +224,7 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed // queue was closed return } - ctx, cancel := context.WithTimeout(runloopCtx, utils.WithJitter(transmitTimeout)) + ctx, cancel := context.WithTimeout(runloopCtx, utils.WithJitter(s.transmitTimeout)) res, err := s.c.Transmit(ctx, t.Req) cancel() if runloopCtx.Err() != nil { @@ -272,18 +275,19 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed } } -func NewTransmitter(lggr logger.Logger, clients map[string]wsrpc.Client, fromAccount ed25519.PublicKey, jobID int32, feedID [32]byte, orm ORM, codec TransmitterReportDecoder) *mercuryTransmitter { +func NewTransmitter(lggr logger.Logger, cfg TransmitterConfig, clients map[string]wsrpc.Client, fromAccount ed25519.PublicKey, jobID int32, feedID [32]byte, orm ORM, codec TransmitterReportDecoder) *mercuryTransmitter { feedIDHex := fmt.Sprintf("0x%x", feedID[:]) servers := make(map[string]*server, len(clients)) for serverURL, client := range clients { cLggr := lggr.Named(serverURL).With("serverURL", serverURL) - pm := NewPersistenceManager(cLggr, serverURL, orm, jobID, maxTransmitQueueSize, flushDeletesFrequency, pruneFrequency) + pm := NewPersistenceManager(cLggr, serverURL, orm, jobID, int(cfg.TransmitQueueMaxSize()), flushDeletesFrequency, pruneFrequency) servers[serverURL] = &server{ cLggr, + cfg.TransmitTimeout().Duration(), client, pm, - NewTransmitQueue(cLggr, serverURL, feedIDHex, maxTransmitQueueSize, pm), - make(chan *pb.TransmitRequest, maxDeleteQueueSize), + NewTransmitQueue(cLggr, serverURL, feedIDHex, int(cfg.TransmitQueueMaxSize()), pm), + make(chan *pb.TransmitRequest, int(cfg.TransmitQueueMaxSize())), transmitSuccessCount.WithLabelValues(feedIDHex, serverURL), transmitDuplicateCount.WithLabelValues(feedIDHex, serverURL), transmitConnectionErrorCount.WithLabelValues(feedIDHex, serverURL), @@ -295,6 +299,7 @@ func NewTransmitter(lggr logger.Logger, clients map[string]wsrpc.Client, fromAcc return &mercuryTransmitter{ services.StateMachine{}, lggr.Named("MercuryTransmitter").With("feedID", feedIDHex), + cfg, servers, codec, feedID, diff --git a/core/services/relay/evm/mercury/transmitter_test.go b/core/services/relay/evm/mercury/transmitter_test.go index 46bf116ed3a..b0da9bea635 100644 --- a/core/services/relay/evm/mercury/transmitter_test.go +++ b/core/services/relay/evm/mercury/transmitter_test.go @@ -4,6 +4,7 @@ import ( "context" "math/big" "testing" + "time" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" @@ -12,6 +13,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -21,6 +23,16 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" ) +type mockCfg struct{} + +func (m mockCfg) TransmitQueueMaxSize() uint32 { + return 10_000 +} + +func (m mockCfg) TransmitTimeout() commonconfig.Duration { + return *commonconfig.MustNewDuration(1 * time.Hour) +} + func Test_MercuryTransmitter_Transmit(t *testing.T) { lggr := logger.TestLogger(t) db := pgtest.NewSqlxDB(t) @@ -36,7 +48,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV1Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -50,7 +62,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV2Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -64,7 +76,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV3Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -83,7 +95,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { clients[sURL2] = c clients[sURL3] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) mt.servers[sURL2].q.Init([]*Transmission{}) @@ -125,7 +137,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -141,7 +153,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -155,7 +167,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.LatestTimestamp(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -185,7 +197,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { return out, nil }, } - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -228,7 +240,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) t.Run("BenchmarkPriceFromReport succeeds", func(t *testing.T) { codec.val = originalPrice @@ -259,7 +271,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) price, err := mt.LatestPrice(testutils.Context(t), sampleFeedID) require.NoError(t, err) @@ -273,7 +285,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.LatestPrice(testutils.Context(t), sampleFeedID) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -303,7 +315,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) bn, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.NoError(t, err) @@ -319,7 +331,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) bn, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.NoError(t, err) @@ -332,7 +344,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -350,7 +362,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "latestReport failed; mismatched feed IDs, expected: 0x1c916b4aa7e57ca7b68ae1bf45653f56b656fd3aa335ef7fae696b663f1b8472, got: 0x") diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go index 0dd971123c6..78f4b43b43f 100644 --- a/core/services/relay/evm/ocr2keeper.go +++ b/core/services/relay/evm/ocr2keeper.go @@ -27,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -69,17 +68,15 @@ type ocr2keeperRelayer struct { chain legacyevm.Chain lggr logger.Logger ethKeystore keystore.Eth - dbCfg pg.QConfig } // NewOCR2KeeperRelayer is the constructor of ocr2keeperRelayer -func NewOCR2KeeperRelayer(ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth, dbCfg pg.QConfig) OCR2KeeperRelayer { +func NewOCR2KeeperRelayer(ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth) OCR2KeeperRelayer { return &ocr2keeperRelayer{ ds: ds, chain: chain, lggr: lggr, ethKeystore: ethKeystore, - dbCfg: dbCfg, } } diff --git a/core/services/relay/evm/ocr2vrf.go b/core/services/relay/evm/ocr2vrf.go index 07edd1c5ac6..a108151be47 100644 --- a/core/services/relay/evm/ocr2vrf.go +++ b/core/services/relay/evm/ocr2vrf.go @@ -6,8 +6,6 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -44,15 +42,13 @@ var ( // Relayer with added DKG and OCR2VRF provider functions. type ocr2vrfRelayer struct { - db *sqlx.DB chain legacyevm.Chain lggr logger.Logger ethKeystore keystore.Eth } -func NewOCR2VRFRelayer(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth) OCR2VRFRelayer { +func NewOCR2VRFRelayer(chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth) OCR2VRFRelayer { return &ocr2vrfRelayer{ - db: db, chain: chain, lggr: lggr, ethKeystore: ethKeystore, diff --git a/core/services/versioning/orm.go b/core/services/versioning/orm.go index 5a2472eee8e..5f6e3e60222 100644 --- a/core/services/versioning/orm.go +++ b/core/services/versioning/orm.go @@ -23,16 +23,14 @@ type ORM interface { } type orm struct { - ds sqlutil.DataSource - lggr logger.Logger - timeout time.Duration + ds sqlutil.DataSource + lggr logger.Logger } -func NewORM(ds sqlutil.DataSource, lggr logger.Logger, timeout time.Duration) *orm { +func NewORM(ds sqlutil.DataSource, lggr logger.Logger) *orm { return &orm{ - ds: ds, - lggr: lggr.Named("VersioningORM"), - timeout: timeout, + ds: ds, + lggr: lggr.Named("VersioningORM"), } } @@ -47,8 +45,6 @@ func (o *orm) UpsertNodeVersion(ctx context.Context, version NodeVersion) error return errors.Wrapf(err, "%q is not valid semver", version.Version) } - ctx, cancel := context.WithTimeout(ctx, o.timeout) - defer cancel() return sqlutil.TransactDataSource(ctx, o.ds, nil, func(tx sqlutil.DataSource) error { if _, _, err := CheckVersion(ctx, tx, logger.NullLogger, version.Version); err != nil { return err diff --git a/core/services/versioning/orm_test.go b/core/services/versioning/orm_test.go index f655c9c47fe..3504c2bc772 100644 --- a/core/services/versioning/orm_test.go +++ b/core/services/versioning/orm_test.go @@ -10,14 +10,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/static" ) func TestORM_NodeVersion_UpsertNodeVersion(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - orm := NewORM(db, logger.TestLogger(t), pg.DefaultQueryTimeout) + orm := NewORM(db, logger.TestLogger(t)) err := orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8")) require.NoError(t, err) @@ -66,7 +65,7 @@ func Test_Version_CheckVersion(t *testing.T) { lggr := logger.TestLogger(t) - orm := NewORM(db, lggr, pg.DefaultQueryTimeout) + orm := NewORM(db, lggr) err := orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8")) require.NoError(t, err) @@ -101,7 +100,7 @@ func Test_Version_CheckVersion(t *testing.T) { func TestORM_NodeVersion_FindLatestNodeVersion(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - orm := NewORM(db, logger.TestLogger(t), pg.DefaultQueryTimeout) + orm := NewORM(db, logger.TestLogger(t)) // Not Found _, err := orm.FindLatestNodeVersion(ctx) diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index a3962977257..889b19d0e04 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -83,10 +83,10 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv btORM := bridges.NewORM(db) ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) _, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - txm, err := txmgr.NewTxm(db, db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), nil, dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil) + txm, err := txmgr.NewTxm(db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), nil, dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil) orm := headtracker.NewORM(*testutils.FixtureChainID, db) require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(51))) - jrm := job.NewORM(db, prm, btORM, ks, lggr, cfg.Database()) + jrm := job.NewORM(db, prm, btORM, ks, lggr) t.Cleanup(func() { assert.NoError(t, jrm.Close()) }) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{LogBroadcaster: lb, KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) @@ -165,7 +165,8 @@ func setup(t *testing.T) (vrfUniverse, *v1.Listener, job.Job) { vs := testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{PublicKey: vuni.vrfkey.PublicKey.String(), EVMChainID: testutils.FixtureChainID.String()}) jb, err := vrfcommon.ValidatedVRFSpec(vs.Toml()) require.NoError(t, err) - err = vuni.jrm.CreateJob(&jb) + ctx := testutils.Context(t) + err = vuni.jrm.CreateJob(ctx, &jb) require.NoError(t, err) vl, err := vd.ServicesForSpec(testutils.Context(t), jb) require.NoError(t, err) @@ -701,7 +702,8 @@ func Test_VRFV2PlusServiceFailsWhenVRFOwnerProvided(t *testing.T) { toml := "vrfOwnerAddress=\"0xF62fEFb54a0af9D32CDF0Db21C52710844c7eddb\"\n" + vs.Toml() jb, err := vrfcommon.ValidatedVRFSpec(toml) require.NoError(t, err) - err = vuni.jrm.CreateJob(&jb) + ctx := testutils.Context(t) + err = vuni.jrm.CreateJob(ctx, &jb) require.NoError(t, err) _, err = vd.ServicesForSpec(testutils.Context(t), jb) require.Error(t, err) diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go index c28ad9ce3d0..74006639c6e 100644 --- a/core/services/vrf/v1/integration_test.go +++ b/core/services/vrf/v1/integration_test.go @@ -55,10 +55,10 @@ func TestIntegration_VRF_JPV2(t *testing.T) { cu := vrftesthelpers.NewVRFCoordinatorUniverse(t, key1, key2) incomingConfs := 2 app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, cu.Backend, key1, key2) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) jb, vrfKey := createVRFJobRegisterKey(t, cu, app, incomingConfs) - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) _, err := cu.ConsumerContract.TestRequestRandomness(cu.Carol, vrfKey.PublicKey.MustHash(), big.NewInt(100)) @@ -93,12 +93,12 @@ func TestIntegration_VRF_JPV2(t *testing.T) { // stop jobs as to not cause a race condition in geth simulated backend // between job creating new tx and fulfillment logs polling below - require.NoError(t, app.JobSpawner().DeleteJob(jb.ID)) + require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, jb.ID)) // Ensure the eth transaction gets confirmed on chain. gomega.NewWithT(t).Eventually(func() bool { - orm := txmgr.NewTxStore(app.GetSqlxDB(), app.GetLogger()) - uc, err2 := orm.CountUnconfirmedTransactions(testutils.Context(t), key1.Address, testutils.SimulatedChainID) + orm := txmgr.NewTxStore(app.GetDB(), app.GetLogger()) + uc, err2 := orm.CountUnconfirmedTransactions(ctx, key1.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) @@ -116,11 +116,11 @@ func TestIntegration_VRF_JPV2(t *testing.T) { }, testutils.WaitTimeout(t), 500*time.Millisecond).Should(gomega.BeTrue()) // Check that each sending address sent one transaction - n1, err := cu.Backend.PendingNonceAt(testutils.Context(t), key1.Address) + n1, err := cu.Backend.PendingNonceAt(ctx, key1.Address) require.NoError(t, err) require.EqualValues(t, 1, n1) - n2, err := cu.Backend.PendingNonceAt(testutils.Context(t), key2.Address) + n2, err := cu.Backend.PendingNonceAt(ctx, key2.Address) require.NoError(t, err) require.EqualValues(t, 1, n2) }) @@ -142,7 +142,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { cu := vrftesthelpers.NewVRFCoordinatorUniverse(t, key) incomingConfs := 2 app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, cu.Backend, key) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) // Create VRF Job but do not start it yet jb, vrfKey := createVRFJobRegisterKey(t, cu, app, incomingConfs) @@ -155,7 +155,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { // Ensure log poller is ready and has all logs. require.NoError(t, app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Ready()) - require.NoError(t, app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Replay(testutils.Context(t), 1)) + require.NoError(t, app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Replay(ctx, 1)) // Create a VRF request _, err := cu.ConsumerContract.TestRequestRandomness(cu.Carol, @@ -194,7 +194,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { } // Start the VRF Job and wait until it's processed - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) var runs []pipeline.Run gomega.NewWithT(t).Eventually(func() bool { @@ -209,13 +209,13 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { // stop jobs as to not cause a race condition in geth simulated backend // between job creating new tx and fulfillment logs polling below - require.NoError(t, app.JobSpawner().DeleteJob(jb.ID)) - require.NoError(t, app.JobSpawner().DeleteJob(bhsJob.ID)) + require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, jb.ID)) + require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, bhsJob.ID)) // Ensure the eth transaction gets confirmed on chain. gomega.NewWithT(t).Eventually(func() bool { - orm := txmgr.NewTxStore(app.GetSqlxDB(), app.GetLogger()) - uc, err2 := orm.CountUnconfirmedTransactions(testutils.Context(t), key.Address, testutils.SimulatedChainID) + orm := txmgr.NewTxStore(app.GetDB(), app.GetLogger()) + uc, err2 := orm.CountUnconfirmedTransactions(ctx, key.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 }, 5*time.Second, 100*time.Millisecond).Should(gomega.BeTrue()) diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go index ddf5779deb0..c8029403084 100644 --- a/core/services/vrf/v1/listener_v1.go +++ b/core/services/vrf/v1/listener_v1.go @@ -28,7 +28,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/recovery" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -57,7 +56,6 @@ type Listener struct { Coordinator *solidity_vrf_coordinator_interface.VRFCoordinator PipelineRunner pipeline.Runner Job job.Job - Q pg.Q GethKs vrfcommon.GethKeyStore MailMon *mailbox.Monitor ReqLogs *mailbox.Mailbox[log.Broadcast] @@ -285,6 +283,8 @@ func (lsn *Listener) RunHeadListener(unsubscribe func()) { } func (lsn *Listener) RunLogListener(unsubscribes []func(), minConfs uint32) { + ctx, cancel := lsn.ChStop.NewCtx() + defer cancel() lsn.L.Infow("Listening for run requests", "gasLimit", lsn.FeeCfg.LimitDefault(), "minConfs", minConfs) @@ -304,8 +304,6 @@ func (lsn *Listener) RunLogListener(unsubscribes []func(), minConfs uint32) { break } recovery.WrapRecover(lsn.L, func() { - ctx, cancel := lsn.ChStop.NewCtx() - defer cancel() lsn.handleLog(ctx, lb, minConfs) }) } @@ -488,8 +486,7 @@ func (lsn *Listener) ProcessRequest(ctx context.Context, req request) bool { // The VRF pipeline has no async tasks, so we don't need to check for `incomplete` if _, err = lsn.PipelineRunner.Run(ctx, run, lggr, true, func(tx sqlutil.DataSource) error { // Always mark consumed regardless of whether the proof failed or not. - //TODO restore tx https://smartcontract-it.atlassian.net/browse/BCF-2978 - if err = lsn.Chain.LogBroadcaster().MarkConsumed(ctx, nil, req.lb); err != nil { + if err = lsn.Chain.LogBroadcaster().MarkConsumed(ctx, tx, req.lb); err != nil { lggr.Errorw("Failed mark consumed", "err", err) } return nil diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index 2e0554fca96..d61779c5714 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -1207,7 +1207,6 @@ func testSingleConsumerBigGasCallbackSandwich( ownerKey ethkey.KeyV2, uni coordinatorV2UniverseCommon, batchCoordinatorAddress common.Address, - batchEnabled bool, vrfVersion vrfcommon.Version, nativePayment bool, ) { @@ -1324,7 +1323,6 @@ func testSingleConsumerMultipleGasLanes( ownerKey ethkey.KeyV2, uni coordinatorV2UniverseCommon, batchCoordinatorAddress common.Address, - batchEnabled bool, vrfVersion vrfcommon.Version, nativePayment bool, ) { @@ -1694,7 +1692,7 @@ func testMaliciousConsumer( }).Toml() jb, err := vrfcommon.ValidatedVRFSpec(s) require.NoError(t, err) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) time.Sleep(1 * time.Second) @@ -1861,7 +1859,7 @@ func testReplayOldRequestsOnStartUp( jb, err := vrfcommon.ValidatedVRFSpec(spec) require.NoError(t, err) t.Log(jb.VRFSpec.PublicKey.MustHash(), vrfKey.PublicKey.MustHash()) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) // Wait until all jobs are active and listening for logs diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go index b885473e488..53baaa0eda3 100644 --- a/core/services/vrf/v2/integration_v2_plus_test.go +++ b/core/services/vrf/v2/integration_v2_plus_test.go @@ -646,29 +646,13 @@ func TestVRFV2PlusIntegration_SingleConsumer_NeedsTopUp(t *testing.T) { func TestVRFV2PlusIntegration_SingleConsumer_BigGasCallback_Sandwich(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false) - testSingleConsumerBigGasCallbackSandwich( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2Plus, - false, - ) + testSingleConsumerBigGasCallbackSandwich(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2Plus, false) } func TestVRFV2PlusIntegration_SingleConsumer_MultipleGasLanes(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false) - testSingleConsumerMultipleGasLanes( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2Plus, - false, - ) + testSingleConsumerMultipleGasLanes(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2Plus, false) } func TestVRFV2PlusIntegration_SingleConsumer_AlwaysRevertingCallback_StillFulfilled(t *testing.T) { @@ -1178,7 +1162,7 @@ func TestVRFV2PlusIntegration_Migration(t *testing.T) { // Fund gas lane. sendEth(t, ownerKey, uni.backend, key1.Address, 10) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) // Create VRF job using key1 and key2 on the same gas lane. jbs := createVRFJobs( @@ -1234,7 +1218,7 @@ func TestVRFV2PlusIntegration_Migration(t *testing.T) { require.NoError(t, err) linkContractBalance, err := uni.linkContract.BalanceOf(nil, uni.migrationTestCoordinatorAddress) require.NoError(t, err) - balance, err := uni.backend.BalanceAt(testutils.Context(t), uni.migrationTestCoordinatorAddress, nil) + balance, err := uni.backend.BalanceAt(ctx, uni.migrationTestCoordinatorAddress, nil) require.NoError(t, err) require.Equal(t, subV1.Balance(), totalLinkBalance) diff --git a/core/services/vrf/v2/integration_v2_reverted_txns_test.go b/core/services/vrf/v2/integration_v2_reverted_txns_test.go index dfee450b6a2..25e3afcf751 100644 --- a/core/services/vrf/v2/integration_v2_reverted_txns_test.go +++ b/core/services/vrf/v2/integration_v2_reverted_txns_test.go @@ -448,7 +448,7 @@ func createVRFJobsNew( jb, err := vrfcommon.ValidatedVRFSpec(s) t.Log(jb.VRFSpec.PublicKey.MustHash(), vrfkey.PublicKey.MustHash()) require.NoError(t, err) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, coordinator, vrfkey, ptr(gasLanePrices[i].ToInt().Uint64())) jobs = append(jobs, jb) diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 543ec943527..e8d4fd255f7 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -574,7 +574,7 @@ func createVRFJobs( jb, err := vrfcommon.ValidatedVRFSpec(spec) require.NoError(t, err) t.Log(jb.VRFSpec.PublicKey.MustHash(), vrfkey.PublicKey.MustHash()) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) registerProvingKeyHelper(t, uni, coordinator, vrfkey, ptr(gasLanePrices[i].ToInt().Uint64())) jobs = append(jobs, jb) @@ -1427,29 +1427,13 @@ func TestVRFV2Integration_SingleConsumer_NeedsTopUp(t *testing.T) { func TestVRFV2Integration_SingleConsumer_BigGasCallback_Sandwich(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2Universe(t, ownerKey, 1) - testSingleConsumerBigGasCallbackSandwich( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2, - false, - ) + testSingleConsumerBigGasCallbackSandwich(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2, false) } func TestVRFV2Integration_SingleConsumer_MultipleGasLanes(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2Universe(t, ownerKey, 1) - testSingleConsumerMultipleGasLanes( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2, - false, - ) + testSingleConsumerMultipleGasLanes(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2, false) } func TestVRFV2Integration_SingleConsumer_AlwaysRevertingCallback_StillFulfilled(t *testing.T) { diff --git a/core/services/vrf/vrftesthelpers/helpers.go b/core/services/vrf/vrftesthelpers/helpers.go index 77d3f33a653..33ad8470731 100644 --- a/core/services/vrf/vrftesthelpers/helpers.go +++ b/core/services/vrf/vrftesthelpers/helpers.go @@ -74,7 +74,8 @@ func CreateAndStartBHSJob( jb, err := blockhashstore.ValidatedSpec(s.Toml()) require.NoError(t, err) - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + ctx := testutils.Context(t) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) gomega.NewWithT(t).Eventually(func() bool { jbs := app.JobSpawner().ActiveJobs() for _, jb := range jbs { @@ -115,7 +116,8 @@ func CreateAndStartBlockHeaderFeederJob( jb, err := blockheaderfeeder.ValidatedSpec(s.Toml()) require.NoError(t, err) - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + ctx := testutils.Context(t) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) gomega.NewWithT(t).Eventually(func() bool { jbs := app.JobSpawner().ActiveJobs() for _, jb := range jbs { diff --git a/core/services/webhook/authorizer.go b/core/services/webhook/authorizer.go index c745c5d0b09..f5409cfbacc 100644 --- a/core/services/webhook/authorizer.go +++ b/core/services/webhook/authorizer.go @@ -24,29 +24,29 @@ var ( _ Authorizer = &neverAuthorizer{} ) -func NewAuthorizer(db sqlutil.DataSource, user *sessions.User, ei *bridges.ExternalInitiator) Authorizer { +func NewAuthorizer(ds sqlutil.DataSource, user *sessions.User, ei *bridges.ExternalInitiator) Authorizer { if user != nil { return &alwaysAuthorizer{} } else if ei != nil { - return NewEIAuthorizer(db, *ei) + return NewEIAuthorizer(ds, *ei) } return &neverAuthorizer{} } type eiAuthorizer struct { - db sqlutil.DataSource + ds sqlutil.DataSource ei bridges.ExternalInitiator } -func NewEIAuthorizer(db sqlutil.DataSource, ei bridges.ExternalInitiator) *eiAuthorizer { - return &eiAuthorizer{db, ei} +func NewEIAuthorizer(ds sqlutil.DataSource, ei bridges.ExternalInitiator) *eiAuthorizer { + return &eiAuthorizer{ds, ei} } func (ea *eiAuthorizer) CanRun(ctx context.Context, config AuthorizerConfig, jobUUID uuid.UUID) (can bool, err error) { if !config.ExternalInitiatorsEnabled() { return false, nil } - row := ea.db.QueryRowxContext(ctx, ` + row := ea.ds.QueryRowxContext(ctx, ` SELECT EXISTS ( SELECT 1 FROM external_initiator_webhook_specs JOIN jobs ON external_initiator_webhook_specs.webhook_spec_id = jobs.webhook_spec_id diff --git a/core/services/webhook/authorizer_test.go b/core/services/webhook/authorizer_test.go index 82af7c6fcce..202791c26c2 100644 --- a/core/services/webhook/authorizer_test.go +++ b/core/services/webhook/authorizer_test.go @@ -8,9 +8,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/sessions" diff --git a/core/services/webhook/external_initiator_manager.go b/core/services/webhook/external_initiator_manager.go index 0c035abde7a..2f9a176906d 100644 --- a/core/services/webhook/external_initiator_manager.go +++ b/core/services/webhook/external_initiator_manager.go @@ -11,12 +11,9 @@ import ( "github.com/lib/pq" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -27,7 +24,7 @@ import ( type ExternalInitiatorManager interface { Notify(ctx context.Context, webhookSpecID int32) error DeleteJob(ctx context.Context, webhookSpecID int32) error - FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) + FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) } //go:generate mockery --quiet --name HTTPClient --output ./mocks/ --case=underscore @@ -36,25 +33,24 @@ type HTTPClient interface { } type externalInitiatorManager struct { - q pg.Q + ds sqlutil.DataSource httpclient HTTPClient } var _ ExternalInitiatorManager = (*externalInitiatorManager)(nil) // NewExternalInitiatorManager returns the concrete externalInitiatorManager -func NewExternalInitiatorManager(db *sqlx.DB, httpclient HTTPClient, lggr logger.Logger, cfg pg.QConfig) *externalInitiatorManager { - namedLogger := lggr.Named("ExternalInitiatorManager") +func NewExternalInitiatorManager(ds sqlutil.DataSource, httpclient HTTPClient) *externalInitiatorManager { return &externalInitiatorManager{ - q: pg.NewQ(db, namedLogger, cfg), + ds: ds, httpclient: httpclient, } } // Notify sends a POST notification to the External Initiator // responsible for initiating the Job Spec. -func (m externalInitiatorManager) Notify(ctx context.Context, webhookSpecID int32) error { - eiWebhookSpecs, jobID, err := m.Load(webhookSpecID) +func (m *externalInitiatorManager) Notify(ctx context.Context, webhookSpecID int32) error { + eiWebhookSpecs, jobID, err := m.Load(ctx, webhookSpecID) if err != nil { return err } @@ -90,19 +86,21 @@ func (m externalInitiatorManager) Notify(ctx context.Context, webhookSpecID int3 return nil } -func (m externalInitiatorManager) Load(webhookSpecID int32) (eiWebhookSpecs []job.ExternalInitiatorWebhookSpec, jobID uuid.UUID, err error) { - err = m.q.Transaction(func(tx pg.Queryer) error { - if err = tx.Get(&jobID, "SELECT external_job_id FROM jobs WHERE webhook_spec_id = $1", webhookSpecID); err != nil { +func (m *externalInitiatorManager) Load(ctx context.Context, webhookSpecID int32) (eiWebhookSpecs []job.ExternalInitiatorWebhookSpec, jobID uuid.UUID, err error) { + err = sqlutil.Transact(ctx, func(ds sqlutil.DataSource) *externalInitiatorManager { + return NewExternalInitiatorManager(ds, m.httpclient) + }, m.ds, nil, func(tx *externalInitiatorManager) error { + if err = tx.ds.GetContext(ctx, &jobID, "SELECT external_job_id FROM jobs WHERE webhook_spec_id = $1", webhookSpecID); err != nil { if err = errors.Wrapf(err, "failed to load job ID from job for webhook spec with ID %d", webhookSpecID); err != nil { return err } } - if err = tx.Select(&eiWebhookSpecs, "SELECT * FROM external_initiator_webhook_specs WHERE external_initiator_webhook_specs.webhook_spec_id = $1", webhookSpecID); err != nil { + if err = tx.ds.SelectContext(ctx, &eiWebhookSpecs, "SELECT * FROM external_initiator_webhook_specs WHERE external_initiator_webhook_specs.webhook_spec_id = $1", webhookSpecID); err != nil { if err = errors.Wrapf(err, "failed to load external_initiator_webhook_specs for webhook_spec_id %d", webhookSpecID); err != nil { return err } } - if err = m.eagerLoadExternalInitiator(tx, eiWebhookSpecs); err != nil { + if err = tx.eagerLoadExternalInitiator(ctx, eiWebhookSpecs); err != nil { if err = errors.Wrapf(err, "failed to preload ExternalInitiator for webhook_spec_id %d", webhookSpecID); err != nil { return err } @@ -113,7 +111,7 @@ func (m externalInitiatorManager) Load(webhookSpecID int32) (eiWebhookSpecs []jo return } -func (m externalInitiatorManager) eagerLoadExternalInitiator(q pg.Queryer, txs []job.ExternalInitiatorWebhookSpec) error { +func (m *externalInitiatorManager) eagerLoadExternalInitiator(ctx context.Context, txs []job.ExternalInitiatorWebhookSpec) error { var ids []int64 for _, tx := range txs { ids = append(ids, tx.ExternalInitiatorID) @@ -122,7 +120,7 @@ func (m externalInitiatorManager) eagerLoadExternalInitiator(q pg.Queryer, txs [ return nil } var externalInitiators []bridges.ExternalInitiator - if err := sqlx.Select(q, &externalInitiators, `SELECT * FROM external_initiators WHERE external_initiators.id = ANY($1);`, pq.Array(ids)); err != nil { + if err := m.ds.SelectContext(ctx, &externalInitiators, `SELECT * FROM external_initiators WHERE external_initiators.id = ANY($1);`, pq.Array(ids)); err != nil { return err } @@ -137,8 +135,8 @@ func (m externalInitiatorManager) eagerLoadExternalInitiator(q pg.Queryer, txs [ return nil } -func (m externalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID int32) error { - eiWebhookSpecs, jobID, err := m.Load(webhookSpecID) +func (m *externalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID int32) error { + eiWebhookSpecs, jobID, err := m.Load(ctx, webhookSpecID) if err != nil { return err } @@ -166,9 +164,9 @@ func (m externalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID i return nil } -func (m externalInitiatorManager) FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) { +func (m *externalInitiatorManager) FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) { var exi bridges.ExternalInitiator - err := m.q.Get(&exi, "SELECT * FROM external_initiators WHERE lower(external_initiators.name) = lower($1)", name) + err := m.ds.GetContext(ctx, &exi, "SELECT * FROM external_initiators WHERE lower(external_initiators.name) = lower($1)", name) return exi, err } @@ -211,6 +209,6 @@ var _ ExternalInitiatorManager = (*NullExternalInitiatorManager)(nil) func (NullExternalInitiatorManager) Notify(context.Context, int32) error { return nil } func (NullExternalInitiatorManager) DeleteJob(context.Context, int32) error { return nil } -func (NullExternalInitiatorManager) FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) { +func (NullExternalInitiatorManager) FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) { return bridges.ExternalInitiator{}, nil } diff --git a/core/services/webhook/external_initiator_manager_test.go b/core/services/webhook/external_initiator_manager_test.go index 22ab50513cf..a2402b4114d 100644 --- a/core/services/webhook/external_initiator_manager_test.go +++ b/core/services/webhook/external_initiator_manager_test.go @@ -17,15 +17,14 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" _ "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" webhookmocks "github.com/smartcontractkit/chainlink/v2/core/services/webhook/mocks" ) func Test_ExternalInitiatorManager_Load(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) borm := bridges.NewORM(db) eiFoo := cltest.MustInsertExternalInitiator(t, borm) @@ -39,21 +38,21 @@ func Test_ExternalInitiatorManager_Load(t *testing.T) { pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiBar.ID, webhookSpecTwoEIs.ID, `{"ei": "bar", "name": "webhookSpecTwoEIs"}`) pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiFoo.ID, webhookSpecOneEI.ID, `{"ei": "foo", "name": "webhookSpecOneEI"}`) - eim := webhook.NewExternalInitiatorManager(db, nil, logger.TestLogger(t), cfg) + eim := webhook.NewExternalInitiatorManager(db, nil) - eiWebhookSpecs, jobID, err := eim.Load(webhookSpecNoEIs.ID) + eiWebhookSpecs, jobID, err := eim.Load(ctx, webhookSpecNoEIs.ID) require.NoError(t, err) assert.Len(t, eiWebhookSpecs, 0) assert.Equal(t, jb3.ExternalJobID, jobID) - eiWebhookSpecs, jobID, err = eim.Load(webhookSpecOneEI.ID) + eiWebhookSpecs, jobID, err = eim.Load(ctx, webhookSpecOneEI.ID) require.NoError(t, err) assert.Len(t, eiWebhookSpecs, 1) assert.Equal(t, `{"ei": "foo", "name": "webhookSpecOneEI"}`, eiWebhookSpecs[0].Spec.Raw) assert.Equal(t, eiFoo.ID, eiWebhookSpecs[0].ExternalInitiator.ID) assert.Equal(t, jb1.ExternalJobID, jobID) - eiWebhookSpecs, jobID, err = eim.Load(webhookSpecTwoEIs.ID) + eiWebhookSpecs, jobID, err = eim.Load(ctx, webhookSpecTwoEIs.ID) require.NoError(t, err) assert.Len(t, eiWebhookSpecs, 2) assert.Equal(t, jb2.ExternalJobID, jobID) @@ -62,7 +61,6 @@ func Test_ExternalInitiatorManager_Load(t *testing.T) { func Test_ExternalInitiatorManager_Notify(t *testing.T) { ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) borm := bridges.NewORM(db) eiWithURL := cltest.MustInsertExternalInitiatorWithOpts(t, borm, cltest.ExternalInitiatorOpts{ @@ -79,7 +77,7 @@ func Test_ExternalInitiatorManager_Notify(t *testing.T) { pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiNoURL.ID, webhookSpecTwoEIs.ID, `{"ei": "bar", "name": "webhookSpecTwoEIs"}`) client := webhookmocks.NewHTTPClient(t) - eim := webhook.NewExternalInitiatorManager(db, client, logger.TestLogger(t), cfg) + eim := webhook.NewExternalInitiatorManager(db, client) // Does nothing with no EI require.NoError(t, eim.Notify(ctx, webhookSpecNoEIs.ID)) @@ -102,7 +100,6 @@ func Test_ExternalInitiatorManager_Notify(t *testing.T) { func Test_ExternalInitiatorManager_DeleteJob(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) borm := bridges.NewORM(db) eiWithURL := cltest.MustInsertExternalInitiatorWithOpts(t, borm, cltest.ExternalInitiatorOpts{ @@ -119,7 +116,7 @@ func Test_ExternalInitiatorManager_DeleteJob(t *testing.T) { pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiNoURL.ID, webhookSpecTwoEIs.ID, `{"ei": "bar", "name": "webhookSpecTwoEIs"}`) client := webhookmocks.NewHTTPClient(t) - eim := webhook.NewExternalInitiatorManager(db, client, logger.TestLogger(t), cfg) + eim := webhook.NewExternalInitiatorManager(db, client) // Does nothing with no EI require.NoError(t, eim.DeleteJob(ctx, webhookSpecNoEIs.ID)) diff --git a/core/services/webhook/mocks/external_initiator_manager.go b/core/services/webhook/mocks/external_initiator_manager.go index 9711ae686ea..7a3ee29f62f 100644 --- a/core/services/webhook/mocks/external_initiator_manager.go +++ b/core/services/webhook/mocks/external_initiator_manager.go @@ -33,9 +33,9 @@ func (_m *ExternalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID return r0 } -// FindExternalInitiatorByName provides a mock function with given fields: name -func (_m *ExternalInitiatorManager) FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) { - ret := _m.Called(name) +// FindExternalInitiatorByName provides a mock function with given fields: ctx, name +func (_m *ExternalInitiatorManager) FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) { + ret := _m.Called(ctx, name) if len(ret) == 0 { panic("no return value specified for FindExternalInitiatorByName") @@ -43,17 +43,17 @@ func (_m *ExternalInitiatorManager) FindExternalInitiatorByName(name string) (br var r0 bridges.ExternalInitiator var r1 error - if rf, ok := ret.Get(0).(func(string) (bridges.ExternalInitiator, error)); ok { - return rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) (bridges.ExternalInitiator, error)); ok { + return rf(ctx, name) } - if rf, ok := ret.Get(0).(func(string) bridges.ExternalInitiator); ok { - r0 = rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) bridges.ExternalInitiator); ok { + r0 = rf(ctx, name) } else { r0 = ret.Get(0).(bridges.ExternalInitiator) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, name) } else { r1 = ret.Error(1) } diff --git a/core/services/webhook/validate.go b/core/services/webhook/validate.go index 6066a863ff7..a6d6aa72e83 100644 --- a/core/services/webhook/validate.go +++ b/core/services/webhook/validate.go @@ -1,6 +1,8 @@ package webhook import ( + "context" + "github.com/pelletier/go-toml" "github.com/pkg/errors" "go.uber.org/multierr" @@ -18,7 +20,7 @@ type TOMLWebhookSpec struct { ExternalInitiators []TOMLWebhookSpecExternalInitiator `toml:"externalInitiators"` } -func ValidatedWebhookSpec(tomlString string, externalInitiatorManager ExternalInitiatorManager) (jb job.Job, err error) { +func ValidatedWebhookSpec(ctx context.Context, tomlString string, externalInitiatorManager ExternalInitiatorManager) (jb job.Job, err error) { var tree *toml.Tree tree, err = toml.Load(tomlString) if err != nil { @@ -40,7 +42,7 @@ func ValidatedWebhookSpec(tomlString string, externalInitiatorManager ExternalIn var externalInitiatorWebhookSpecs []job.ExternalInitiatorWebhookSpec for _, eiSpec := range tomlSpec.ExternalInitiators { - ei, findErr := externalInitiatorManager.FindExternalInitiatorByName(eiSpec.Name) + ei, findErr := externalInitiatorManager.FindExternalInitiatorByName(ctx, eiSpec.Name) if findErr != nil { err = multierr.Combine(err, errors.Wrapf(findErr, "unable to find external initiator named %s", eiSpec.Name)) continue diff --git a/core/services/webhook/validate_test.go b/core/services/webhook/validate_test.go index f6993f6aefe..8d398fc0b68 100644 --- a/core/services/webhook/validate_test.go +++ b/core/services/webhook/validate_test.go @@ -6,9 +6,11 @@ import ( "github.com/manyminds/api2go/jsonapi" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" webhookmocks "github.com/smartcontractkit/chainlink/v2/core/services/webhook/mocks" @@ -96,8 +98,8 @@ func TestValidatedWebJobSpec(t *testing.T) { """ `, mock: func(t *testing.T, eim *webhookmocks.ExternalInitiatorManager) { - eim.On("FindExternalInitiatorByName", "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() - eim.On("FindExternalInitiatorByName", "bar").Return(bridges.ExternalInitiator{ID: 43}, nil).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "bar").Return(bridges.ExternalInitiator{ID: 43}, nil).Once() }, assertion: func(t *testing.T, s job.Job, err error) { require.NoError(t, err) @@ -134,9 +136,9 @@ func TestValidatedWebJobSpec(t *testing.T) { """ `, mock: func(t *testing.T, eim *webhookmocks.ExternalInitiatorManager) { - eim.On("FindExternalInitiatorByName", "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() - eim.On("FindExternalInitiatorByName", "bar").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() - eim.On("FindExternalInitiatorByName", "baz").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "bar").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "baz").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() }, assertion: func(t *testing.T, s job.Job, err error) { require.EqualError(t, err, "unable to find external initiator named bar: something exploded; unable to find external initiator named baz: something exploded") @@ -147,11 +149,12 @@ func TestValidatedWebJobSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) eim := new(webhookmocks.ExternalInitiatorManager) if tc.mock != nil { tc.mock(t, eim) } - s, err := webhook.ValidatedWebhookSpec(tc.toml, eim) + s, err := webhook.ValidatedWebhookSpec(ctx, tc.toml, eim) tc.assertion(t, s, err) }) } diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index e22a78212d2..8dc440da477 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -2,22 +2,26 @@ package workflows import ( "context" + "encoding/hex" "fmt" "github.com/google/uuid" "github.com/pelletier/go-toml" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) type Delegate struct { registry core.CapabilitiesRegistry logger logger.Logger legacyEVMChains legacyevm.LegacyChainContainer + peerID func() *p2ptypes.PeerID } var _ job.Delegate = (*Delegate)(nil) @@ -42,11 +46,18 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser d.logger.Errorw("could not initialize writes", err) } + dinfo, err := initializeDONInfo(d.logger) + if err != nil { + d.logger.Errorw("could not add initialize don info", err) + } + cfg := Config{ Lggr: d.logger, Spec: spec.WorkflowSpec.Workflow, WorkflowID: spec.WorkflowSpec.WorkflowID, Registry: d.registry, + DONInfo: dinfo, + PeerID: d.peerID, } engine, err := NewEngine(cfg) if err != nil { @@ -55,8 +66,45 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser return []job.ServiceCtx{engine}, nil } -func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer) *Delegate { - return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains} +func initializeDONInfo(lggr logger.Logger) (*capabilities.DON, error) { + var key [16]byte + + // TODO: fetch the key and DONInfo from the registry + keyString := "44fb5c1ee8ee48846c808a383da3aba3" + k, err := hex.DecodeString(keyString) + if err != nil { + lggr.Errorf("could not decode key %s: %w", keyString, err) + } + key = [16]byte(k) + + p2pStrings := []string{ + "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", + "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", + "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", + "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", + } + + p2pIDs := []p2ptypes.PeerID{} + for _, p := range p2pStrings { + pid := p2ptypes.PeerID{} + err := pid.UnmarshalText([]byte(p)) + if err != nil { + return nil, err + } + + p2pIDs = append(p2pIDs, pid) + } + + return &capabilities.DON{ + Members: p2pIDs, + Config: capabilities.DONConfig{ + SharedSecret: key, + }, + }, nil +} + +func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, peerID func() *p2ptypes.PeerID) *Delegate { + return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains, peerID: peerID} } func ValidatedWorkflowSpec(tomlString string) (job.Job, error) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 052c2c86647..0ecc311acac 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) const ( @@ -21,12 +22,18 @@ const ( mockedWorkflowID = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" ) +type donInfo struct { + *capabilities.DON + PeerID func() *p2ptypes.PeerID +} + // Engine handles the lifecycle of a single workflow and its executions. type Engine struct { services.StateMachine logger logger.Logger registry core.CapabilitiesRegistry workflow *workflow + donInfo donInfo executionStates *inMemoryStore pendingStepRequests chan stepRequest triggerEvents chan capabilities.CapabilityResponse @@ -88,7 +95,11 @@ LOOP: continue } - // Walk the graph and register each step's capability to this workflow + // Walk the graph and initialize each step. + // This means: + // - fetching the capability + // - register the capability to this workflow + // - initializing the step's executionStrategy err := e.workflow.walkDo(keywordTrigger, func(s *step) error { // The graph contains a dummy step for triggers, but // we handle triggers separately since there might be more than one. @@ -96,45 +107,12 @@ LOOP: return nil } - // If the capability already exists, that means we've already registered it - if s.capability != nil { - return nil - } - - cp, innerErr := e.registry.Get(ctx, s.Type) - if innerErr != nil { - return fmt.Errorf("failed to get capability with ref %s: %s, retrying in %d seconds", s.Type, innerErr, retrySec) - } - - // We only need to configure actions, consensus and targets here, and - // they all satisfy the `CallbackExecutable` interface - cc, ok := cp.(capabilities.CallbackExecutable) - if !ok { - return fmt.Errorf("could not coerce capability %s to CallbackExecutable", s.Type) - } - - if s.config == nil { - configMap, ierr := values.NewMap(s.Config) - if ierr != nil { - return fmt.Errorf("failed to convert config to values.Map: %s", ierr) - } - s.config = configMap - } - - reg := capabilities.RegisterToWorkflowRequest{ - Metadata: capabilities.RegistrationMetadata{ - WorkflowID: e.workflow.id, - }, - Config: s.config, - } - - innerErr = cc.RegisterToWorkflow(ctx, reg) - if innerErr != nil { - return fmt.Errorf("failed to register to workflow (%+v): %w", reg, innerErr) + err := e.initializeCapability(ctx, s, retrySec) + if err != nil { + return err } - s.capability = cc - return nil + return e.initializeExecutionStrategy(s) }) if err != nil { initSuccessful = false @@ -158,6 +136,101 @@ LOOP: e.logger.Info("engine initialized") } +func (e *Engine) initializeCapability(ctx context.Context, s *step, retrySec int) error { + // If the capability already exists, that means we've already registered it + if s.capability != nil { + return nil + } + + cp, innerErr := e.registry.Get(ctx, s.Type) + if innerErr != nil { + return fmt.Errorf("failed to get capability with ref %s: %s, retrying in %d seconds", s.Type, innerErr, retrySec) + } + + // We only need to configure actions, consensus and targets here, and + // they all satisfy the `CallbackCapability` interface + cc, ok := cp.(capabilities.CallbackCapability) + if !ok { + return fmt.Errorf("could not coerce capability %s to CallbackCapability", s.Type) + } + + if s.config == nil { + configMap, ierr := values.NewMap(s.Config) + if ierr != nil { + return fmt.Errorf("failed to convert config to values.Map: %s", ierr) + } + s.config = configMap + } + + reg := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: e.workflow.id, + }, + Config: s.config, + } + + innerErr = cc.RegisterToWorkflow(ctx, reg) + if innerErr != nil { + return fmt.Errorf("failed to register to workflow (%+v): %w", reg, innerErr) + } + + s.capability = cc + return nil +} + +// initializeExecutionStrategy for `step`. +// Broadly speaking, we'll use `immediateExecution` for non-target steps +// and `scheduledExecution` for targets. If we don't have the necessary +// config to initialize a scheduledExecution for a target, we'll fallback to +// using `immediateExecution`. +func (e *Engine) initializeExecutionStrategy(step *step) error { + if step.executionStrategy != nil { + return nil + } + + // If donInfo has no peerID, then the peer wrapper hasn't been initialized. + // Let's error and try again next time around. + if e.donInfo.PeerID() == nil { + return fmt.Errorf("failed to initialize execution strategy: peer ID %s has not been initialized", e.donInfo.PeerID()) + } + + ie := immediateExecution{} + if step.CapabilityType != capabilities.CapabilityTypeTarget { + e.logger.Debugf("initializing step %+v with immediate execution strategy: not a target", step) + step.executionStrategy = ie + return nil + } + + dinfo := e.donInfo + if dinfo.DON == nil { + e.logger.Debugf("initializing target step with immediate execution strategy: donInfo %+v", e.donInfo) + step.executionStrategy = ie + return nil + } + + var position *int + for i, w := range dinfo.Members { + if w == *dinfo.PeerID() { + idx := i + position = &idx + } + } + + if position == nil { + e.logger.Debugf("initializing step %+v with immediate execution strategy: position not found in donInfo %+v", step, e.donInfo) + step.executionStrategy = ie + return nil + } + + step.executionStrategy = scheduledExecution{ + DON: e.donInfo.DON, + Position: *position, + PeerID: e.donInfo.PeerID(), + } + e.logger.Debugf("initializing step %+v with scheduled execution strategy", step) + return nil +} + // registerTrigger is used during the initialization phase to bind a trigger to this workflow func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability) error { triggerInputs, err := values.NewMap( @@ -436,20 +509,24 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { defer func() { e.newWorkerCh <- struct{}{} }() defer e.wg.Done() - e.logger.Debugw("executing on a step event", "stepRef", msg.stepRef, "executionID", msg.state.executionID) + // Instantiate a child logger; in addition to the WorkflowID field the workflow + // logger will already have, this adds the `stepRef` and `executionID` + l := e.logger.With("stepRef", msg.stepRef, "executionID", msg.state.executionID) + + l.Debugw("executing on a step event") stepState := &stepState{ outputs: &stepOutput{}, executionID: msg.state.executionID, ref: msg.stepRef, } - inputs, outputs, err := e.executeStep(ctx, msg) + inputs, outputs, err := e.executeStep(ctx, l, msg) if err != nil { - e.logger.Errorf("error executing step request: %s", err, "executionID", msg.state.executionID, "stepRef", msg.stepRef) + l.Errorf("error executing step request: %s", err) stepState.outputs.err = err stepState.status = statusErrored } else { - e.logger.Infow("step executed successfully", "executionID", msg.state.executionID, "stepRef", msg.stepRef, "outputs", outputs) + l.Infow("step executed successfully", "outputs", outputs) stepState.outputs.value = outputs stepState.status = statusCompleted } @@ -464,13 +541,13 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // like this one will get picked up again and will be reprocessed. select { case <-ctx.Done(): - e.logger.Errorf("context canceled before step update could be issued", err, "executionID", msg.state.executionID, "stepRef", msg.stepRef) + l.Errorf("context canceled before step update could be issued", err) case e.stepUpdateCh <- *stepState: } } // executeStep executes the referenced capability within a step and returns the result. -func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, values.Value, error) { +func (e *Engine) executeStep(ctx context.Context, l logger.Logger, msg stepRequest) (*values.Map, values.Value, error) { step, err := e.workflow.Vertex(msg.stepRef) if err != nil { return nil, nil, err @@ -495,18 +572,12 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, }, } - resp, err := capabilities.ExecuteSync(ctx, step.capability, tr) + output, err := step.executionStrategy.Apply(ctx, l, step.capability, tr) if err != nil { return inputs, nil, err } - // `ExecuteSync` returns a `values.List` even if there was - // just one return value. If that is the case, let's unwrap the - // single value to make it easier to use in -- for example -- variable interpolation. - if len(resp.Underlying) > 1 { - return inputs, resp, err - } - return inputs, resp.Underlying[0], err + return inputs, output, err } func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability) error { @@ -595,6 +666,8 @@ type Config struct { MaxWorkerLimit int QueueSize int NewWorkerTimeout time.Duration + DONInfo *capabilities.DON + PeerID func() *p2ptypes.PeerID } const ( @@ -638,9 +711,13 @@ func NewEngine(cfg Config) (engine *Engine, err error) { } engine = &Engine{ - logger: cfg.Lggr.Named("WorkflowEngine"), - registry: cfg.Registry, - workflow: workflow, + logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), + registry: cfg.Registry, + workflow: workflow, + donInfo: donInfo{ + DON: cfg.DONInfo, + PeerID: cfg.PeerID, + }, executionStates: newInMemoryStore(), pendingStepRequests: make(chan stepRequest, cfg.QueueSize), newWorkerCh: newWorkerCh, diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 7bb6cd00c1c..d82c9d4b7d2 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -14,6 +14,7 @@ import ( coreCap "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) const hardcodedWorkflow = ` @@ -136,6 +137,7 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { capabilities.CapabilityTypeTarget, "a write capability targeting ethereum sepolia testnet", "v1.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { m := req.Inputs.Underlying["report"].(*values.Map) @@ -147,10 +149,13 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { require.NoError(t, reg.Add(ctx, target2)) lggr := logger.TestLogger(t) + peerID := p2ptypes.PeerID{} cfg := Config{ Lggr: lggr, Registry: reg, Spec: hardcodedWorkflow, + DONInfo: nil, + PeerID: func() *p2ptypes.PeerID { return &peerID }, } eng, err := NewEngine(cfg) require.NoError(t, err) @@ -219,6 +224,7 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Cap capabilities.CapabilityTypeTrigger, "issues a trigger when a mercury report is received.", "v1.0.0", + nil, ), ch: make(chan capabilities.CapabilityResponse, 10), } @@ -242,6 +248,7 @@ func mockFailingConsensus() *mockCapability { capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", "v3.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { return capabilities.CapabilityResponse{}, errors.New("fatal consensus error") @@ -256,6 +263,7 @@ func mockConsensus() *mockCapability { capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", "v3.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { obs := req.Inputs.Underlying["observations"] @@ -282,6 +290,7 @@ func mockTarget() *mockCapability { capabilities.CapabilityTypeTarget, "a write capability targeting polygon mumbai testnet", "v1.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { m := req.Inputs.Underlying["report"].(*values.Map) @@ -303,10 +312,13 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { require.NoError(t, reg.Add(ctx, mockFailingConsensus())) require.NoError(t, reg.Add(ctx, mockTarget())) + peerID := p2ptypes.PeerID{} cfg := Config{ Lggr: logger.TestLogger(t), Registry: reg, Spec: simpleWorkflow, + DONInfo: nil, + PeerID: func() *p2ptypes.PeerID { return &peerID }, } eng, err := NewEngine(cfg) require.NoError(t, err) @@ -383,6 +395,7 @@ func mockAction() (*mockCapability, values.Value) { capabilities.CapabilityTypeAction, "a read chain action", "v1.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { @@ -407,10 +420,13 @@ func TestEngine_MultiStepDependencies(t *testing.T) { action, out := mockAction() require.NoError(t, reg.Add(ctx, action)) + peerID := p2ptypes.PeerID{} cfg := Config{ Lggr: logger.TestLogger(t), Registry: reg, Spec: multiStepWorkflow, + DONInfo: nil, + PeerID: func() *p2ptypes.PeerID { return &peerID }, } eng, err := NewEngine(cfg) require.NoError(t, err) diff --git a/core/services/workflows/execution_strategy.go b/core/services/workflows/execution_strategy.go new file mode 100644 index 00000000000..f5da8bca4be --- /dev/null +++ b/core/services/workflows/execution_strategy.go @@ -0,0 +1,171 @@ +package workflows + +import ( + "context" + "fmt" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + + "github.com/smartcontractkit/libocr/permutation" + + "golang.org/x/crypto/sha3" +) + +type executionStrategy interface { + Apply(ctx context.Context, l logger.Logger, cap capabilities.CallbackCapability, req capabilities.CapabilityRequest) (values.Value, error) +} + +var _ executionStrategy = immediateExecution{} + +type immediateExecution struct{} + +func (i immediateExecution) Apply(ctx context.Context, lggr logger.Logger, cap capabilities.CallbackCapability, req capabilities.CapabilityRequest) (values.Value, error) { + l, err := capabilities.ExecuteSync(ctx, cap, req) + if err != nil { + return nil, err + } + + // `ExecuteSync` returns a `values.List` even if there was + // just one return value. If that is the case, let's unwrap the + // single value to make it easier to use in -- for example -- variable interpolation. + if len(l.Underlying) > 1 { + return l, nil + } + + return l.Underlying[0], nil +} + +var _ executionStrategy = scheduledExecution{} + +type scheduledExecution struct { + DON *capabilities.DON + PeerID *p2ptypes.PeerID + Position int +} + +var ( + // S = [N] + Schedule_AllAtOnce = "allAtOnce" + // S = [1 * N] + Schedule_OneAtATime = "oneAtATime" +) + +// scheduledExecution generates a pseudo-random transmission schedule, +// and delays execution until a node is required to transmit. +func (d scheduledExecution) Apply(ctx context.Context, lggr logger.Logger, cap capabilities.CallbackCapability, req capabilities.CapabilityRequest) (values.Value, error) { + tc, err := d.transmissionConfig(req.Config) + if err != nil { + return nil, err + } + + info, err := cap.Info(ctx) + if err != nil { + return nil, err + } + + switch { + // Case 1: Local DON + case info.DON == nil: + n := len(d.DON.Members) + key := d.key(d.DON.Config.SharedSecret, req.Metadata.WorkflowID, req.Metadata.WorkflowExecutionID) + sched, err := schedule(tc.Schedule, n) + if err != nil { + return nil, err + } + + picked := permutation.Permutation(n, key) + delay := d.delayFor(d.Position, sched, picked, tc.DeltaStage) + if delay == nil { + lggr.Debugw("skipping transmission: node is not included in schedule") + return nil, nil + } + + lggr.Debugf("execution delayed by %+v", *delay) + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(*delay): + lggr.Debugw("executing delayed execution") + return immediateExecution{}.Apply(ctx, lggr, cap, req) + } + // Case 2: Remote DON + default: + // TODO: fill in the remote DON case once consensus has been reach on what to do. + lggr.Debugw("remote DON transmission not implemented: using immediate execution") + return immediateExecution{}.Apply(ctx, lggr, cap, req) + } +} + +// `key` uses a shared secret, combined with a workflowID and a workflowExecutionID to generate +// a secret that can later be used to pseudo-randomly determine a schedule for a set of nodes in a DON. +// The addition of the workflowExecutionID -- which nodes don't know ahead of time -- additionally guarantees +// that a malicious coalition of nodes can't "game" the schedule. +// IMPORTANT: changing this function should happen carefully to maintain the guarantee that all nodes +// arrive at the same secret. +func (d scheduledExecution) key(sharedSecret [16]byte, workflowID, workflowExecutionID string) [16]byte { + hash := sha3.NewLegacyKeccak256() + hash.Write(sharedSecret[:]) + hash.Write([]byte(workflowID)) + hash.Write([]byte(workflowExecutionID)) + + var key [16]byte + copy(key[:], hash.Sum(nil)) + return key +} + +type transmissionConfig struct { + Schedule string + DeltaStage time.Duration +} + +func (d scheduledExecution) transmissionConfig(config *values.Map) (transmissionConfig, error) { + var tc struct { + DeltaStage string + Schedule string + } + err := config.UnwrapTo(&tc) + if err != nil { + return transmissionConfig{}, err + } + + duration, err := time.ParseDuration(tc.DeltaStage) + if err != nil { + return transmissionConfig{}, fmt.Errorf("failed to parse DeltaStage %s as duration: %w", tc.DeltaStage, err) + } + + return transmissionConfig{ + Schedule: tc.Schedule, + DeltaStage: duration, + }, nil +} + +func (d scheduledExecution) delayFor(position int, schedule []int, permutation []int, deltaStage time.Duration) *time.Duration { + sum := 0 + for i, s := range schedule { + sum += s + if permutation[position] < sum { + result := time.Duration(i) * deltaStage + return &result + } + } + + return nil +} + +func schedule(sched string, N int) ([]int, error) { + switch sched { + case Schedule_AllAtOnce: + return []int{N}, nil + case Schedule_OneAtATime: + sch := []int{} + for i := 0; i < N; i++ { + sch = append(sch, 1) + } + return sch, nil + } + return nil, fmt.Errorf("unknown schedule %s", sched) +} diff --git a/core/services/workflows/execution_strategy_test.go b/core/services/workflows/execution_strategy_test.go new file mode 100644 index 00000000000..bdf782c87b9 --- /dev/null +++ b/core/services/workflows/execution_strategy_test.go @@ -0,0 +1,170 @@ +package workflows + +import ( + "crypto/rand" + "encoding/hex" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +func assertBetween(t *testing.T, got time.Duration, low time.Duration, high time.Duration) { + assert.GreaterOrEqual(t, got, low) + assert.LessOrEqual(t, got, high) +} + +func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { + var gotTime time.Time + var called bool + + // Our capability has DONInfo == nil, so we'll treat it as a local + // capability and use the local DON Info to determine the transmission + // schedule. + mt := newMockCapability( + capabilities.MustNewCapabilityInfo( + "write_polygon-testnet-mumbai", + capabilities.CapabilityTypeTarget, + "a write capability targeting polygon mumbai testnet", + "v1.0.0", + nil, + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + gotTime = time.Now() + called = true + return capabilities.CapabilityResponse{}, nil + }, + ) + + l := logger.TestLogger(t) + + // The combination of this key and the metadata above + // will yield the permutation [3, 2, 0, 1] + key, err := hex.DecodeString("fb13ca015a9ec60089c7141e9522de79") + require.NoError(t, err) + + testCases := []struct { + name string + position int + schedule string + low time.Duration + high time.Duration + }{ + { + name: "position 0; oneAtATime", + position: 0, + schedule: "oneAtATime", + low: 300 * time.Millisecond, + high: 400 * time.Millisecond, + }, + { + name: "position 1; oneAtATime", + position: 1, + schedule: "oneAtATime", + low: 200 * time.Millisecond, + high: 300 * time.Millisecond, + }, + { + name: "position 2; oneAtATime", + position: 2, + schedule: "oneAtATime", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 3; oneAtATime", + position: 3, + schedule: "oneAtATime", + low: 100 * time.Millisecond, + high: 200 * time.Millisecond, + }, + { + name: "position 0; allAtOnce", + position: 0, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 1; allAtOnce", + position: 1, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 2; allAtOnce", + position: 2, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 3; allAtOnce", + position: 3, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + startTime := time.Now() + + m, err := values.NewMap(map[string]any{ + "schedule": tc.schedule, + "deltaStage": "100ms", + }) + require.NoError(t, err) + + req := capabilities.CapabilityRequest{ + Config: m, + Metadata: capabilities.RequestMetadata{ + WorkflowID: "mock-workflow-id", + WorkflowExecutionID: "mock-execution-id", + }, + } + + ids := []p2ptypes.PeerID{ + randKey(), + randKey(), + randKey(), + randKey(), + } + don := &capabilities.DON{ + Members: ids, + Config: capabilities.DONConfig{ + SharedSecret: [16]byte(key), + }, + } + peerID := ids[tc.position] + de := scheduledExecution{ + DON: don, + PeerID: &peerID, + Position: tc.position, + } + _, err = de.Apply(tests.Context(t), l, mt, req) + require.NoError(t, err) + require.True(t, called) + + assertBetween(t, gotTime.Sub(startTime), tc.low, tc.high) + }) + } +} + +func randKey() [32]byte { + key := make([]byte, 32) + _, err := rand.Read(key) + if err != nil { + panic(err) + } + return [32]byte(key) +} diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index e6c92a641e4..92abf36d2c0 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -19,10 +19,13 @@ type stepRequest struct { // // Within the workflow spec, they are called "Capability Properties". type stepDefinition struct { + // TODO: Rename this, type here refers to the capability ID, not its type. Type string `json:"type" jsonschema:"required"` Ref string `json:"ref,omitempty" jsonschema:"pattern=^[a-z0-9_]+$"` Inputs map[string]any `json:"inputs,omitempty"` Config map[string]any `json:"config" jsonschema:"required"` + + CapabilityType capabilities.CapabilityType `json:"-"` } // workflowSpec is the parsed representation of a workflow. @@ -106,9 +109,10 @@ func (w *workflow) dependents(start string) ([]*step, error) { // step wraps a stepDefinition with additional context for dependencies and execution type step struct { stepDefinition - dependencies []string - capability capabilities.CallbackExecutable - config *values.Map + dependencies []string + capability capabilities.CallbackCapability + config *values.Map + executionStrategy executionStrategy } type triggerCapability struct { diff --git a/core/services/workflows/models_yaml.go b/core/services/workflows/models_yaml.go index 396811c3729..3d65e24a814 100644 --- a/core/services/workflows/models_yaml.go +++ b/core/services/workflows/models_yaml.go @@ -10,6 +10,8 @@ import ( "github.com/invopop/jsonschema" "github.com/shopspring/decimal" "sigs.k8s.io/yaml" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" ) func GenerateJsonSchema() ([]byte, error) { @@ -47,22 +49,30 @@ type workflowSpecYaml struct { func (w workflowSpecYaml) toWorkflowSpec() workflowSpec { triggers := make([]stepDefinition, 0, len(w.Triggers)) for _, t := range w.Triggers { - triggers = append(triggers, t.toStepDefinition()) + sd := t.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeTrigger + triggers = append(triggers, sd) } actions := make([]stepDefinition, 0, len(w.Actions)) for _, a := range w.Actions { - actions = append(actions, a.toStepDefinition()) + sd := a.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeAction + actions = append(actions, sd) } consensus := make([]stepDefinition, 0, len(w.Consensus)) for _, c := range w.Consensus { - consensus = append(consensus, c.toStepDefinition()) + sd := c.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeConsensus + consensus = append(consensus, sd) } targets := make([]stepDefinition, 0, len(w.Targets)) for _, t := range w.Targets { - targets = append(targets, t.toStepDefinition()) + sd := t.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeTarget + targets = append(targets, sd) } return workflowSpec{ diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json index dfa13449a48..f4024e24267 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json @@ -28,4 +28,4 @@ "config": {} } ] -} \ No newline at end of file +} diff --git a/core/sessions/ldapauth/sync.go b/core/sessions/ldapauth/sync.go index 74c606a9684..a6e0366e21d 100644 --- a/core/sessions/ldapauth/sync.go +++ b/core/sessions/ldapauth/sync.go @@ -1,23 +1,23 @@ package ldapauth import ( + "context" "errors" "fmt" "time" "github.com/go-ldap/ldap/v3" - "github.com/jmoiron/sqlx" "github.com/lib/pq" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/sessions" ) type LDAPServerStateSyncer struct { - q pg.Q + ds sqlutil.DataSource ldapClient LDAPClient config config.LDAP lggr logger.Logger @@ -26,14 +26,13 @@ type LDAPServerStateSyncer struct { // NewLDAPServerStateSync creates a reaper that cleans stale sessions from the store. func NewLDAPServerStateSync( - db *sqlx.DB, - pgCfg pg.QConfig, + ds sqlutil.DataSource, config config.LDAP, lggr logger.Logger, ) *utils.SleeperTask { namedLogger := lggr.Named("LDAPServerStateSync") serverSync := LDAPServerStateSyncer{ - q: pg.NewQ(db, namedLogger, pgCfg), + ds: ds, ldapClient: newLDAPClient(config), config: config, lggr: namedLogger, @@ -65,14 +64,15 @@ func (ldSync *LDAPServerStateSyncer) StartWorkOnTimer() { } func (ldSync *LDAPServerStateSyncer) Work() { + ctx := context.Background() // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 // Purge expired ldap_sessions and ldap_user_api_tokens recordCreationStaleThreshold := ldSync.config.SessionTimeout().Before(time.Now()) - err := ldSync.deleteStaleSessions(recordCreationStaleThreshold) + err := ldSync.deleteStaleSessions(ctx, recordCreationStaleThreshold) if err != nil { ldSync.lggr.Error("unable to expire local LDAP sessions: ", err) } recordCreationStaleThreshold = ldSync.config.UserAPITokenDuration().Before(time.Now()) - err = ldSync.deleteStaleAPITokens(recordCreationStaleThreshold) + err = ldSync.deleteStaleAPITokens(ctx, recordCreationStaleThreshold) if err != nil { ldSync.lggr.Error("unable to expire user API tokens: ", err) } @@ -160,18 +160,18 @@ func (ldSync *LDAPServerStateSyncer) Work() { // upstreamUserStateMap is now the most up to date source of truth // Now sync database sessions and roles with new data - err = ldSync.q.Transaction(func(tx pg.Queryer) error { + err = sqlutil.TransactDataSource(ctx, ldSync.ds, nil, func(tx sqlutil.DataSource) error { // First, purge users present in the local ldap_sessions table but not in the upstream server type LDAPSession struct { UserEmail string UserRole sessions.UserRole } var existingSessions []LDAPSession - if err = tx.Select(&existingSessions, "SELECT user_email, user_role FROM ldap_sessions WHERE localauth_user = false"); err != nil { + if err = tx.SelectContext(ctx, &existingSessions, "SELECT user_email, user_role FROM ldap_sessions WHERE localauth_user = false"); err != nil { return fmt.Errorf("unable to query ldap_sessions table: %w", err) } var existingAPITokens []LDAPSession - if err = tx.Select(&existingAPITokens, "SELECT user_email, user_role FROM ldap_user_api_tokens WHERE localauth_user = false"); err != nil { + if err = tx.SelectContext(ctx, &existingAPITokens, "SELECT user_email, user_role FROM ldap_user_api_tokens WHERE localauth_user = false"); err != nil { return fmt.Errorf("unable to query ldap_user_api_tokens table: %w", err) } @@ -202,7 +202,7 @@ func (ldSync *LDAPServerStateSyncer) Work() { // Remove any active sessions this user may have if len(emailsToPurge) > 0 { - _, err = ldSync.q.Exec("DELETE FROM ldap_sessions WHERE user_email = ANY($1)", pq.Array(emailsToPurge)) + _, err = tx.ExecContext(ctx, "DELETE FROM ldap_sessions WHERE user_email = ANY($1)", pq.Array(emailsToPurge)) if err != nil { return err } @@ -210,7 +210,7 @@ func (ldSync *LDAPServerStateSyncer) Work() { // Remove any active API tokens this user may have if len(apiTokenEmailsToPurge) > 0 { - _, err = ldSync.q.Exec("DELETE FROM ldap_user_api_tokens WHERE user_email = ANY($1)", pq.Array(apiTokenEmailsToPurge)) + _, err = tx.ExecContext(ctx, "DELETE FROM ldap_user_api_tokens WHERE user_email = ANY($1)", pq.Array(apiTokenEmailsToPurge)) if err != nil { return err } @@ -235,14 +235,14 @@ func (ldSync *LDAPServerStateSyncer) Work() { if len(emailValues) != 0 { // Set new role state for all rows in single Exec query := fmt.Sprintf("UPDATE ldap_sessions SET user_role = CASE %s ELSE user_role END", queryWhenClause) - _, err = ldSync.q.Exec(query, emailValues...) + _, err = tx.ExecContext(ctx, query, emailValues...) if err != nil { return err } // Update role of API tokens as well query = fmt.Sprintf("UPDATE ldap_user_api_tokens SET user_role = CASE %s ELSE user_role END", queryWhenClause) - _, err = ldSync.q.Exec(query, emailValues...) + _, err = tx.ExecContext(ctx, query, emailValues...) if err != nil { return err } @@ -258,14 +258,14 @@ func (ldSync *LDAPServerStateSyncer) Work() { } // deleteStaleSessions deletes all ldap_sessions before the passed time. -func (ldSync *LDAPServerStateSyncer) deleteStaleSessions(before time.Time) error { - _, err := ldSync.q.Exec("DELETE FROM ldap_sessions WHERE created_at < $1", before) +func (ldSync *LDAPServerStateSyncer) deleteStaleSessions(ctx context.Context, before time.Time) error { + _, err := ldSync.ds.ExecContext(ctx, "DELETE FROM ldap_sessions WHERE created_at < $1", before) return err } // deleteStaleAPITokens deletes all ldap_user_api_tokens before the passed time. -func (ldSync *LDAPServerStateSyncer) deleteStaleAPITokens(before time.Time) error { - _, err := ldSync.q.Exec("DELETE FROM ldap_user_api_tokens WHERE created_at < $1", before) +func (ldSync *LDAPServerStateSyncer) deleteStaleAPITokens(ctx context.Context, before time.Time) error { + _, err := ldSync.ds.ExecContext(ctx, "DELETE FROM ldap_user_api_tokens WHERE created_at < $1", before) return err } diff --git a/core/sessions/localauth/reaper.go b/core/sessions/localauth/reaper.go index eef884367aa..7b91e4ce2c0 100644 --- a/core/sessions/localauth/reaper.go +++ b/core/sessions/localauth/reaper.go @@ -1,16 +1,17 @@ package localauth import ( - "database/sql" + "context" "time" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" ) type sessionReaper struct { - db *sql.DB + ds sqlutil.DataSource config SessionReaperConfig lggr logger.Logger } @@ -21,9 +22,9 @@ type SessionReaperConfig interface { } // NewSessionReaper creates a reaper that cleans stale sessions from the store. -func NewSessionReaper(db *sql.DB, config SessionReaperConfig, lggr logger.Logger) *utils.SleeperTask { +func NewSessionReaper(ds sqlutil.DataSource, config SessionReaperConfig, lggr logger.Logger) *utils.SleeperTask { return utils.NewSleeperTask(&sessionReaper{ - db, + ds, config, lggr.Named("SessionReaper"), }) @@ -34,16 +35,17 @@ func (sr *sessionReaper) Name() string { } func (sr *sessionReaper) Work() { + ctx := context.Background() //TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 recordCreationStaleThreshold := sr.config.SessionReaperExpiration().Before( sr.config.SessionTimeout().Before(time.Now())) - err := sr.deleteStaleSessions(recordCreationStaleThreshold) + err := sr.deleteStaleSessions(ctx, recordCreationStaleThreshold) if err != nil { sr.lggr.Error("unable to reap stale sessions: ", err) } } // DeleteStaleSessions deletes all sessions before the passed time. -func (sr *sessionReaper) deleteStaleSessions(before time.Time) error { - _, err := sr.db.Exec("DELETE FROM sessions WHERE last_used < $1", before) +func (sr *sessionReaper) deleteStaleSessions(ctx context.Context, before time.Time) error { + _, err := sr.ds.ExecContext(ctx, "DELETE FROM sessions WHERE last_used < $1", before) return err } diff --git a/core/sessions/localauth/reaper_test.go b/core/sessions/localauth/reaper_test.go index 47413c5fc62..806c9448682 100644 --- a/core/sessions/localauth/reaper_test.go +++ b/core/sessions/localauth/reaper_test.go @@ -37,7 +37,7 @@ func TestSessionReaper_ReapSessions(t *testing.T) { lggr := logger.TestLogger(t) orm := localauth.NewORM(db, config.SessionTimeout().Duration(), lggr, audit.NoopLogger) - r := localauth.NewSessionReaper(db.DB, config, lggr) + r := localauth.NewSessionReaper(db, config, lggr) t.Cleanup(func() { assert.NoError(t, r.Stop()) }) diff --git a/core/store/migrate/migrate.go b/core/store/migrate/migrate.go index aff3229e92a..c8f70e87383 100644 --- a/core/store/migrate/migrate.go +++ b/core/store/migrate/migrate.go @@ -9,13 +9,12 @@ import ( "strconv" "strings" - "github.com/jmoiron/sqlx" pkgerrors "github.com/pkg/errors" "github.com/pressly/goose/v3" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/config/env" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/store/migrate/migrations" // Invoke init() functions within migrations pkg. @@ -36,7 +35,7 @@ func init() { } // Ensure we migrated from v1 migrations to goose_migrations -func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { +func ensureMigrated(ctx context.Context, db *sql.DB) error { sqlxDB := pg.WrapDbWithSqlx(db) var names []string err := sqlxDB.SelectContext(ctx, &names, `SELECT id FROM migrations`) @@ -44,12 +43,10 @@ func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { // already migrated return nil } - err = pg.SqlTransaction(ctx, db, lggr, func(tx *sqlx.Tx) error { - // ensure that no legacy job specs are present: we _must_ bail out early if - // so because otherwise we run the risk of dropping working jobs if the - // user has not read the release notes - return migrations.CheckNoLegacyJobs(tx.Tx) - }) + // ensure that no legacy job specs are present: we _must_ bail out early if + // so because otherwise we run the risk of dropping working jobs if the + // user has not read the release notes + err = migrations.CheckNoLegacyJobs(ctx, db) if err != nil { return err } @@ -66,14 +63,14 @@ func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { } // ensure a goose migrations table exists with it's initial v0 - if _, err = goose.GetDBVersion(db); err != nil { + if _, err = goose.GetDBVersionContext(ctx, db); err != nil { return err } // insert records for existing migrations //nolint sql := fmt.Sprintf(`INSERT INTO %s (version_id, is_applied) VALUES ($1, true);`, goose.TableName()) - return pg.SqlTransaction(ctx, db, lggr, func(tx *sqlx.Tx) error { + return sqlutil.TransactDataSource(ctx, sqlxDB, nil, func(tx sqlutil.DataSource) error { for _, name := range names { var id int64 // the first migration doesn't follow the naming convention @@ -92,18 +89,18 @@ func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { } } - if _, err = db.Exec(sql, id); err != nil { + if _, err = tx.ExecContext(ctx, sql, id); err != nil { return err } } - _, err = db.Exec("DROP TABLE migrations;") + _, err = tx.ExecContext(ctx, "DROP TABLE migrations;") return err }) } -func Migrate(ctx context.Context, db *sql.DB, lggr logger.Logger) error { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Migrate(ctx context.Context, db *sql.DB) error { + if err := ensureMigrated(ctx, db); err != nil { return err } // WithAllowMissing is necessary when upgrading from 0.10.14 since it @@ -111,8 +108,8 @@ func Migrate(ctx context.Context, db *sql.DB, lggr logger.Logger) error { return goose.Up(db, MIGRATIONS_DIR, goose.WithAllowMissing()) } -func Rollback(ctx context.Context, db *sql.DB, lggr logger.Logger, version null.Int) error { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Rollback(ctx context.Context, db *sql.DB, version null.Int) error { + if err := ensureMigrated(ctx, db); err != nil { return err } if version.Valid { @@ -121,15 +118,15 @@ func Rollback(ctx context.Context, db *sql.DB, lggr logger.Logger, version null. return goose.Down(db, MIGRATIONS_DIR) } -func Current(ctx context.Context, db *sql.DB, lggr logger.Logger) (int64, error) { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Current(ctx context.Context, db *sql.DB) (int64, error) { + if err := ensureMigrated(ctx, db); err != nil { return -1, err } return goose.EnsureDBVersion(db) } -func Status(ctx context.Context, db *sql.DB, lggr logger.Logger) error { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Status(ctx context.Context, db *sql.DB) error { + if err := ensureMigrated(ctx, db); err != nil { return err } return goose.Status(db, MIGRATIONS_DIR) diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go index 3c0c2dc2158..8169368eb1f 100644 --- a/core/store/migrate/migrate_test.go +++ b/core/store/migrate/migrate_test.go @@ -21,11 +21,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -79,13 +77,13 @@ func TestMigrate_0100_BootstrapConfigs(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) ctx := testutils.Context(t) - pipelineID, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + pipelineID, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) - pipelineID2, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + pipelineID2, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) - nonBootstrapPipelineID, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + nonBootstrapPipelineID, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) - newFormatBoostrapPipelineID2, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + newFormatBoostrapPipelineID2, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) // OCR2 struct at migration v0099 @@ -392,25 +390,24 @@ func TestMigrate_101_GenericOCR2(t *testing.T) { func TestMigrate(t *testing.T) { ctx := testutils.Context(t) - lggr := logger.TestLogger(t) _, db := heavyweight.FullTestDBEmptyV2(t, nil) err := goose.UpTo(db.DB, migrationDir, 100) require.NoError(t, err) - err = migrate.Status(ctx, db.DB, lggr) + err = migrate.Status(ctx, db.DB) require.NoError(t, err) - ver, err := migrate.Current(ctx, db.DB, lggr) + ver, err := migrate.Current(ctx, db.DB) require.NoError(t, err) require.Equal(t, int64(100), ver) - err = migrate.Migrate(ctx, db.DB, lggr) + err = migrate.Migrate(ctx, db.DB) require.NoError(t, err) - err = migrate.Rollback(ctx, db.DB, lggr, null.IntFrom(99)) + err = migrate.Rollback(ctx, db.DB, null.IntFrom(99)) require.NoError(t, err) - ver, err = migrate.Current(ctx, db.DB, lggr) + ver, err = migrate.Current(ctx, db.DB) require.NoError(t, err) require.Equal(t, int64(99), ver) } @@ -543,6 +540,7 @@ func TestNoTriggers(t *testing.T) { } func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { + ctx := testutils.Context(b) previousMigration := int64(201) backfillMigration := int64(202) chainCount := 2 @@ -555,7 +553,6 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { err := goose.UpTo(db.DB, migrationDir, previousMigration) require.NoError(b, err) - q := pg.NewQ(db, logger.NullLogger, pgtest.NewQConfig(true)) for j := 0; j < chainCount; j++ { // Insert 100_000 block to database, can't do all at once, so batching by 10k var blocks []logpoller.LogPollerBlock @@ -574,7 +571,7 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { end = maxLogsSize } - err = q.ExecQNamed(` + _, err = db.NamedExecContext(ctx, ` INSERT INTO evm.log_poller_blocks (evm_chain_id, block_hash, block_number, finalized_block_number, block_timestamp, created_at) VALUES @@ -600,7 +597,7 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { err = goose.DownTo(db.DB, migrationDir, previousMigration) require.NoError(b, err) - err = q.ExecQ(` + _, err = db.ExecContext(ctx, ` UPDATE evm.log_poller_blocks SET finalized_block_number = 0`) require.NoError(b, err) diff --git a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go index 924d32308b8..b5ddcccd89b 100644 --- a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go +++ b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go @@ -32,9 +32,13 @@ func init() { goose.AddMigrationContext(Up54, Down54) } +type queryer interface { + QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row +} + // nolint func Up54(ctx context.Context, tx *sql.Tx) error { - if err := CheckNoLegacyJobs(tx); err != nil { + if err := CheckNoLegacyJobs(ctx, tx); err != nil { return err } if _, err := tx.ExecContext(ctx, up54); err != nil { @@ -49,9 +53,9 @@ func Down54(ctx context.Context, tx *sql.Tx) error { } // CheckNoLegacyJobs ensures that there are no legacy job specs -func CheckNoLegacyJobs(tx *sql.Tx) error { +func CheckNoLegacyJobs(ctx context.Context, ds queryer) error { var count int - if err := tx.QueryRow(`SELECT COUNT(*) FROM job_specs WHERE deleted_at IS NULL`).Scan(&count); err != nil { + if err := ds.QueryRowContext(ctx, `SELECT COUNT(*) FROM job_specs WHERE deleted_at IS NULL`).Scan(&count); err != nil { return err } if count > 0 { diff --git a/core/store/migrate/migrations/0234_generic_plugin_multichain_keybundle_.sql b/core/store/migrate/migrations/0234_generic_plugin_multichain_keybundle_.sql new file mode 100644 index 00000000000..b29ff9de382 --- /dev/null +++ b/core/store/migrate/migrations/0234_generic_plugin_multichain_keybundle_.sql @@ -0,0 +1,11 @@ +-- +goose Up +-- +goose StatementBegin +ALTER TABLE ocr2_oracle_specs + ADD COLUMN onchain_signing_strategy JSONB NOT NULL DEFAULT '{}'; +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +ALTER TABLE ocr2_oracle_specs + DROP COLUMN onchain_signing_strategy; +-- +goose StatementEnd \ No newline at end of file diff --git a/core/web/api.go b/core/web/api.go index 1f97d59c77d..51f7b855cd5 100644 --- a/core/web/api.go +++ b/core/web/api.go @@ -120,7 +120,7 @@ func ParsePaginatedResponse(input []byte, resource interface{}, links *jsonapi.L func parsePaginatedResponseToDocument(input []byte, resource interface{}, document *jsonapi.Document) error { err := ParseJSONAPIResponse(input, resource) if err != nil { - return errors.Wrap(err, "ParseJSONAPIResponse error") + return errors.Wrapf(err, "ParseJSONAPIResponse error body: %s", string(input)) } // Unmarshal using the stdlib Unmarshal to extract the links part of the document diff --git a/core/web/bridge_types_controller.go b/core/web/bridge_types_controller.go index 1c9fd7365f7..c787ca2fb54 100644 --- a/core/web/bridge_types_controller.go +++ b/core/web/bridge_types_controller.go @@ -213,7 +213,7 @@ func (btc *BridgeTypesController) Destroy(c *gin.Context) { jsonAPIError(c, http.StatusInternalServerError, fmt.Errorf("error searching for bridge: %+v", err)) return } - jobsUsingBridge, err := btc.App.JobORM().FindJobIDsWithBridge(name) + jobsUsingBridge, err := btc.App.JobORM().FindJobIDsWithBridge(ctx, name) if err != nil { jsonAPIError(c, http.StatusInternalServerError, fmt.Errorf("error searching for associated v2 jobs: %+v", err)) return diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go index 09a3eb5fa1e..34cde6f6a64 100644 --- a/core/web/eth_keys_controller_test.go +++ b/core/web/eth_keys_controller_test.go @@ -425,8 +425,7 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { }) assert.NoError(t, err) - db := app.GetSqlxDB() - txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) + txStore := txmgr.NewTxStore(app.GetDB(), logger.TestLogger(t)) txes, err := txStore.FindTxesByFromAddressAndState(testutils.Context(t), addr, "fatal_error") require.NoError(t, err) diff --git a/core/web/evm_transactions_controller_test.go b/core/web/evm_transactions_controller_test.go index a4dd21c9f03..3eb667bc6f8 100644 --- a/core/web/evm_transactions_controller_test.go +++ b/core/web/evm_transactions_controller_test.go @@ -25,8 +25,8 @@ func TestTransactionsController_Index_Success(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - db := app.GetSqlxDB() - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + db := app.GetDB() + txStore := cltest.NewTestTxStore(t, app.GetDB()) ethKeyStore := cltest.NewKeyStore(t, db).Eth() client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -84,7 +84,7 @@ func TestTransactionsController_Show_Success(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) @@ -118,7 +118,7 @@ func TestTransactionsController_Show_NotFound(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) tx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, from) diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index bfac6752f51..fff30a7df31 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -10,9 +10,8 @@ import ( "testing" "time" - "github.com/jmoiron/sqlx" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -72,7 +71,7 @@ func TestTransfersController_CreateSuccess_From(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) } func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { @@ -113,7 +112,7 @@ func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) } func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testing.T) { @@ -159,7 +158,7 @@ func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testin assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) } func TestTransfersController_TransferZeroAddressError(t *testing.T) { @@ -327,7 +326,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { err = web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource) assert.NoError(t, err) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) // check returned data assert.NotEmpty(t, resource.Hash) @@ -398,8 +397,8 @@ func TestTransfersController_FindTxAttempt(t *testing.T) { }) } -func validateTxCount(t *testing.T, db *sqlx.DB, count int) { - txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) +func validateTxCount(t *testing.T, ds sqlutil.DataSource, count int) { + txStore := txmgr.NewTxStore(ds, logger.TestLogger(t)) txes, err := txStore.GetAllTxes(testutils.Context(t)) require.NoError(t, err) diff --git a/core/web/evm_tx_attempts_controller_test.go b/core/web/evm_tx_attempts_controller_test.go index a92c8293a3f..f277f1f37bf 100644 --- a/core/web/evm_tx_attempts_controller_test.go +++ b/core/web/evm_tx_attempts_controller_test.go @@ -20,7 +20,7 @@ func TestTxAttemptsController_Index_Success(t *testing.T) { app := cltest.NewApplicationWithKey(t) require.NoError(t, app.Start(testutils.Context(t))) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) diff --git a/core/web/external_initiators_controller_test.go b/core/web/external_initiators_controller_test.go index 3c1425bcfdd..a79909c5864 100644 --- a/core/web/external_initiators_controller_test.go +++ b/core/web/external_initiators_controller_test.go @@ -75,7 +75,7 @@ func TestExternalInitiatorsController_Index(t *testing.T) { client := app.NewHTTPClient(nil) - db := app.GetSqlxDB() + db := app.GetDB() borm := bridges.NewORM(db) eiFoo := cltest.MustInsertExternalInitiatorWithOpts(t, borm, cltest.ExternalInitiatorOpts{ diff --git a/core/web/jobs_controller.go b/core/web/jobs_controller.go index 0808422cca7..5ca00476007 100644 --- a/core/web/jobs_controller.go +++ b/core/web/jobs_controller.go @@ -26,7 +26,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/streams" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" @@ -48,7 +47,7 @@ func (jc *JobsController) Index(c *gin.Context, size, page, offset int) { size = 1000 } - jobs, count, err := jc.App.JobORM().FindJobs(offset, size) + jobs, count, err := jc.App.JobORM().FindJobs(c.Request.Context(), offset, size) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -66,14 +65,15 @@ func (jc *JobsController) Index(c *gin.Context, size, page, offset int) { // Example: // "GET /jobs/:ID" func (jc *JobsController) Show(c *gin.Context) { + ctx := c.Request.Context() var err error jobSpec := job.Job{} if externalJobID, pErr := uuid.Parse(c.Param("ID")); pErr == nil { // Find a job by external job ID - jobSpec, err = jc.App.JobORM().FindJobByExternalJobID(externalJobID, pg.WithParentCtx(c.Request.Context())) + jobSpec, err = jc.App.JobORM().FindJobByExternalJobID(ctx, externalJobID) } else if pErr = jobSpec.SetID(c.Param("ID")); pErr == nil { // Find a job by job ID - jobSpec, err = jc.App.JobORM().FindJobTx(c, jobSpec.ID) + jobSpec, err = jc.App.JobORM().FindJobTx(ctx, jobSpec.ID) } else { jsonAPIError(c, http.StatusUnprocessableEntity, pErr) return @@ -242,7 +242,7 @@ func (jc *JobsController) validateJobSpec(ctx context.Context, tomlString string case job.VRF: jb, err = vrfcommon.ValidatedVRFSpec(tomlString) case job.Webhook: - jb, err = webhook.ValidatedWebhookSpec(tomlString, jc.App.GetExternalInitiatorManager()) + jb, err = webhook.ValidatedWebhookSpec(ctx, tomlString, jc.App.GetExternalInitiatorManager()) case job.BlockhashStore: jb, err = blockhashstore.ValidatedSpec(tomlString) case job.BlockHeaderFeeder: diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 9c7b529b6bf..bade8fe293b 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -24,8 +24,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -37,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils/tomlutils" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -129,7 +127,7 @@ func TestJobController_Create_DirectRequest_Fast(t *testing.T) { }(i) } wg.Wait() - cltest.AssertCount(t, app.GetSqlxDB(), "direct_request_specs", int64(n)) + cltest.AssertCount(t, app.GetDB(), "direct_request_specs", int64(n)) } func mustInt32FromString(t *testing.T, s string) int32 { @@ -141,7 +139,7 @@ func mustInt32FromString(t *testing.T, s string) int32 { func TestJobController_Create_HappyPath(t *testing.T) { ctx := testutils.Context(t) app, client := setupJobsControllerTests(t) - b1, b2 := setupBridges(t, app.GetSqlxDB(), app.GetConfig().Database()) + b1, b2 := setupBridges(t, app.GetDB()) require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) var pks []vrfkey.KeyV2 var k []p2pkey.KeyV2 @@ -220,7 +218,8 @@ func TestJobController_Create_HappyPath(t *testing.T) { // services failed to start require.Contains(t, errs.Errors[0].Detail, "no contract code at given address") // but the job should still exist - jb, err := jorm.FindJobByExternalJobID(uuid.MustParse(nameAndExternalJobID)) + ctx := testutils.Context(t) + jb, err := jorm.FindJobByExternalJobID(ctx, uuid.MustParse(nameAndExternalJobID)) require.NoError(t, err) require.NotNil(t, jb.KeeperSpec) @@ -333,7 +332,8 @@ func TestJobController_Create_HappyPath(t *testing.T) { // services failed to start require.Contains(t, errs.Errors[0].Detail, "no contract code at given address") // but the job should still exist - jb, err := jorm.FindJobByExternalJobID(uuid.MustParse(nameAndExternalJobID)) + ctx := testutils.Context(t) + jb, err := jorm.FindJobByExternalJobID(ctx, uuid.MustParse(nameAndExternalJobID)) require.NoError(t, err) require.NotNil(t, jb.FluxMonitorSpec) @@ -481,8 +481,8 @@ func TestJobsController_Create_WebhookSpec(t *testing.T) { app := cltest.NewApplicationEVMDisabled(t) require.NoError(t, app.Start(testutils.Context(t))) - _, fetchBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, submitBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, fetchBridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, submitBridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) @@ -620,10 +620,10 @@ func TestJobsController_Update_HappyPath(t *testing.T) { app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey) require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) @@ -639,16 +639,16 @@ func TestJobsController_Update_HappyPath(t *testing.T) { // BCF-2095 // disable fkey checks until the end of the test transaction require.NoError(t, utils.JustError( - app.GetSqlxDB().Exec(`SET CONSTRAINTS job_spec_errors_v2_job_id_fkey DEFERRED`))) + app.GetDB().ExecContext(ctx, `SET CONSTRAINTS job_spec_errors_v2_job_id_fkey DEFERRED`))) var ocrSpec job.OCROracleSpec err = toml.Unmarshal([]byte(ocrspec.Toml()), &ocrSpec) require.NoError(t, err) jb.OCROracleSpec = &ocrSpec jb.OCROracleSpec.TransmitterAddress = &app.Keys[0].EIP55Address - err = app.AddJobV2(testutils.Context(t), &jb) + err = app.AddJobV2(ctx, &jb) require.NoError(t, err) - dbJb, err := app.JobORM().FindJob(testutils.Context(t), jb.ID) + dbJb, err := app.JobORM().FindJob(ctx, jb.ID) require.NoError(t, err) require.Equal(t, dbJb.Name.String, ocrspec.Name) @@ -666,7 +666,7 @@ func TestJobsController_Update_HappyPath(t *testing.T) { response, cleanup := client.Put("/v2/jobs/"+fmt.Sprintf("%v", jb.ID), bytes.NewReader(body)) t.Cleanup(cleanup) - dbJb, err = app.JobORM().FindJob(testutils.Context(t), jb.ID) + dbJb, err = app.JobORM().FindJob(ctx, jb.ID) require.NoError(t, err) require.Equal(t, dbJb.Name.String, updatedSpec.Name) @@ -686,8 +686,8 @@ func TestJobsController_Update_NonExistentID(t *testing.T) { require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(ctx)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) @@ -754,9 +754,9 @@ func runDirectRequestJobSpecAssertions(t *testing.T, ereJobSpecFromFile job.Job, assert.Contains(t, ereJobSpecFromServer.DirectRequestSpec.UpdatedAt.String(), "20") } -func setupBridges(t *testing.T, db *sqlx.DB, cfg pg.QConfig) (b1, b2 string) { - _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) +func setupBridges(t *testing.T, ds sqlutil.DataSource) (b1, b2 string) { + _, bridge := cltest.MustCreateBridge(t, ds, cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, ds, cltest.BridgeOpts{}) return bridge.Name.String(), bridge2.Name.String() } @@ -800,8 +800,8 @@ func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(ctx)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) diff --git a/core/web/lca_controller.go b/core/web/lca_controller.go new file mode 100644 index 00000000000..bb4866c3d08 --- /dev/null +++ b/core/web/lca_controller.go @@ -0,0 +1,74 @@ +package web + +import ( + "errors" + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +type LCAController struct { + App chainlink.Application +} + +// FindLCA compares chain of blocks available in the DB with chain provided by an RPC and returns last common ancestor +// Example: +// +// "/v2/find_lca" +func (bdc *LCAController) FindLCA(c *gin.Context) { + chain, err := getChain(bdc.App.GetRelayers().LegacyEVMChains(), c.Query("evmChainID")) + if err != nil { + if errors.Is(err, ErrInvalidChainID) || errors.Is(err, ErrMultipleChains) || errors.Is(err, ErrMissingChainID) { + jsonAPIError(c, http.StatusUnprocessableEntity, err) + return + } + jsonAPIError(c, http.StatusInternalServerError, err) + return + } + chainID := chain.ID() + + lca, err := bdc.App.FindLCA(c.Request.Context(), chainID) + if err != nil { + jsonAPIError(c, http.StatusInternalServerError, err) + return + } + + if lca == nil { + jsonAPIError(c, http.StatusNotFound, fmt.Errorf("failed to find last common ancestor")) + return + } + + response := LCAResponse{ + BlockNumber: lca.BlockNumber, + Hash: lca.BlockHash.String(), + EVMChainID: big.New(chainID), + } + jsonAPIResponse(c, &response, "response") + +} + +type LCAResponse struct { + BlockNumber int64 `json:"blockNumber"` + Hash string `json:"hash"` + EVMChainID *big.Big `json:"evmChainID"` +} + +// GetID returns the jsonapi ID. +func (s LCAResponse) GetID() string { + return "LCAResponseID" +} + +// GetName returns the collection name for jsonapi. +func (LCAResponse) GetName() string { + return "lca_response" +} + +// SetID is used to conform to the UnmarshallIdentifier interface for +// deserializing from jsonapi documents. +func (*LCAResponse) SetID(string) error { + return nil +} diff --git a/core/web/lca_controller_test.go b/core/web/lca_controller_test.go new file mode 100644 index 00000000000..7ec476e8eca --- /dev/null +++ b/core/web/lca_controller_test.go @@ -0,0 +1,29 @@ +package web_test + +import ( + _ "embed" + "io" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" +) + +func TestLCAController_FindLCA(t *testing.T) { + cfg := configtest.NewTestGeneralConfig(t) + ec := setupEthClientForControllerTests(t) + app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey, ec) + require.NoError(t, app.Start(testutils.Context(t))) + client := app.NewHTTPClient(nil) + resp, cleanup := client.Get("/v2/find_lca?evmChainID=1") + t.Cleanup(cleanup) + assert.Equal(t, http.StatusUnprocessableEntity, resp.StatusCode) + b, err := io.ReadAll(resp.Body) + require.NoError(t, err) + assert.Contains(t, string(b), "chain id does not match any local chains") +} diff --git a/core/web/loader/feeds_manager.go b/core/web/loader/feeds_manager.go index fb894d38b6e..a29d510a09d 100644 --- a/core/web/loader/feeds_manager.go +++ b/core/web/loader/feeds_manager.go @@ -14,7 +14,7 @@ type feedsBatcher struct { app chainlink.Application } -func (b *feedsBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *feedsBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -28,7 +28,7 @@ func (b *feedsBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*dat } // Fetch the feeds managers - managers, err := b.app.GetFeedsService().ListManagersByIDs(managersIDs) + managers, err := b.app.GetFeedsService().ListManagersByIDs(ctx, managersIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/feeds_manager_chain_config.go b/core/web/loader/feeds_manager_chain_config.go index 89d35919fd1..661edc33219 100644 --- a/core/web/loader/feeds_manager_chain_config.go +++ b/core/web/loader/feeds_manager_chain_config.go @@ -14,10 +14,10 @@ type feedsManagerChainConfigBatcher struct { app chainlink.Application } -func (b *feedsManagerChainConfigBatcher) loadByManagerIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *feedsManagerChainConfigBatcher) loadByManagerIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { ids, keyOrder := keyOrderInt64(keys) - cfgs, err := b.app.GetFeedsService().ListChainConfigsByManagerIDs(ids) + cfgs, err := b.app.GetFeedsService().ListChainConfigsByManagerIDs(ctx, ids) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job.go b/core/web/loader/job.go index 11eb2c76814..a37c2809625 100644 --- a/core/web/loader/job.go +++ b/core/web/loader/job.go @@ -16,7 +16,7 @@ type jobBatcher struct { app chainlink.Application } -func (b *jobBatcher) loadByExternalJobIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobBatcher) loadByExternalJobIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -33,7 +33,7 @@ func (b *jobBatcher) loadByExternalJobIDs(_ context.Context, keys dataloader.Key // Fetch the jobs var jobs []job.Job for _, id := range jobIDs { - job, err := b.app.JobORM().FindJobByExternalJobID(id) + job, err := b.app.JobORM().FindJobByExternalJobID(ctx, id) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} @@ -63,7 +63,7 @@ func (b *jobBatcher) loadByExternalJobIDs(_ context.Context, keys dataloader.Key return results } -func (b *jobBatcher) loadByPipelineSpecIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobBatcher) loadByPipelineSpecIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -77,7 +77,7 @@ func (b *jobBatcher) loadByPipelineSpecIDs(_ context.Context, keys dataloader.Ke } // Fetch the jobs - jobs, err := b.app.JobORM().FindJobsByPipelineSpecIDs(plSpecIDs) + jobs, err := b.app.JobORM().FindJobsByPipelineSpecIDs(ctx, plSpecIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_proposal.go b/core/web/loader/job_proposal.go index ac24e620f47..17fb6bc67c2 100644 --- a/core/web/loader/job_proposal.go +++ b/core/web/loader/job_proposal.go @@ -14,7 +14,7 @@ type jobProposalBatcher struct { app chainlink.Application } -func (b *jobProposalBatcher) loadByManagersIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobProposalBatcher) loadByManagersIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -28,7 +28,7 @@ func (b *jobProposalBatcher) loadByManagersIDs(_ context.Context, keys dataloade keyOrder[key.String()] = ix } - jps, err := b.app.GetFeedsService().ListJobProposalsByManagersIDs(mgrsIDs) + jps, err := b.app.GetFeedsService().ListJobProposalsByManagersIDs(ctx, mgrsIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_proposal_spec.go b/core/web/loader/job_proposal_spec.go index bb6720903dc..bff112268f8 100644 --- a/core/web/loader/job_proposal_spec.go +++ b/core/web/loader/job_proposal_spec.go @@ -14,10 +14,10 @@ type jobProposalSpecBatcher struct { app chainlink.Application } -func (b *jobProposalSpecBatcher) loadByJobProposalsIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobProposalSpecBatcher) loadByJobProposalsIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { ids, keyOrder := keyOrderInt64(keys) - specs, err := b.app.GetFeedsService().ListSpecsByJobProposalIDs(ids) + specs, err := b.app.GetFeedsService().ListSpecsByJobProposalIDs(ctx, ids) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_run.go b/core/web/loader/job_run.go index 691b27a3511..4367eec2c78 100644 --- a/core/web/loader/job_run.go +++ b/core/web/loader/job_run.go @@ -14,7 +14,7 @@ type jobRunBatcher struct { app chainlink.Application } -func (b *jobRunBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobRunBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -29,7 +29,7 @@ func (b *jobRunBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*da } // Fetch the runs - runs, err := b.app.JobORM().FindPipelineRunsByIDs(runIDs) + runs, err := b.app.JobORM().FindPipelineRunsByIDs(ctx, runIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_spec_errors.go b/core/web/loader/job_spec_errors.go index 5ef23154d2e..5d558c52ec5 100644 --- a/core/web/loader/job_spec_errors.go +++ b/core/web/loader/job_spec_errors.go @@ -7,7 +7,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils/stringutils" ) @@ -29,7 +28,7 @@ func (b *jobSpecErrorsBatcher) loadByJobIDs(ctx context.Context, keys dataloader keyOrder[key.String()] = ix } - specErrors, err := b.app.JobORM().FindSpecErrorsByJobIDs(jobIDs, pg.WithParentCtx(ctx)) + specErrors, err := b.app.JobORM().FindSpecErrorsByJobIDs(ctx, jobIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go index d12a10a9e52..5e22c9afef6 100644 --- a/core/web/loader/loader_test.go +++ b/core/web/loader/loader_test.go @@ -125,7 +125,7 @@ func TestLoader_FeedsManagers(t *testing.T) { Name: "manager 3", } - fsvc.On("ListManagersByIDs", []int64{3, 1, 2, 5}).Return([]feeds.FeedsManager{ + fsvc.On("ListManagersByIDs", mock.Anything, []int64{3, 1, 2, 5}).Return([]feeds.FeedsManager{ mgr1, mgr2, mgr3, }, nil) app.On("GetFeedsService").Return(fsvc) @@ -167,7 +167,7 @@ func TestLoader_JobProposals(t *testing.T) { Status: feeds.JobProposalStatusRejected, } - fsvc.On("ListJobProposalsByManagersIDs", []int64{3, 1, 2}).Return([]feeds.JobProposal{ + fsvc.On("ListJobProposalsByManagersIDs", mock.Anything, []int64{3, 1, 2}).Return([]feeds.JobProposal{ jp1, jp3, jp2, }, nil) app.On("GetFeedsService").Return(fsvc) @@ -194,7 +194,7 @@ func TestLoader_JobRuns(t *testing.T) { run2 := pipeline.Run{ID: int64(2)} run3 := pipeline.Run{ID: int64(3)} - jobsORM.On("FindPipelineRunsByIDs", []int64{3, 1, 2}).Return([]pipeline.Run{ + jobsORM.On("FindPipelineRunsByIDs", mock.Anything, []int64{3, 1, 2}).Return([]pipeline.Run{ run3, run1, run2, }, nil) app.On("JobORM").Return(jobsORM) @@ -224,7 +224,7 @@ func TestLoader_JobsByPipelineSpecIDs(t *testing.T) { job2 := job.Job{ID: int32(3), PipelineSpecID: int32(2)} job3 := job.Job{ID: int32(4), PipelineSpecID: int32(3)} - jobsORM.On("FindJobsByPipelineSpecIDs", []int32{3, 1, 2}).Return([]job.Job{ + jobsORM.On("FindJobsByPipelineSpecIDs", mock.Anything, []int32{3, 1, 2}).Return([]job.Job{ job1, job2, job3, }, nil) app.On("JobORM").Return(jobsORM) @@ -247,7 +247,7 @@ func TestLoader_JobsByPipelineSpecIDs(t *testing.T) { app := coremocks.NewApplication(t) ctx := InjectDataloader(testutils.Context(t), app) - jobsORM.On("FindJobsByPipelineSpecIDs", []int32{3, 1, 2}).Return([]job.Job{}, sql.ErrNoRows) + jobsORM.On("FindJobsByPipelineSpecIDs", mock.Anything, []int32{3, 1, 2}).Return([]job.Job{}, sql.ErrNoRows) app.On("JobORM").Return(jobsORM) batcher := jobBatcher{app} @@ -274,7 +274,7 @@ func TestLoader_JobsByExternalJobIDs(t *testing.T) { ejID := uuid.New() job := job.Job{ID: int32(2), ExternalJobID: ejID} - jobsORM.On("FindJobByExternalJobID", ejID).Return(job, nil) + jobsORM.On("FindJobByExternalJobID", mock.Anything, ejID).Return(job, nil) app.On("JobORM").Return(jobsORM) batcher := jobBatcher{app} @@ -335,7 +335,7 @@ func TestLoader_SpecErrorsByJobID(t *testing.T) { specErr2 := job.SpecError{ID: int64(3), JobID: int32(2)} specErr3 := job.SpecError{ID: int64(4), JobID: int32(3)} - jobsORM.On("FindSpecErrorsByJobIDs", []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{ + jobsORM.On("FindSpecErrorsByJobIDs", mock.Anything, []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{ specErr1, specErr2, specErr3, }, nil) app.On("JobORM").Return(jobsORM) @@ -358,7 +358,7 @@ func TestLoader_SpecErrorsByJobID(t *testing.T) { app := coremocks.NewApplication(t) ctx := InjectDataloader(testutils.Context(t), app) - jobsORM.On("FindSpecErrorsByJobIDs", []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{}, sql.ErrNoRows) + jobsORM.On("FindSpecErrorsByJobIDs", mock.Anything, []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{}, sql.ErrNoRows) app.On("JobORM").Return(jobsORM) batcher := jobSpecErrorsBatcher{app} diff --git a/core/web/pipeline_job_spec_errors_controller_test.go b/core/web/pipeline_job_spec_errors_controller_test.go index 8ec77a84f05..9729bfac51d 100644 --- a/core/web/pipeline_job_spec_errors_controller_test.go +++ b/core/web/pipeline_job_spec_errors_controller_test.go @@ -17,7 +17,8 @@ func TestPipelineJobSpecErrorsController_Delete_2(t *testing.T) { description := "job spec error description" - require.NoError(t, app.JobORM().RecordError(jID, description)) + ctx := testutils.Context(t) + require.NoError(t, app.JobORM().RecordError(ctx, jID, description)) // FindJob -> find error j, err := app.JobORM().FindJob(testutils.Context(t), jID) diff --git a/core/web/pipeline_runs_controller.go b/core/web/pipeline_runs_controller.go index 1bd52b021c3..099f824e0c3 100644 --- a/core/web/pipeline_runs_controller.go +++ b/core/web/pipeline_runs_controller.go @@ -40,8 +40,9 @@ func (prc *PipelineRunsController) Index(c *gin.Context, size, page, offset int) var count int var err error + ctx := c.Request.Context() if id == "" { - pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(nil, offset, size) + pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(ctx, nil, offset, size) } else { jobSpec := job.Job{} err = jobSpec.SetID(c.Param("ID")) @@ -50,7 +51,7 @@ func (prc *PipelineRunsController) Index(c *gin.Context, size, page, offset int) return } - pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(&jobSpec.ID, offset, size) + pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(ctx, &jobSpec.ID, offset, size) } if err != nil { @@ -113,13 +114,13 @@ func (prc *PipelineRunsController) Create(c *gin.Context) { // Is it a UUID? Then process it as a webhook job jobUUID, err := uuid.Parse(idStr) if err == nil { - canRun, err2 := authorizer.CanRun(c.Request.Context(), prc.App.GetConfig().JobPipeline(), jobUUID) + canRun, err2 := authorizer.CanRun(ctx, prc.App.GetConfig().JobPipeline(), jobUUID) if err2 != nil { jsonAPIError(c, http.StatusInternalServerError, err2) return } if canRun { - jobRunID, err3 := prc.App.RunWebhookJobV2(c.Request.Context(), jobUUID, string(bodyBytes), jsonserializable.JSONSerializable{}) + jobRunID, err3 := prc.App.RunWebhookJobV2(ctx, jobUUID, string(bodyBytes), jsonserializable.JSONSerializable{}) if errors.Is(err3, webhook.ErrJobNotExists) { jsonAPIError(c, http.StatusNotFound, err3) return @@ -141,7 +142,7 @@ func (prc *PipelineRunsController) Create(c *gin.Context) { jobID64, err := strconv.ParseInt(idStr, 10, 32) if err == nil { jobID = int32(jobID64) - jobRunID, err := prc.App.RunJobV2(c.Request.Context(), jobID, nil) + jobRunID, err := prc.App.RunJobV2(ctx, jobID, nil) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return diff --git a/core/web/pipeline_runs_controller_test.go b/core/web/pipeline_runs_controller_test.go index f6b4291a34f..e123df2bdb3 100644 --- a/core/web/pipeline_runs_controller_test.go +++ b/core/web/pipeline_runs_controller_test.go @@ -33,6 +33,7 @@ import ( func TestPipelineRunsController_CreateWithBody_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.JobPipeline.HTTPRequest.DefaultTimeout = commonconfig.MustNewDuration(2 * time.Second) @@ -50,13 +51,13 @@ func TestPipelineRunsController_CreateWithBody_HappyPath(t *testing.T) { require.Equal(t, `{"result":"12345"}`, string(bs)) }) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: mockServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: mockServer.URL}) // Add the job uuid := uuid.New() { tomlStr := fmt.Sprintf(testspecs.WebhookSpecWithBodyTemplate, uuid, bridge.Name.String()) - jb, err := webhook.ValidatedWebhookSpec(tomlStr, app.GetExternalInitiatorManager()) + jb, err := webhook.ValidatedWebhookSpec(ctx, tomlStr, app.GetExternalInitiatorManager()) require.NoError(t, err) err = app.AddJobV2(testutils.Context(t), &jb) @@ -88,6 +89,7 @@ func TestPipelineRunsController_CreateWithBody_HappyPath(t *testing.T) { func TestPipelineRunsController_CreateNoBody_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.JobPipeline.HTTPRequest.DefaultTimeout = commonconfig.MustNewDuration(2 * time.Second) @@ -100,7 +102,7 @@ func TestPipelineRunsController_CreateNoBody_HappyPath(t *testing.T) { // Setup the bridges mockServer := cltest.NewHTTPMockServer(t, 200, "POST", `{"data":{"result":"123.45"}}`) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: mockServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: mockServer.URL}) mockServer = cltest.NewHTTPMockServerWithRequest(t, 200, `{}`, func(r *http.Request) { defer r.Body.Close() @@ -109,13 +111,13 @@ func TestPipelineRunsController_CreateNoBody_HappyPath(t *testing.T) { require.Equal(t, `{"result":"12345"}`, string(bs)) }) - _, submitBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: mockServer.URL}) + _, submitBridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: mockServer.URL}) // Add the job uuid := uuid.New() { tomlStr := testspecs.GetWebhookSpecNoBody(uuid, bridge.Name.String(), submitBridge.Name.String()) - jb, err := webhook.ValidatedWebhookSpec(tomlStr, app.GetExternalInitiatorManager()) + jb, err := webhook.ValidatedWebhookSpec(ctx, tomlStr, app.GetExternalInitiatorManager()) require.NoError(t, err) err = app.AddJobV2(testutils.Context(t), &jb) diff --git a/core/web/resolver/bridge_test.go b/core/web/resolver/bridge_test.go index 706d3fb6d5a..2244ddf3dac 100644 --- a/core/web/resolver/bridge_test.go +++ b/core/web/resolver/bridge_test.go @@ -418,7 +418,7 @@ func Test_DeleteBridgeMutation(t *testing.T) { f.Mocks.bridgeORM.On("FindBridge", mock.Anything, name).Return(bridge, nil) f.Mocks.bridgeORM.On("DeleteBridgeType", mock.Anything, &bridge).Return(nil) - f.Mocks.jobORM.On("FindJobIDsWithBridge", name.String()).Return([]int32{}, nil) + f.Mocks.jobORM.On("FindJobIDsWithBridge", mock.Anything, name.String()).Return([]int32{}, nil) f.App.On("JobORM").Return(f.Mocks.jobORM) f.App.On("BridgeORM").Return(f.Mocks.bridgeORM) }, @@ -481,7 +481,7 @@ func Test_DeleteBridgeMutation(t *testing.T) { }, before: func(f *gqlTestFramework) { f.Mocks.bridgeORM.On("FindBridge", mock.Anything, name).Return(bridges.BridgeType{}, nil) - f.Mocks.jobORM.On("FindJobIDsWithBridge", name.String()).Return([]int32{1}, nil) + f.Mocks.jobORM.On("FindJobIDsWithBridge", mock.Anything, name.String()).Return([]int32{1}, nil) f.App.On("BridgeORM").Return(f.Mocks.bridgeORM) f.App.On("JobORM").Return(f.Mocks.jobORM) }, diff --git a/core/web/resolver/feeds_manager_chain_config_test.go b/core/web/resolver/feeds_manager_chain_config_test.go index ae869b50874..31208aa0581 100644 --- a/core/web/resolver/feeds_manager_chain_config_test.go +++ b/core/web/resolver/feeds_manager_chain_config_test.go @@ -101,7 +101,7 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { }, }, }).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, ChainType: feeds.ChainTypeEVM, ChainID: chainID, @@ -164,7 +164,7 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("CreateChainConfig", mock.Anything, mock.IsType(feeds.ChainConfig{})).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -211,7 +211,7 @@ func Test_DeleteFeedsManagerChainConfig(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, }, nil) f.Mocks.feedsSvc.On("DeleteChainConfig", mock.Anything, cfgID).Return(cfgID, nil) @@ -232,7 +232,7 @@ func Test_DeleteFeedsManagerChainConfig(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -249,7 +249,7 @@ func Test_DeleteFeedsManagerChainConfig(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, }, nil) f.Mocks.feedsSvc.On("DeleteChainConfig", mock.Anything, cfgID).Return(int64(0), sql.ErrNoRows) @@ -352,7 +352,7 @@ func Test_UpdateFeedsManagerChainConfig(t *testing.T) { }, }, }).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, AccountAddress: accountAddr, AdminAddress: adminAddr, @@ -413,7 +413,7 @@ func Test_UpdateFeedsManagerChainConfig(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateChainConfig", mock.Anything, mock.IsType(feeds.ChainConfig{})).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, diff --git a/core/web/resolver/feeds_manager_test.go b/core/web/resolver/feeds_manager_test.go index 84558090da5..a3ea80a6443 100644 --- a/core/web/resolver/feeds_manager_test.go +++ b/core/web/resolver/feeds_manager_test.go @@ -42,14 +42,14 @@ func Test_FeedsManagers(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("ListJobProposalsByManagersIDs", []int64{1}).Return([]feeds.JobProposal{ + f.Mocks.feedsSvc.On("ListJobProposalsByManagersIDs", mock.Anything, []int64{1}).Return([]feeds.JobProposal{ { ID: int64(100), FeedsManagerID: int64(1), Status: feeds.JobProposalStatusApproved, }, }, nil) - f.Mocks.feedsSvc.On("ListManagers").Return([]feeds.FeedsManager{ + f.Mocks.feedsSvc.On("ListManagers", mock.Anything).Return([]feeds.FeedsManager{ { ID: 1, Name: "manager1", @@ -115,7 +115,7 @@ func Test_FeedsManager(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(&feeds.FeedsManager{ + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(&feeds.FeedsManager{ ID: mgrID, Name: "manager1", URI: "localhost:2000", @@ -142,7 +142,7 @@ func Test_FeedsManager(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(nil, sql.ErrNoRows) }, query: query, result: ` @@ -219,7 +219,7 @@ func Test_CreateFeedsManager(t *testing.T) { URI: uri, PublicKey: *pubKey, }).Return(mgrID, nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(&feeds.FeedsManager{ + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(&feeds.FeedsManager{ ID: mgrID, Name: name, URI: uri, @@ -269,7 +269,7 @@ func Test_CreateFeedsManager(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("RegisterManager", mock.Anything, mock.IsType(feeds.RegisterManagerParams{})).Return(mgrID, nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -366,7 +366,7 @@ func Test_UpdateFeedsManager(t *testing.T) { URI: uri, PublicKey: *pubKey, }).Return(nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(&feeds.FeedsManager{ + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(&feeds.FeedsManager{ ID: mgrID, Name: name, URI: uri, @@ -397,7 +397,7 @@ func Test_UpdateFeedsManager(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateManager", mock.Anything, mock.IsType(feeds.FeedsManager{})).Return(nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, diff --git a/core/web/resolver/job.go b/core/web/resolver/job.go index cb79b0c6e63..e9855fdb8fe 100644 --- a/core/web/resolver/job.go +++ b/core/web/resolver/job.go @@ -113,7 +113,7 @@ func (r *JobResolver) Runs(ctx context.Context, args struct { limit = 100 } - ids, err := r.app.JobORM().FindPipelineRunIDsByJobID(r.j.ID, offset, limit) + ids, err := r.app.JobORM().FindPipelineRunIDsByJobID(ctx, r.j.ID, offset, limit) if err != nil { return nil, err } @@ -123,7 +123,7 @@ func (r *JobResolver) Runs(ctx context.Context, args struct { return nil, err } - count, err := r.app.JobORM().CountPipelineRunsByJobID(r.j.ID) + count, err := r.app.JobORM().CountPipelineRunsByJobID(ctx, r.j.ID) if err != nil { return nil, err } diff --git a/core/web/resolver/job_error_test.go b/core/web/resolver/job_error_test.go index 30d06289ed6..69899a3ec47 100644 --- a/core/web/resolver/job_error_test.go +++ b/core/web/resolver/job_error_test.go @@ -29,10 +29,10 @@ func TestResolver_JobErrors(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: int32(1), }, nil) - f.Mocks.jobORM.On("FindSpecErrorsByJobIDs", []int32{1}, mock.Anything).Return([]job.SpecError{ + f.Mocks.jobORM.On("FindSpecErrorsByJobIDs", mock.Anything, []int32{1}, mock.Anything).Return([]job.SpecError{ { ID: errorID, Description: "no contract code at given address", @@ -124,7 +124,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{ + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{ ID: id, Occurrences: 5, Description: "test-description", @@ -141,7 +141,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "not found on FindSpecError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -159,7 +159,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "not found on DismissError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, nil) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, nil) f.Mocks.jobORM.On("DismissError", mock.Anything, id).Return(sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, @@ -178,7 +178,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "generic error on FindSpecError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, gError) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -197,7 +197,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "generic error on DismissError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, nil) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, nil) f.Mocks.jobORM.On("DismissError", mock.Anything, id).Return(gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, diff --git a/core/web/resolver/job_proposal_spec_test.go b/core/web/resolver/job_proposal_spec_test.go index 2681129b2ae..c65702c5622 100644 --- a/core/web/resolver/job_proposal_spec_test.go +++ b/core/web/resolver/job_proposal_spec_test.go @@ -53,7 +53,7 @@ func TestResolver_ApproveJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("ApproveSpec", mock.Anything, specID, false).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) }, @@ -84,7 +84,7 @@ func TestResolver_ApproveJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("ApproveSpec", mock.Anything, specID, false).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -157,7 +157,7 @@ func TestResolver_CancelJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("CancelSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) @@ -189,7 +189,7 @@ func TestResolver_CancelJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("CancelSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -245,7 +245,7 @@ func TestResolver_RejectJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("RejectSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) }, @@ -276,7 +276,7 @@ func TestResolver_RejectJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("RejectSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -335,7 +335,7 @@ func TestResolver_UpdateJobProposalSpecDefinition(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateSpecDefinition", mock.Anything, specID, "").Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) }, @@ -367,7 +367,7 @@ func TestResolver_UpdateJobProposalSpecDefinition(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateSpecDefinition", mock.Anything, specID, "").Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -446,7 +446,7 @@ func TestResolver_GetJobProposal_Spec(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.feedsSvc.On("GetJobProposal", jpID).Return(&feeds.JobProposal{ + f.Mocks.feedsSvc.On("GetJobProposal", mock.Anything, jpID).Return(&feeds.JobProposal{ ID: jpID, Status: feeds.JobProposalStatusApproved, FeedsManagerID: 1, @@ -454,7 +454,7 @@ func TestResolver_GetJobProposal_Spec(t *testing.T) { PendingUpdate: false, }, nil) f.Mocks.feedsSvc. - On("ListSpecsByJobProposalIDs", []int64{jpID}). + On("ListSpecsByJobProposalIDs", mock.Anything, []int64{jpID}). Return(specs, nil) f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) }, diff --git a/core/web/resolver/job_proposal_test.go b/core/web/resolver/job_proposal_test.go index 466ddd5d8ab..5544b39c936 100644 --- a/core/web/resolver/job_proposal_test.go +++ b/core/web/resolver/job_proposal_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/google/uuid" + "github.com/stretchr/testify/mock" "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" @@ -64,13 +65,13 @@ func TestResolver_GetJobProposal(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.feedsSvc.On("ListManagersByIDs", []int64{1}).Return([]feeds.FeedsManager{ + f.Mocks.feedsSvc.On("ListManagersByIDs", mock.Anything, []int64{1}).Return([]feeds.FeedsManager{ { ID: 1, Name: "manager", }, }, nil) - f.Mocks.feedsSvc.On("GetJobProposal", jpID).Return(&feeds.JobProposal{ + f.Mocks.feedsSvc.On("GetJobProposal", mock.Anything, jpID).Return(&feeds.JobProposal{ ID: jpID, Name: null.StringFrom(name), Status: feeds.JobProposalStatusApproved, @@ -89,7 +90,7 @@ func TestResolver_GetJobProposal(t *testing.T) { name: "not found error", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.feedsSvc.On("GetJobProposal", jpID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetJobProposal", mock.Anything, jpID).Return(nil, sql.ErrNoRows) f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) }, query: query, diff --git a/core/web/resolver/job_run_test.go b/core/web/resolver/job_run_test.go index a35a2f66ac5..51631864e8c 100644 --- a/core/web/resolver/job_run_test.go +++ b/core/web/resolver/job_run_test.go @@ -40,7 +40,7 @@ func TestQuery_PaginatedJobRuns(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("PipelineRuns", (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return([]pipeline.Run{ + f.Mocks.jobORM.On("PipelineRuns", mock.Anything, (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return([]pipeline.Run{ { ID: int64(200), }, @@ -64,7 +64,7 @@ func TestQuery_PaginatedJobRuns(t *testing.T) { name: "generic error on PipelineRuns()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("PipelineRuns", (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return(nil, 0, gError) + f.Mocks.jobORM.On("PipelineRuns", mock.Anything, (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return(nil, 0, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: query, @@ -131,7 +131,7 @@ func TestResolver_JobRun(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindPipelineRunByID", int64(2)).Return(pipeline.Run{ + f.Mocks.jobORM.On("FindPipelineRunByID", mock.Anything, int64(2)).Return(pipeline.Run{ ID: 2, PipelineSpecID: 5, CreatedAt: f.Timestamp(), @@ -142,7 +142,7 @@ func TestResolver_JobRun(t *testing.T) { Outputs: outputs, State: pipeline.RunStatusErrored, }, nil) - f.Mocks.jobORM.On("FindJobsByPipelineSpecIDs", []int32{5}).Return([]job.Job{ + f.Mocks.jobORM.On("FindJobsByPipelineSpecIDs", mock.Anything, []int32{5}).Return([]job.Job{ { ID: 1, PipelineSpecID: 2, @@ -180,7 +180,7 @@ func TestResolver_JobRun(t *testing.T) { name: "not found error", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindPipelineRunByID", int64(2)).Return(pipeline.Run{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindPipelineRunByID", mock.Anything, int64(2)).Return(pipeline.Run{}, sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: query, @@ -197,7 +197,7 @@ func TestResolver_JobRun(t *testing.T) { name: "generic error on FindPipelineRunByID()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindPipelineRunByID", int64(2)).Return(pipeline.Run{}, gError) + f.Mocks.jobORM.On("FindPipelineRunByID", mock.Anything, int64(2)).Return(pipeline.Run{}, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: query, diff --git a/core/web/resolver/job_test.go b/core/web/resolver/job_test.go index e91e37b6903..0615e47a621 100644 --- a/core/web/resolver/job_test.go +++ b/core/web/resolver/job_test.go @@ -72,7 +72,7 @@ func TestResolver_Jobs(t *testing.T) { plnSpecID := int32(12) f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobs", 0, 50).Return([]job.Job{ + f.Mocks.jobORM.On("FindJobs", mock.Anything, 0, 50).Return([]job.Job{ { ID: 1, Name: null.StringFrom("job1"), @@ -89,13 +89,13 @@ func TestResolver_Jobs(t *testing.T) { }, }, 1, nil) f.Mocks.jobORM. - On("FindPipelineRunIDsByJobID", int32(1), 0, 50). + On("FindPipelineRunIDsByJobID", mock.Anything, int32(1), 0, 50). Return([]int64{200}, nil) f.Mocks.jobORM. - On("FindPipelineRunsByIDs", []int64{200}). + On("FindPipelineRunsByIDs", mock.Anything, []int64{200}). Return([]pipeline.Run{{ID: 200}}, nil) f.Mocks.jobORM. - On("CountPipelineRunsByJobID", int32(1)). + On("CountPipelineRunsByJobID", mock.Anything, int32(1)). Return(int32(1), nil) }, query: query, @@ -208,7 +208,7 @@ func TestResolver_Job(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: 1, Name: null.StringFrom("job1"), SchemaVersion: 1, @@ -223,13 +223,13 @@ func TestResolver_Job(t *testing.T) { }, }, nil) f.Mocks.jobORM. - On("FindPipelineRunIDsByJobID", int32(1), 0, 50). + On("FindPipelineRunIDsByJobID", mock.Anything, int32(1), 0, 50). Return([]int64{200}, nil) f.Mocks.jobORM. - On("FindPipelineRunsByIDs", []int64{200}). + On("FindPipelineRunsByIDs", mock.Anything, []int64{200}). Return([]pipeline.Run{{ID: 200}}, nil) f.Mocks.jobORM. - On("CountPipelineRunsByJobID", int32(1)). + On("CountPipelineRunsByJobID", mock.Anything, int32(1)). Return(int32(1), nil) }, query: query, @@ -240,7 +240,7 @@ func TestResolver_Job(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, sql.ErrNoRows) }, query: query, result: ` @@ -257,7 +257,7 @@ func TestResolver_Job(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: 1, Name: null.StringFrom("job1"), SchemaVersion: 1, @@ -272,13 +272,13 @@ func TestResolver_Job(t *testing.T) { }, }, chains.ErrNoSuchChainID) f.Mocks.jobORM. - On("FindPipelineRunIDsByJobID", int32(1), 0, 50). + On("FindPipelineRunIDsByJobID", mock.Anything, int32(1), 0, 50). Return([]int64{200}, nil) f.Mocks.jobORM. - On("FindPipelineRunsByIDs", []int64{200}). + On("FindPipelineRunsByIDs", mock.Anything, []int64{200}). Return([]pipeline.Run{{ID: 200}}, nil) f.Mocks.jobORM. - On("CountPipelineRunsByJobID", int32(1)). + On("CountPipelineRunsByJobID", mock.Anything, int32(1)). Return(int32(1), nil) }, query: query, @@ -453,7 +453,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: id, Name: null.StringFrom("test-job"), ExternalJobID: extJID, @@ -471,7 +471,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "not found on FindJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -489,7 +489,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "not found on DeleteJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, nil) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, nil) f.App.On("JobORM").Return(f.Mocks.jobORM) f.App.On("DeleteJob", mock.Anything, id).Return(sql.ErrNoRows) }, @@ -508,7 +508,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "generic error on FindJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, gError) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -527,7 +527,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "generic error on DeleteJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, nil) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, nil) f.App.On("JobORM").Return(f.Mocks.jobORM) f.App.On("DeleteJob", mock.Anything, id).Return(gError) }, diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 9663f9dfe82..641eabdfd8b 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -238,7 +238,7 @@ func (r *Resolver) CreateFeedsManagerChainConfig(ctx context.Context, args struc return nil, err } - ccfg, err := fsvc.GetChainConfig(id) + ccfg, err := fsvc.GetChainConfig(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewCreateFeedsManagerChainConfigPayload(nil, err, nil), nil @@ -267,7 +267,7 @@ func (r *Resolver) DeleteFeedsManagerChainConfig(ctx context.Context, args struc fsvc := r.App.GetFeedsService() - ccfg, err := fsvc.GetChainConfig(id) + ccfg, err := fsvc.GetChainConfig(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewDeleteFeedsManagerChainConfigPayload(nil, err), nil @@ -367,7 +367,7 @@ func (r *Resolver) UpdateFeedsManagerChainConfig(ctx context.Context, args struc return nil, err } - ccfg, err := fsvc.GetChainConfig(id) + ccfg, err := fsvc.GetChainConfig(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewUpdateFeedsManagerChainConfigPayload(nil, err, nil), nil @@ -418,7 +418,7 @@ func (r *Resolver) CreateFeedsManager(ctx context.Context, args struct { return nil, err } - mgr, err := feedsService.GetManager(id) + mgr, err := feedsService.GetManager(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewCreateFeedsManagerPayload(nil, err, nil), nil @@ -541,7 +541,7 @@ func (r *Resolver) UpdateFeedsManager(ctx context.Context, args struct { return nil, err } - mgr, err = feedsService.GetManager(id) + mgr, err = feedsService.GetManager(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewUpdateFeedsManagerPayload(nil, err, nil), nil @@ -615,7 +615,7 @@ func (r *Resolver) DeleteBridge(ctx context.Context, args struct { return nil, err } - jobsUsingBridge, err := r.App.JobORM().FindJobIDsWithBridge(string(args.ID)) + jobsUsingBridge, err := r.App.JobORM().FindJobIDsWithBridge(ctx, string(args.ID)) if err != nil { return nil, err } @@ -751,7 +751,7 @@ func (r *Resolver) ApproveJobProposalSpec(ctx context.Context, args struct { return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -786,7 +786,7 @@ func (r *Resolver) CancelJobProposalSpec(ctx context.Context, args struct { return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -821,7 +821,7 @@ func (r *Resolver) RejectJobProposalSpec(ctx context.Context, args struct { return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -859,7 +859,7 @@ func (r *Resolver) UpdateJobProposalSpecDefinition(ctx context.Context, args str return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -1039,7 +1039,7 @@ func (r *Resolver) CreateJob(ctx context.Context, args struct { case job.VRF: jb, err = vrfcommon.ValidatedVRFSpec(args.Input.TOML) case job.Webhook: - jb, err = webhook.ValidatedWebhookSpec(args.Input.TOML, r.App.GetExternalInitiatorManager()) + jb, err = webhook.ValidatedWebhookSpec(ctx, args.Input.TOML, r.App.GetExternalInitiatorManager()) case job.BlockhashStore: jb, err = blockhashstore.ValidatedSpec(args.Input.TOML) case job.BlockHeaderFeeder: @@ -1085,7 +1085,7 @@ func (r *Resolver) DeleteJob(ctx context.Context, args struct { return nil, err } - j, err := r.App.JobORM().FindJobWithoutSpecErrors(id) + j, err := r.App.JobORM().FindJobWithoutSpecErrors(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewDeleteJobPayload(r.App, nil, err), nil @@ -1119,7 +1119,7 @@ func (r *Resolver) DismissJobError(ctx context.Context, args struct { return nil, err } - specErr, err := r.App.JobORM().FindSpecError(id) + specErr, err := r.App.JobORM().FindSpecError(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewDismissJobErrorPayload(nil, err), nil diff --git a/core/web/resolver/query.go b/core/web/resolver/query.go index e24974e765d..9de678adc51 100644 --- a/core/web/resolver/query.go +++ b/core/web/resolver/query.go @@ -132,7 +132,7 @@ func (r *Resolver) FeedsManager(ctx context.Context, args struct{ ID graphql.ID return nil, err } - mgr, err := r.App.GetFeedsService().GetManager(id) + mgr, err := r.App.GetFeedsService().GetManager(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewFeedsManagerPayload(nil, err), nil @@ -149,7 +149,7 @@ func (r *Resolver) FeedsManagers(ctx context.Context) (*FeedsManagersPayloadReso return nil, err } - mgrs, err := r.App.GetFeedsService().ListManagers() + mgrs, err := r.App.GetFeedsService().ListManagers(ctx) if err != nil { return nil, err } @@ -168,7 +168,7 @@ func (r *Resolver) Job(ctx context.Context, args struct{ ID graphql.ID }) (*JobP return nil, err } - j, err := r.App.JobORM().FindJobWithoutSpecErrors(id) + j, err := r.App.JobORM().FindJobWithoutSpecErrors(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewJobPayload(r.App, nil, err), nil @@ -197,7 +197,7 @@ func (r *Resolver) Jobs(ctx context.Context, args struct { offset := pageOffset(args.Offset) limit := pageLimit(args.Limit) - jobs, count, err := r.App.JobORM().FindJobs(offset, limit) + jobs, count, err := r.App.JobORM().FindJobs(ctx, offset, limit) if err != nil { return nil, err } @@ -328,7 +328,7 @@ func (r *Resolver) JobProposal(ctx context.Context, args struct { return nil, err } - jp, err := r.App.GetFeedsService().GetJobProposal(id) + jp, err := r.App.GetFeedsService().GetJobProposal(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewJobProposalPayload(nil, err), nil @@ -377,7 +377,7 @@ func (r *Resolver) JobRuns(ctx context.Context, args struct { limit := pageLimit(args.Limit) offset := pageOffset(args.Offset) - runs, count, err := r.App.JobORM().PipelineRuns(nil, offset, limit) + runs, count, err := r.App.JobORM().PipelineRuns(ctx, nil, offset, limit) if err != nil { return nil, err } @@ -397,7 +397,7 @@ func (r *Resolver) JobRun(ctx context.Context, args struct { return nil, err } - jr, err := r.App.JobORM().FindPipelineRunByID(id) + jr, err := r.App.JobORM().FindPipelineRunByID(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewJobRunPayload(nil, r.App, err), nil diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index 7021576fdcf..43682c14ead 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" @@ -35,7 +36,7 @@ func TestResolver_CronSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Cron, CronSpec: &job.CronSpec{ CronSchedule: "CRON_TZ=UTC 0 0 1 1 *", @@ -89,7 +90,7 @@ func TestResolver_DirectRequestSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.DirectRequest, DirectRequestSpec: &job.DirectRequestSpec{ ContractAddress: contractAddress, @@ -154,7 +155,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.FluxMonitor, FluxMonitorSpec: &job.FluxMonitorSpec{ ContractAddress: contractAddress, @@ -221,7 +222,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.FluxMonitor, FluxMonitorSpec: &job.FluxMonitorSpec{ ContractAddress: contractAddress, @@ -304,7 +305,7 @@ func TestResolver_KeeperSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Keeper, KeeperSpec: &job.KeeperSpec{ ContractAddress: contractAddress, @@ -368,7 +369,7 @@ func TestResolver_OCRSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.OffchainReporting, OCROracleSpec: &job.OCROracleSpec{ BlockchainTimeout: models.Interval(1 * time.Minute), @@ -473,7 +474,7 @@ func TestResolver_OCR2Spec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.OffchainReporting2, OCR2OracleSpec: &job.OCR2OracleSpec{ BlockchainTimeout: models.Interval(1 * time.Minute), @@ -575,7 +576,7 @@ func TestResolver_VRFSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.VRF, VRFSpec: &job.VRFSpec{ BatchCoordinatorAddress: &batchCoordinatorAddress, @@ -671,7 +672,7 @@ func TestResolver_WebhookSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Webhook, WebhookSpec: &job.WebhookSpec{ CreatedAt: f.Timestamp(), @@ -740,7 +741,7 @@ func TestResolver_BlockhashStoreSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.BlockhashStore, BlockhashStoreSpec: &job.BlockhashStoreSpec{ CoordinatorV1Address: &coordinatorV1Address, @@ -844,7 +845,7 @@ func TestResolver_BlockHeaderFeederSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.BlockHeaderFeeder, BlockHeaderFeederSpec: &job.BlockHeaderFeederSpec{ CoordinatorV1Address: &coordinatorV1Address, @@ -931,7 +932,7 @@ func TestResolver_BootstrapSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Bootstrap, BootstrapSpec: &job.BootstrapSpec{ ID: id, @@ -1003,7 +1004,7 @@ func TestResolver_WorkflowSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Workflow, WorkflowSpec: &job.WorkflowSpec{ ID: id, @@ -1061,7 +1062,7 @@ func TestResolver_GatewaySpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Gateway, GatewaySpec: &job.GatewaySpec{ ID: id, diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index 759a380d15c..38c3ed62017 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 69d56974130..75fad4d2fc9 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -240,6 +240,10 @@ LatestReportDeadline = '1m42s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 123 +TransmitTimeout = '3m54s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 13 diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index a6cba2aaac3..7aa3bb50b35 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/core/web/router.go b/core/web/router.go index c327583a005..158ea4b411f 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -292,6 +292,8 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { rc := ReplayController{app} authv2.POST("/replay_from_block/:number", auth.RequiresRunRole(rc.ReplayFromBlock)) + lcaC := LCAController{app} + authv2.GET("/find_lca", auth.RequiresRunRole(lcaC.FindLCA)) csakc := CSAKeysController{app} authv2.GET("/keys/csa", csakc.Index) diff --git a/core/web/sessions_controller_test.go b/core/web/sessions_controller_test.go index cd63628390e..049be4e2b69 100644 --- a/core/web/sessions_controller_test.go +++ b/core/web/sessions_controller_test.go @@ -8,10 +8,10 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -25,7 +25,7 @@ func TestSessionsController_Create(t *testing.T) { ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) user := cltest.MustRandomUser(t) require.NoError(t, app.AuthenticationProvider().CreateUser(ctx, &user)) @@ -44,6 +44,7 @@ func TestSessionsController_Create(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctx := testutils.Context(t) body := fmt.Sprintf(`{"email":"%s","password":"%s"}`, test.email, test.password) request, err := http.NewRequestWithContext(ctx, "POST", app.Server.URL+"/sessions", bytes.NewBufferString(body)) assert.NoError(t, err) @@ -78,9 +79,10 @@ func TestSessionsController_Create(t *testing.T) { } } -func mustInsertSession(t *testing.T, q pg.Q, session *sessions.Session) { +func mustInsertSession(t *testing.T, ds sqlutil.DataSource, session *sessions.Session) { + ctx := testutils.Context(t) sql := "INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, $3, $4) RETURNING *" - _, err := q.Exec(sql, session.ID, session.Email, session.LastUsed, session.CreatedAt) + _, err := ds.ExecContext(ctx, sql, session.ID, session.Email, session.LastUsed, session.CreatedAt) require.NoError(t, err) } @@ -97,8 +99,7 @@ func TestSessionsController_Create_ReapSessions(t *testing.T) { staleSession := cltest.NewSession() staleSession.LastUsed = time.Now().Add(-cltest.MustParseDuration(t, "241h")) staleSession.Email = user.Email - q := pg.NewQ(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) - mustInsertSession(t, q, &staleSession) + mustInsertSession(t, app.GetDB(), &staleSession) body := fmt.Sprintf(`{"email":"%s","password":"%s"}`, user.Email, cltest.Password) req, err := http.NewRequestWithContext(ctx, "POST", app.Server.URL+"/sessions", bytes.NewBufferString(body)) @@ -127,15 +128,14 @@ func TestSessionsController_Destroy(t *testing.T) { ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) user := cltest.MustRandomUser(t) require.NoError(t, app.AuthenticationProvider().CreateUser(ctx, &user)) correctSession := sessions.NewSession() correctSession.Email = user.Email - q := pg.NewQ(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) - mustInsertSession(t, q, &correctSession) + mustInsertSession(t, app.GetDB(), &correctSession) client := clhttptest.NewTestLocalOnlyHTTPClient() tests := []struct { @@ -148,6 +148,7 @@ func TestSessionsController_Destroy(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctx := testutils.Context(t) cookie := cltest.MustGenerateSessionCookie(t, test.sessionID) request, err := http.NewRequestWithContext(ctx, "DELETE", app.Server.URL+"/sessions", nil) assert.NoError(t, err) @@ -173,8 +174,7 @@ func TestSessionsController_Destroy_ReapSessions(t *testing.T) { client := clhttptest.NewTestLocalOnlyHTTPClient() app := cltest.NewApplicationEVMDisabled(t) - q := pg.NewQ(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) user := cltest.MustRandomUser(t) require.NoError(t, app.AuthenticationProvider().CreateUser(ctx, &user)) @@ -182,13 +182,13 @@ func TestSessionsController_Destroy_ReapSessions(t *testing.T) { correctSession := sessions.NewSession() correctSession.Email = user.Email - mustInsertSession(t, q, &correctSession) + mustInsertSession(t, app.GetDB(), &correctSession) cookie := cltest.MustGenerateSessionCookie(t, correctSession.ID) staleSession := cltest.NewSession() staleSession.Email = user.Email staleSession.LastUsed = time.Now().Add(-cltest.MustParseDuration(t, "241h")) - mustInsertSession(t, q, &staleSession) + mustInsertSession(t, app.GetDB(), &staleSession) request, err := http.NewRequestWithContext(ctx, "DELETE", app.Server.URL+"/sessions", nil) assert.NoError(t, err) diff --git a/crib/.env.example b/crib/.env.example index 703c7bf7f83..e24473a9a22 100644 --- a/crib/.env.example +++ b/crib/.env.example @@ -13,5 +13,15 @@ DEVSPACE_INGRESS_CERT_ARN= # Time to wait for pods to be in `Ready` condition DEVSPACE_K8S_POD_WAIT_TIMEOUT=600s +# HELM repo URI for the crib-chainlink-cluster helm chart +CHAINLINK_CLUSTER_HELM_CHART_URI= + # The duration that the namespace and all of its associated resources will be kept alive. NS_TTL=72h + +## +# These are used by the shell script: cribbit.sh +## +AWS_REGION= +AWS_SSO_ROLE_NAME= +AWS_SSO_START_URL= diff --git a/crib/README.md b/crib/README.md index c9106d401cd..a88eedb5c41 100644 --- a/crib/README.md +++ b/crib/README.md @@ -26,16 +26,17 @@ Configure the cluster, see `deployments.app.helm.values` and [values.yaml](../ch Set up your K8s access -``` -export DEVSPACE_IMAGE="..." -./setup.sh ${my-personal-namespace-name-crib} -``` +Copy the `.env.example` file to `.env` and fill in the required values -Create a .env file based on the .env.sample file +```sh +cp crib/.env.example crib/.env +``` ```sh -cp .env.sample .env -# Fill in the required values in .env +cd crib/ +nix develop +# Pro tip: use `crib-` as a prefix for your namespace. +cribbit.sh ``` Build and deploy the current state of your repository diff --git a/crib/devspace.yaml b/crib/devspace.yaml index cc82c6a464c..213fe4c24c7 100644 --- a/crib/devspace.yaml +++ b/crib/devspace.yaml @@ -73,6 +73,8 @@ images: MACOS_SDK_DIR=$(pwd)/tools/bin/MacOSX12.3.sdk IMAGE=$image ./tools/bin/goreleaser_wrapper release --snapshot --clean --config .goreleaser.devspace.yaml docker push $image hooks: + - command: ./scripts/check_env_vars.sh + events: [ "before:deploy:app" ] - wait: running: true terminatedWithCode: 0 @@ -97,8 +99,8 @@ deployments: helm: releaseName: "app" chart: - name: cl-cluster - path: ../charts/chainlink-cluster + name: ${CHAINLINK_CLUSTER_HELM_CHART_URI} + version: 0.5.0 # for simplicity, we define all the values here # they can be defined the same way in values.yml # devspace merges these "values" with the "values.yaml" before deploy diff --git a/crib/scripts/check_env_vars.sh b/crib/scripts/check_env_vars.sh new file mode 100755 index 00000000000..55480313800 --- /dev/null +++ b/crib/scripts/check_env_vars.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# List of required environment variables +required_vars=( + "DEVSPACE_IMAGE" + "DEVSPACE_INGRESS_CIDRS" + "DEVSPACE_INGRESS_BASE_DOMAIN" + "DEVSPACE_INGRESS_CERT_ARN" + "DEVSPACE_K8S_POD_WAIT_TIMEOUT" + "CHAINLINK_CLUSTER_HELM_CHART_URI" + "NS_TTL" + ) + +missing_vars=0 # Counter for missing variables + +# Check each variable +for var in "${required_vars[@]}"; do + if [ -z "${!var}" ]; then # If variable is unset or empty + echo "Error: Environment variable $var is not set." + missing_vars=$((missing_vars + 1)) + fi +done + +# Exit with an error if any variables were missing +if [ $missing_vars -ne 0 ]; then + echo "Total missing environment variables: $missing_vars" + echo "To fix it, add missing variables in the \"crib/.env\" file." + echo "you can find example of the .env config in the \"crib/.env.example\"" + exit 1 +else + echo "All required environment variables are set." +fi \ No newline at end of file diff --git a/crib/scripts/cribbit.sh b/crib/scripts/cribbit.sh new file mode 100755 index 00000000000..316791b10cb --- /dev/null +++ b/crib/scripts/cribbit.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash + +set -euo pipefail + +############################# +# __________ +# < CRIBbit! > +# ---------- +# _ _ / +# (o)--(o) / +# /.______.\ +# \________/ +# ./ \. +# ( . , ) +# \ \_\\//_/ / +# ~~ ~~ ~~ +# +# Initialize your CRIB +# environment. +############################# + +DEVSPACE_NAMESPACE="${1:-}" +if [[ -z "${DEVSPACE_NAMESPACE}" ]]; then + echo "Usage: $0 " + exit 1 +fi + +# Bail if $DEVSPACE_NAMESPACE does not begin with a crib- prefix or does not have an override set. +if [[ ! "${DEVSPACE_NAMESPACE}" =~ ^crib- ]] && [[ -z "${CRIB_IGNORE_NAMESPACE_PREFIX:-}" ]]; then + echo "Error: DEVSPACE_NAMESPACE must begin with 'crib-' prefix." + exit 1 +fi + +# Path to the .env file +repo_root=$(git rev-parse --show-toplevel 2>/dev/null || echo ".") +env_file="${repo_root}/crib/.env" + +# Source .env file if it exists +if [[ -f "${env_file}" ]]; then + # shellcheck disable=SC1090 + source "${env_file}" +else + echo "Error: .env file not found at $env_file" + exit 1 +fi + +# List of required environment variables +required_vars=( + "AWS_REGION" + # Should be the short name and not the full IAM role ARN. + "AWS_SSO_ROLE_NAME" + # The AWS SSO start URL, e.g. https://.awsapps.com/start + "AWS_SSO_START_URL" + "DEVSPACE_IMAGE" + "HOME" +) + +missing_vars=0 # Counter for missing variables + +for var in "${required_vars[@]}"; do + if [[ -z "${!var:-}" ]]; then # If variable is unset or empty + echo "Error: Environment variable ${var} is not set." + missing_vars=$((missing_vars + 1)) + fi +done + +# Exit with an error if any variables were missing +if [[ $missing_vars -ne 0 ]]; then + echo "Error: Total missing environment variables: $missing_vars" + exit 1 +fi + +## +# Setup AWS Profile +## + +path_aws_config="$HOME/.aws/config" +aws_account_id_ecr_registry=$(echo "${DEVSPACE_IMAGE}" | cut -d'.' -f1) +aws_profile_name="staging-crib" + +if grep -q "$aws_profile_name" "$path_aws_config"; then + echo "Info: Skip updating ${path_aws_config}. Profile already set: ${aws_profile_name}" +else + cat <> "$path_aws_config" +[profile $aws_profile_name] +region=${AWS_REGION} +sso_start_url=${AWS_SSO_START_URL} +sso_region=${AWS_REGION} +sso_account_id=${aws_account_id_ecr_registry} +sso_role_name=${AWS_SSO_ROLE_NAME} +EOF + echo "Info: ${path_aws_config} modified. Added profile: ${aws_profile_name}" +fi + +echo "Info: Setting AWS Profile env var: AWS_PROFILE=${aws_profile_name}" +export AWS_PROFILE=${aws_profile_name} + +if aws sts get-caller-identity > /dev/null 2>&1; then + echo "Info: AWS credentials working." +else + echo "Info: AWS credentials not detected. Attempting to login through SSO." + aws sso login +fi + +# Check again and fail this time if not successful +if ! aws sts get-caller-identity > /dev/null 2>&1; then + echo "Error: AWS credentials still not detected. Exiting." + exit 1 +fi + +## +# Setup EKS KUBECONFIG +## + +path_kubeconfig="${KUBECONFIG:-$HOME/.kube/config}" +eks_cluster_name="${CRIB_EKS_CLUSTER_NAME:-main-stage-cluster}" +eks_alias_name="${CRIB_EKS_ALIAS_NAME:-main-stage-cluster-crib}" + +if [[ ! -f "${path_kubeconfig}" ]] || ! grep -q "name: ${eks_alias_name}" "${path_kubeconfig}"; then + echo "Info: KUBECONFIG file (${path_kubeconfig}) not found or alias (${eks_alias_name}) not found. Attempting to update kubeconfig." + aws eks update-kubeconfig \ + --name "${eks_cluster_name}" \ + --alias "${eks_alias_name}" \ + --region "${AWS_REGION}" +else + echo "Info: Alias '${eks_alias_name}' already exists in kubeconfig. No update needed." + echo "Info: Setting kubernetes context to: ${eks_alias_name}" + kubectl config use-context "${eks_alias_name}" +fi + +## +# Check Docker Daemon +## + +if docker info > /dev/null 2>&1; then + echo "Info: Docker daemon is running, authorizing registry" +else + echo "Error: Docker daemon is not running. Exiting." + exit 1 +fi + +## +# AWS ECR Login +## + +# Function to extract the host URI of the ECR registry from OCI URI +extract_ecr_host_uri() { + local ecr_uri="$1" + # Regex to capture the ECR host URI + if [[ $ecr_uri =~ oci:\/\/([0-9]+\.dkr\.ecr\.[a-zA-Z0-9-]+\.amazonaws\.com) ]]; then + echo "${BASH_REMATCH[1]}" + else + echo "No valid ECR host URI found in the URI." + echo "Have you set CHAINLINK_CLUSTER_HELM_CHART_URI env var?" + exit 1 + fi +} + +# Set env var CRIB_SKIP_ECR_LOGIN=true to skip ECR login. +if [[ -n "${CRIB_SKIP_ECR_LOGIN:-}" ]]; then + echo "Info: Skipping ECR login." +else + echo "Info: Logging docker into AWS ECR registry." + aws ecr get-login-password \ + --region "${AWS_REGION}" \ + | docker login --username AWS \ + --password-stdin "${aws_account_id_ecr_registry}.dkr.ecr.${AWS_REGION}.amazonaws.com" + + echo "Info: Logging helm into AWS ECR registry." + helm_registry_uri=$(extract_ecr_host_uri "${CHAINLINK_CLUSTER_HELM_CHART_URI}") + aws ecr get-login-password --region "${AWS_REGION}" \ + | helm registry login "$helm_registry_uri" --username AWS --password-stdin +fi + +## +# Setup DevSpace +## + +devspace use namespace "${DEVSPACE_NAMESPACE}" diff --git a/crib/setup.sh b/crib/setup.sh deleted file mode 100755 index 536bef57c75..00000000000 --- a/crib/setup.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash - -set -e -user_home="$HOME" -file_path="$user_home/.aws/config" -image="" -registry_id=$(echo "$DEVSPACE_IMAGE" | cut -d'.' -f1) - -if grep -q "staging-crib" "$file_path"; then - echo "Staging AWS config is already applied, role is 'staging-crib'" -else - cat <> "$file_path" -[profile staging-crib] -region=us-west-2 -sso_start_url=https://smartcontract.awsapps.com/start -sso_region=us-west-2 -sso_account_id=${registry_id} -sso_role_name=CRIB-ECR-Power -EOF - echo "~/.aws/config modified, added 'staging-crib" -fi - -# Login through SSO -aws sso login --profile staging-crib -# Update kubeconfig and switch context -export AWS_PROFILE=staging-crib -aws eks update-kubeconfig --name main-stage-cluster --alias main-stage-cluster-crib --profile staging-crib - -# Check if the Docker daemon is running -if docker info > /dev/null 2>&1; then - echo "Docker daemon is running, authorizing registry" -else - echo "Docker daemon is not running, exiting" - exit 1 -fi -aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin ${registry_id}.dkr.ecr.us-west-2.amazonaws.com -devspace use namespace $1 diff --git a/charts/chainlink-cluster/values-profiles/README.md b/crib/values-profiles/README.md similarity index 100% rename from charts/chainlink-cluster/values-profiles/README.md rename to crib/values-profiles/README.md diff --git a/charts/chainlink-cluster/values-profiles/values-dev.yaml.example b/crib/values-profiles/values-dev.yaml.example similarity index 100% rename from charts/chainlink-cluster/values-profiles/values-dev.yaml.example rename to crib/values-profiles/values-dev.yaml.example diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 0596fcdd84d..f93d990413f 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1698,6 +1698,33 @@ CertFile = "/path/to/client/certs.pem" # Example ``` CertFile is the path to a PEM file of trusted root certificate authority certificates +## Mercury.Transmitter +```toml +[Mercury.Transmitter] +TransmitQueueMaxSize = 10_000 # Default +TransmitTimeout = "5s" # Default +``` +Mercury.Transmitter controls settings for the mercury transmitter + +### TransmitQueueMaxSize +```toml +TransmitQueueMaxSize = 10_000 # Default +``` +TransmitQueueMaxSize controls the size of the transmit queue. This is scoped +per OCR instance. If the queue is full, the transmitter will start dropping +the oldest messages in order to make space. + +This is useful if mercury server goes offline and the nop needs to buffer +transmissions. + +### TransmitTimeout +```toml +TransmitTimeout = "5s" # Default +``` +TransmitTimeout controls how long the transmitter will wait for a response +when sending a message to the mercury server, before aborting and considering +the transmission to be failed. + ## EVM EVM defaults depend on ChainID: diff --git a/go.mod b/go.mod index 752dd110c49..6e081467bc0 100644 --- a/go.mod +++ b/go.mod @@ -72,13 +72,13 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 - github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 + github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 diff --git a/go.sum b/go.sum index 5f042f2e4c4..50cb9f3b44f 100644 --- a/go.sum +++ b/go.sum @@ -1180,10 +1180,10 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= @@ -1192,8 +1192,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index f5c91b63527..ee4309c3613 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -8,14 +8,18 @@ import ( "errors" "fmt" "math/big" + "os" "strings" "sync" "testing" "time" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/go-resty/resty/v2" + "github.com/rs/zerolog" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/keystore" @@ -33,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" ) // ContractDeploymentInterval After how many contract actions to wait before starting any more @@ -562,3 +567,100 @@ func WaitForBlockNumberToBe( } } } + +// todo - move to EVMClient +func RewindSimulatedChainToBlockNumber( + ctx context.Context, + evmClient blockchain.EVMClient, + rpcURL string, + rewindChainToBlockNumber uint64, + l zerolog.Logger, +) (uint64, error) { + latestBlockNumberBeforeReorg, err := evmClient.LatestBlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Str("RPC URL", rpcURL). + Uint64("Latest Block Number before Reorg", latestBlockNumberBeforeReorg). + Uint64("Rewind Chain to Block Number", rewindChainToBlockNumber). + Msg("Performing Reorg on chain by rewinding chain to specific block number") + + _, err = NewRPCRawClient(rpcURL).SetHeadForSimulatedChain(rewindChainToBlockNumber) + + if err != nil { + return 0, fmt.Errorf("error making reorg: %w", err) + } + + err = evmClient.WaitForEvents() + if err != nil { + return 0, fmt.Errorf("error waiting for events: %w", err) + } + + latestBlockNumberAfterReorg, err := evmClient.LatestBlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Uint64("Block Number", latestBlockNumberAfterReorg). + Msg("Latest Block Number after Reorg") + return latestBlockNumberAfterReorg, nil +} + +func GetRPCUrl(env *test_env.CLClusterTestEnv, chainID int64) (string, error) { + provider, err := env.GetRpcProvider(chainID) + if err != nil { + return "", err + } + return provider.PublicHttpUrls()[0], nil +} + +// RPCRawClient +// created separate client since method evmClient.RawJsonRPCCall fails on "invalid argument 0: json: cannot unmarshal non-string into Go value of type hexutil.Uint64" +type RPCRawClient struct { + resty *resty.Client +} + +func NewRPCRawClient(url string) *RPCRawClient { + isDebug := os.Getenv("DEBUG_RESTY") == "true" + restyClient := resty.New().SetDebug(isDebug).SetBaseURL(url) + return &RPCRawClient{ + resty: restyClient, + } +} + +func (g *RPCRawClient) SetHeadForSimulatedChain(setHeadToBlockNumber uint64) (JsonRPCResponse, error) { + var responseObject JsonRPCResponse + postBody, _ := json.Marshal(map[string]any{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_setHead", + "params": []string{hexutil.EncodeUint64(setHeadToBlockNumber)}, + }) + resp, err := g.resty.R(). + SetHeader("Content-Type", "application/json"). + SetBody(postBody). + SetResult(&responseObject). + Post("") + + if err != nil { + return JsonRPCResponse{}, fmt.Errorf("error making API request: %w", err) + } + statusCode := resp.StatusCode() + if statusCode != 200 && statusCode != 201 { + return JsonRPCResponse{}, fmt.Errorf("error invoking debug_setHead method, received unexpected status code %d: %s", statusCode, resp.String()) + } + if responseObject.Error != "" { + return JsonRPCResponse{}, fmt.Errorf("received non-empty error field: %v", responseObject.Error) + } + return responseObject, nil +} + +type JsonRPCResponse struct { + Version string `json:"jsonrpc"` + Id int `json:"id"` + Result string `json:"result,omitempty"` + Error string `json:"error,omitempty"` +} diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index fef780b695b..7c1ee634f98 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -506,7 +506,7 @@ func RequestRandomnessAndWaitForFulfillment( randomnessRequestCountPerRequest uint16, randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, -) (*contracts.CoordinatorRandomWordsFulfilled, error) { +) (*contracts.CoordinatorRandomWordsRequested, *contracts.CoordinatorRandomWordsFulfilled, error) { randomWordsRequestedEvent, err := RequestRandomness( l, consumer, @@ -520,18 +520,18 @@ func RequestRandomnessAndWaitForFulfillment( randomnessRequestCountPerRequestDeviation, ) if err != nil { - return nil, err + return nil, nil, err } - fulfillmentEvents, err := WaitRandomWordsFulfilledEvent( + randomWordsFulfilledEvent, err := WaitRandomWordsFulfilledEvent( coordinator, randomWordsRequestedEvent.RequestId, randomWordsFulfilledEventTimeout, l, ) if err != nil { - return nil, err + return nil, nil, err } - return fulfillmentEvents, nil + return randomWordsRequestedEvent, randomWordsFulfilledEvent, nil } func RequestRandomness( diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 143b1e2cd9b..26532e9b8e8 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -376,7 +376,7 @@ func RequestRandomnessAndWaitForFulfillment( isNativeBilling bool, config *vrfv2plus_config.General, l zerolog.Logger, -) (*contracts.CoordinatorRandomWordsFulfilled, error) { +) (*contracts.CoordinatorRandomWordsRequested, *contracts.CoordinatorRandomWordsFulfilled, error) { randomWordsRequestedEvent, err := RequestRandomness( consumer, coordinator, @@ -387,7 +387,7 @@ func RequestRandomnessAndWaitForFulfillment( l, ) if err != nil { - return nil, err + return nil, nil, err } randomWordsFulfilledEvent, err := WaitRandomWordsFulfilledEvent( @@ -399,9 +399,9 @@ func RequestRandomnessAndWaitForFulfillment( l, ) if err != nil { - return nil, err + return nil, nil, err } - return randomWordsFulfilledEvent, nil + return randomWordsRequestedEvent, randomWordsFulfilledEvent, nil } diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index aaccbad0602..f54d1a25936 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -8,8 +8,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" @@ -20,6 +18,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_wrapper_load_test_consumer" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" ) type VRF interface { diff --git a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go index 260af44019f..473b308dc42 100644 --- a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go +++ b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go @@ -13,12 +13,12 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) // EthereumDKG represents DKG contract diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 7eee9231b17..8bb83cc8ee4 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -308,7 +308,7 @@ func (n *ClNode) containerStartOrRestart(restartDb bool) error { // If the node secrets TOML is not set, generate it with the default template nodeSecretsToml, err := templates.NodeSecretsTemplate{ PgDbName: n.PostgresDb.DbName, - PgHost: n.PostgresDb.ContainerName, + PgHost: strings.Split(n.PostgresDb.InternalURL.Host, ":")[0], PgPort: n.PostgresDb.InternalPort, PgPassword: n.PostgresDb.Password, CustomSecrets: n.NodeSecretsConfigTOML, @@ -339,14 +339,6 @@ func (n *ClNode) containerStartOrRestart(restartDb bool) error { return fmt.Errorf("%s err: %w", ErrStartCLNodeContainer, err) } - // retries can change the container name which affects urls used later - // so update to use the name that actually started - n.ContainerName, err = container.Name(context.Background()) - if err != nil { - return err - } - n.ContainerName = strings.Replace(n.ContainerName, "/", "", -1) - clEndpoint, err := test_env.GetEndpoint(testcontext.Get(n.t), container, "http") if err != nil { return err @@ -374,7 +366,7 @@ func (n *ClNode) containerStartOrRestart(restartDb bool) error { if err != nil { return fmt.Errorf("%s err: %w", ErrConnectNodeClient, err) } - clClient.Config.InternalIP = n.ContainerName + n.Container = container n.API = clClient diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 08e50e1843e..483a4ce7211 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -6,6 +6,7 @@ go 1.21.7 replace github.com/smartcontractkit/chainlink/v2 => ../ require ( + github.com/avast/retry-go/v4 v4.5.1 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/cli/go-gh/v2 v2.0.0 github.com/ethereum/go-ethereum v1.13.8 @@ -25,9 +26,9 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-testing-framework v1.28.7-0.20240426090923-904b8dd184d8 - github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 + github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/smartcontractkit/seth v0.1.6-0.20240426090349-4ca87b1f9c8c @@ -88,7 +89,6 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect - github.com/avast/retry-go/v4 v4.5.1 // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect @@ -373,7 +373,7 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 1f0c7851683..63a2168ba49 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1511,10 +1511,10 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= @@ -1527,8 +1527,8 @@ github.com/smartcontractkit/chainlink-testing-framework v1.28.7-0.20240426090923 github.com/smartcontractkit/chainlink-testing-framework v1.28.7-0.20240426090923-904b8dd184d8/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 h1:fX/xmGm1GBsD1ZZnooNT+eWA0hiTAqFlHzOC5CY4dy8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index d15780c3e55..b2d4108a5bd 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-testing-framework v1.28.7-0.20240426090923-904b8dd184d8 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 @@ -367,13 +367,13 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 // indirect github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 // indirect - github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 // indirect + github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect github.com/soheilhy/cmux v0.1.5 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index d66560c9f4b..85f606355bc 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1502,10 +1502,10 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= @@ -1518,8 +1518,8 @@ github.com/smartcontractkit/chainlink-testing-framework v1.28.7-0.20240426090923 github.com/smartcontractkit/chainlink-testing-framework v1.28.7-0.20240426090923-904b8dd184d8/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 h1:fX/xmGm1GBsD1ZZnooNT+eWA0hiTAqFlHzOC5CY4dy8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index 71d3113e60f..d15ee18d451 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -87,7 +87,7 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { vrfv2Config := m.testConfig.General //randomly increase/decrease randomness request count per TX randomnessRequestCountPerRequest := deviateValue(*vrfv2Config.RandomnessRequestCountPerRequest, *vrfv2Config.RandomnessRequestCountPerRequestDeviation) - _, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, _, err := vrfv2.RequestRandomnessAndWaitForFulfillment( m.logger, //the same consumer is used for all requests and in all subs m.contracts.VRFV2Consumers[0], diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 8a99392fa57..6879fbe32dc 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -99,7 +99,7 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { //randomly increase/decrease randomness request count per TX reqCount := deviateValue(*m.testConfig.General.RandomnessRequestCountPerRequest, *m.testConfig.General.RandomnessRequestCountPerRequestDeviation) m.testConfig.General.RandomnessRequestCountPerRequest = &reqCount - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( //the same consumer is used for all requests and in all subs m.contracts.VRFV2PlusConsumer[0], m.contracts.CoordinatorV2Plus, diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 62c5dc84fe6..4dd23bce26f 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -63,7 +63,7 @@ func TestVRFv2Basic(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -104,7 +104,7 @@ func TestVRFv2Basic(t *testing.T) { subBalanceBeforeRequest := subscription.Balance // test and assert - randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -137,6 +137,54 @@ func TestVRFv2Basic(t *testing.T) { } }) + t.Run("VRF Node waits block confirmation number specified by the consumer in the rand request before sending fulfilment on-chain", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2.General + + consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( + testEnv, + chainID, + vrfContracts.CoordinatorV2, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + expectedBlockNumberWait := uint16(10) + testConfig.MinimumConfirmations = ptr.Ptr[uint16](expectedBlockNumberWait) + randomWordsRequestedEvent, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *testConfig.MinimumConfirmations, + *testConfig.CallbackGasLimit, + *testConfig.NumberOfWords, + *testConfig.RandomnessRequestCountPerRequest, + *testConfig.RandomnessRequestCountPerRequestDeviation, + testConfig.RandomWordsFulfilledEventTimeout.Duration, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + // check that VRF node waited at least the number of blocks specified by the consumer in the rand request min confs field + blockNumberWait := randomWordsRequestedEvent.Raw.BlockNumber - randomWordsFulfilledEvent.Raw.BlockNumber + require.GreaterOrEqual(t, blockNumberWait, uint64(expectedBlockNumberWait)) + + status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) + require.NoError(t, err, "error getting rand request status") + require.True(t, status.Fulfilled) + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + }) + t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForJobRuns, err := vrfv2.SetupNewConsumersAndSubs( @@ -161,7 +209,7 @@ func TestVRFv2Basic(t *testing.T) { require.NoError(t, err, "error reading job runs") // test and assert - _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -281,7 +329,7 @@ func TestVRFv2Basic(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subIDForOracleWithdraw, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForOracleWithDraw...) - fulfilledEventLink, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, fulfilledEventLink, err := vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -436,7 +484,7 @@ func TestVRFv2Basic(t *testing.T) { // Request randomness - should fail due to underfunded subscription randomWordsFulfilledEventTimeout := 5 * time.Second - _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -556,7 +604,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -602,7 +650,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { var fulfillmentTxFromAddresses []string for i := 0; i < newEnvConfig.NumberOfTxKeysToCreate+1; i++ { - randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -664,7 +712,7 @@ func TestVRFOwner(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -807,7 +855,7 @@ func TestVRFV2WithBHS(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -984,3 +1032,164 @@ func TestVRFV2WithBHS(t *testing.T) { require.Equal(t, 0, randomWordsRequestedEvent.Raw.BlockHash.Cmp(randRequestBlockHash)) }) } + +func TestVRFV2NodeReorg(t *testing.T) { + t.Parallel() + var ( + env *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []uint64 + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig("Smoke", tc.VRFv2) + require.NoError(t, err, "Error getting config") + vrfv2Config := config.VRFv2 + chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + + cleanupFn := func() { + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + + if evmClient.NetworkSimulated() { + l.Info(). + Str("Network Name", evmClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfv2Config.General.CancelSubsAfterTestRun { + //cancel subs and return funds to sub owner + vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) + } + } + if !*vrfv2Config.General.UseExistingEnv { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } + newEnvConfig := vrfcommon.NewEnvConfig{ + NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, + NumberOfTxKeysToCreate: 0, + UseVRFOwner: false, + UseTestCoordinator: false, + } + + env, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, config, chainID, cleanupFn, newEnvConfig, l) + require.NoError(t, err, "Error setting up VRFv2 universe") + + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + defaultWalletAddress = evmClient.GetDefaultWallet().Address() + + consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2, + config, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + t.Run("Reorg on fulfillment", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + configCopy.VRFv2.General.MinimumConfirmations = ptr.Ptr[uint16](10) + + //1. request randomness and wait for fulfillment for blockhash from Reorged Fork + randomWordsRequestedEvent, randomWordsFulfilledEventOnReorgedFork, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, + ) + require.NoError(t, err) + + // rewind chain to block number after the request was made, but before the request was fulfilled + rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //2. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlock, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) + + //3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made + require.Greater(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //3.2 ensure that chain is reorged and latest block number is less than the block number when fulfilment was performed + require.Less(t, latestBlockNumberAfterReorg, randomWordsFulfilledEventOnReorgedFork.Raw.BlockNumber) + + //4. wait for the fulfillment which VRF Node will generate for Canonical chain + _, err = vrfv2.WaitRandomWordsFulfilledEvent( + vrfContracts.CoordinatorV2, + randomWordsRequestedEvent.RequestId, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, + l, + ) + + require.NoError(t, err, "error waiting for randomness fulfilled event") + }) + + t.Run("Reorg on rand request", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + //1. set minimum confirmations to higher value so that we can be sure that request won't be fulfilled before reorg + configCopy.VRFv2.General.MinimumConfirmations = ptr.Ptr[uint16](6) + + //2. request randomness + randomWordsRequestedEvent, err := vrfv2.RequestRandomness( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + ) + require.NoError(t, err) + + // rewind chain to block number before the randomness request was made + rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //3. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlockNumber, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) + + //4. ensure that chain is reorged and latest block number is less than the block number when request was made + require.Less(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //5. ensure that rand request is not fulfilled for the request which was made on reorged fork + // For context - when performing debug_setHead on geth simulated chain and therefore rewinding chain to a previous block, + //then tx that was mined after reorg will not appear in canonical chain contrary to real world scenario + //Hence, we only verify that VRF node will not generate fulfillment for the reorged fork request + _, err = vrfContracts.CoordinatorV2.WaitForRandomWordsFulfilledEvent( + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + Timeout: time.Second * 10, + }, + ) + require.Error(t, err, "fulfillment should not be generated for the request which was made on reorged fork on Simulated Chain") + }) +} diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index c535e77ef62..ae190e060ee 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -26,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" @@ -64,7 +64,7 @@ func TestVRFv2Plus(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -106,7 +106,7 @@ func TestVRFv2Plus(t *testing.T) { subBalanceBeforeRequest := subscription.Balance // test and assert - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -163,7 +163,7 @@ func TestVRFv2Plus(t *testing.T) { subNativeTokenBalanceBeforeRequest := subscription.NativeBalance // test and assert - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -193,6 +193,52 @@ func TestVRFv2Plus(t *testing.T) { require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) + + t.Run("VRF Node waits block confirmation number specified by the consumer in the rand request before sending fulfilment on-chain", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2Plus.General + var isNativeBilling = true + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2Plus, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + expectedBlockNumberWait := uint16(10) + testConfig.MinimumConfirmations = ptr.Ptr[uint16](expectedBlockNumberWait) + randomWordsRequestedEvent, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + testConfig, + l, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + // check that VRF node waited at least the number of blocks specified by the consumer in the rand request min confs field + blockNumberWait := randomWordsRequestedEvent.Raw.BlockNumber - randomWordsFulfilledEvent.Raw.BlockNumber + require.GreaterOrEqual(t, blockNumberWait, uint64(expectedBlockNumberWait)) + + status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) + require.NoError(t, err, "error getting rand request status") + require.True(t, status.Fulfilled) + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + }) + t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) var isNativeBilling = false @@ -217,7 +263,7 @@ func TestVRFv2Plus(t *testing.T) { require.NoError(t, err, "error reading job runs") // test and assert - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -482,7 +528,7 @@ func TestVRFv2Plus(t *testing.T) { require.False(t, pendingRequestsExist, "Pending requests should not exist") configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout = ptr.Ptr(blockchain.StrDuration{Duration: 5 * time.Second}) - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -494,7 +540,7 @@ func TestVRFv2Plus(t *testing.T) { require.Error(t, err, "error should occur for waiting for fulfilment due to low sub balance") - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -622,7 +668,7 @@ func TestVRFv2Plus(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - fulfilledEventLink, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, fulfilledEventLink, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -633,7 +679,7 @@ func TestVRFv2Plus(t *testing.T) { ) require.NoError(t, err) - fulfilledEventNative, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, fulfilledEventNative, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -719,7 +765,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -766,7 +812,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { var fulfillmentTxFromAddresses []string for i := 0; i < newEnvConfig.NumberOfTxKeysToCreate+1; i++ { - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -826,7 +872,7 @@ func TestVRFv2PlusMigration(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1002,7 +1048,7 @@ func TestVRFv2PlusMigration(t *testing.T) { require.Equal(t, 0, expectedEthTotalBalanceForOldCoordinator.Cmp(oldCoordinatorEthTotalBalanceAfterMigration)) //Verify rand requests fulfills with Link Token billing - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], newCoordinator, vrfKey, @@ -1014,7 +1060,7 @@ func TestVRFv2PlusMigration(t *testing.T) { require.NoError(t, err, "error requesting randomness and waiting for fulfilment") //Verify rand requests fulfills with Native Token billing - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[1], newCoordinator, vrfKey, @@ -1249,7 +1295,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1470,7 +1516,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1618,7 +1664,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1694,7 +1740,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { 1, ) require.NoError(t, err, "error creating funded sub in replay test") - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[1], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -1817,7 +1863,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1862,7 +1908,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) l.Info().Uint16("minimumConfirmationDelay", *config.VRFv2Plus.General.MinimumConfirmations).Msg("Minimum Confirmation Delay") // test and assert - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -1878,3 +1924,162 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") } + +func TestVRFv2PlusNodeReorg(t *testing.T) { + t.Parallel() + var ( + env *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []*big.Int + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + require.NoError(t, err, "Error getting config") + vrfv2PlusConfig := config.VRFv2Plus + chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + + cleanupFn := func() { + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + + if evmClient.NetworkSimulated() { + l.Info(). + Str("Network Name", evmClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { + //cancel subs and return funds to sub owner + vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) + } + } + if !*vrfv2PlusConfig.General.UseExistingEnv { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } + newEnvConfig := vrfcommon.NewEnvConfig{ + NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, + NumberOfTxKeysToCreate: 0, + UseVRFOwner: false, + UseTestCoordinator: false, + } + + env, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, config, chainID, cleanupFn, newEnvConfig, l) + require.NoError(t, err, "Error setting up VRFv2Plus universe") + + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + defaultWalletAddress = evmClient.GetDefaultWallet().Address() + + var isNativeBilling = true + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2Plus, + config, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + t.Run("Reorg on fulfillment", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + configCopy.VRFv2Plus.General.MinimumConfirmations = ptr.Ptr[uint16](10) + + //1. request randomness and wait for fulfillment for blockhash from Reorged Fork + randomWordsRequestedEvent, randomWordsFulfilledEventOnReorgedFork, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General, + l, + ) + require.NoError(t, err) + + // rewind chain to block number after the request was made, but before the request was fulfilled + rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //2. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlock, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) + + //3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made + require.Greater(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //3.2 ensure that chain is reorged and latest block number is less than the block number when fulfilment was performed + require.Less(t, latestBlockNumberAfterReorg, randomWordsFulfilledEventOnReorgedFork.Raw.BlockNumber) + + //4. wait for the fulfillment which VRF Node will generate for Canonical chain + _, err = vrfv2plus.WaitRandomWordsFulfilledEvent( + vrfContracts.CoordinatorV2Plus, + randomWordsRequestedEvent.RequestId, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, + l, + ) + require.NoError(t, err, "error waiting for randomness fulfilled event") + }) + + t.Run("Reorg on rand request", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + //1. set minimum confirmations to higher value so that we can be sure that request won't be fulfilled before reorg + configCopy.VRFv2Plus.General.MinimumConfirmations = ptr.Ptr[uint16](6) + + //2. request randomness + randomWordsRequestedEvent, err := vrfv2plus.RequestRandomness( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General, + l, + ) + require.NoError(t, err) + + // rewind chain to block number before the randomness request was made + rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //3. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlockNumber, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) + + //4. ensure that chain is reorged and latest block number is less than the block number when request was made + require.Less(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //5. ensure that rand request is not fulfilled for the request which was made on reorged fork + // For context - when performing debug_setHead on geth simulated chain and therefore rewinding chain to a previous block, + //then tx that was mined after reorg will not appear in canonical chain contrary to real world scenario + //Hence, we only verify that VRF node will not generate fulfillment for the reorged fork request + _, err = vrfContracts.CoordinatorV2Plus.WaitForRandomWordsFulfilledEvent( + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + SubIDs: []*big.Int{subID}, + Timeout: time.Second * 10, + }, + ) + require.Error(t, err, "fulfillment should not be generated for the request which was made on reorged fork on Simulated Chain") + }) + +} diff --git a/lintconf.yaml b/lintconf.yaml deleted file mode 100644 index ff37371d476..00000000000 --- a/lintconf.yaml +++ /dev/null @@ -1,46 +0,0 @@ ---- -# Copied from: -# https://redhat-cop.github.io/ci/linting-testing-helm-charts.html -# with `min-spaces-from-content` changed to be compatible with prettier. -rules: - braces: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - brackets: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - colons: - max-spaces-before: 0 - max-spaces-after: 1 - commas: - max-spaces-before: 0 - min-spaces-after: 1 - max-spaces-after: 1 - comments: - require-starting-space: true - min-spaces-from-content: 1 - document-end: disable - document-start: disable # No --- to start a file - empty-lines: - max: 2 - max-start: 0 - max-end: 0 - hyphens: - max-spaces-after: 1 - indentation: - spaces: consistent - indent-sequences: whatever # - list indentation will handle both indentation and without - check-multi-line-strings: false - key-duplicates: enable - line-length: disable # Lines can be any length - new-line-at-end-of-file: disable - new-lines: - type: unix - trailing-spaces: enable - truthy: - level: warning - diff --git a/shell.nix b/shell.nix index 69bf202351d..1fde34fcfd8 100644 --- a/shell.nix +++ b/shell.nix @@ -57,4 +57,10 @@ mkShell' { PGDATA = "db"; CL_DATABASE_URL = "postgresql://chainlink:chainlink@localhost:5432/chainlink_test?sslmode=disable"; + + shellHook = '' + # Find the root of the git repository + repo_root=$(git rev-parse --show-toplevel 2>/dev/null || echo ".") + export PATH=$PATH:$repo_root/crib/scripts + ''; } diff --git a/testdata/scripts/blocks/help.txtar b/testdata/scripts/blocks/help.txtar index 55aaf71858d..5d362a082fd 100644 --- a/testdata/scripts/blocks/help.txtar +++ b/testdata/scripts/blocks/help.txtar @@ -9,7 +9,8 @@ USAGE: chainlink blocks command [command options] [arguments...] COMMANDS: - replay Replays block data from the given number + replay Replays block data from the given number + find-lca Find latest common block stored in DB and on chain OPTIONS: --help, -h show help diff --git a/testdata/scripts/help-all/help-all.txtar b/testdata/scripts/help-all/help-all.txtar index eeaf0da98d1..e111295abb4 100644 --- a/testdata/scripts/help-all/help-all.txtar +++ b/testdata/scripts/help-all/help-all.txtar @@ -16,6 +16,7 @@ admin users list # Lists all API users and their roles attempts # Commands for managing Ethereum Transaction Attempts attempts list # List the Transaction Attempts in descending order blocks # Commands for managing blocks +blocks find-lca # Find latest common block stored in DB and on chain blocks replay # Replays block data from the given number bridges # Commands for Bridges communicating with External Adapters bridges create # Create a new Bridge to an External Adapter @@ -132,6 +133,7 @@ node db status # Display the current database migration status. node db version # Display the current database version. node profile # Collects profile metrics from the node. node rebroadcast-transactions # Manually rebroadcast txs matching nonce range with the specified gas price. This is useful in emergencies e.g. high gas prices and/or network congestion to forcibly clear out the pending TX queue +node remove-blocks # Deletes block range and all associated data node start # Run the Chainlink node node status # Displays the health of various services running inside the node. node validate # Validate the TOML configuration and secrets that are passed as flags to the `node` command. Prints the full effective configuration, with defaults included diff --git a/testdata/scripts/node/help.txtar b/testdata/scripts/node/help.txtar index 33e1fdc90bc..875500b13df 100644 --- a/testdata/scripts/node/help.txtar +++ b/testdata/scripts/node/help.txtar @@ -13,6 +13,7 @@ COMMANDS: rebroadcast-transactions Manually rebroadcast txs matching nonce range with the specified gas price. This is useful in emergencies e.g. high gas prices and/or network congestion to forcibly clear out the pending TX queue validate Validate the TOML configuration and secrets that are passed as flags to the `node` command. Prints the full effective configuration, with defaults included db Commands for managing the database. + remove-blocks Deletes block range and all associated data OPTIONS: --config value, -c value TOML configuration file(s) via flag, or raw TOML via env var. If used, legacy env vars must not be set. Multiple files can be used (-c configA.toml -c configB.toml), and they are applied in order with duplicated fields overriding any earlier values. If the 'CL_CONFIG' env var is specified, it is always processed last with the effect of being the final override. [$CL_CONFIG] diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index dd3af5f91b6..a8e8e41750d 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -242,6 +242,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 15a476460da..feaf546f022 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -286,6 +286,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index cc8b4577bfb..b37fed41150 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -286,6 +286,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index c578d200923..6ae02ab38f4 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -286,6 +286,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 91ae520532d..45c97477bd5 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -271,6 +271,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index a5e4b766b6e..df0118bbbbf 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -276,6 +276,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index c220d7f2e5f..edb07fd5e4f 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -283,6 +283,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 018aaf95f4c..cf121e959e1 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -265,6 +265,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/tools/bin/codecov b/tools/bin/codecov deleted file mode 100755 index 36513ce06df..00000000000 --- a/tools/bin/codecov +++ /dev/null @@ -1,1888 +0,0 @@ -#!/usr/bin/env bash - -# Apache License Version 2.0, January 2004 -# https://github.com/codecov/codecov-bash/blob/master/LICENSE - -set -e +o pipefail - -VERSION="1.0.6" - -codecov_flags=( ) -url="https://codecov.io" -env="$CODECOV_ENV" -service="" -token="" -search_in="" -# shellcheck disable=SC2153 -flags="$CODECOV_FLAGS" -exit_with=0 -curlargs="" -curlawsargs="" -dump="0" -clean="0" -curl_s="-s" -name="$CODECOV_NAME" -include_cov="" -exclude_cov="" -ddp="$HOME/Library/Developer/Xcode/DerivedData" -xp="" -files="" -save_to="" -direct_file_upload="" -cacert="$CODECOV_CA_BUNDLE" -gcov_ignore="-not -path './bower_components/**' -not -path './node_modules/**' -not -path './vendor/**'" -gcov_include="" - -ft_gcov="1" -ft_coveragepy="1" -ft_fix="1" -ft_search="1" -ft_s3="1" -ft_network="1" -ft_xcodellvm="1" -ft_xcodeplist="0" -ft_gcovout="1" -ft_html="0" -ft_yaml="0" - -_git_root=$(git rev-parse --show-toplevel 2>/dev/null || hg root 2>/dev/null || echo "$PWD") -git_root="$_git_root" -remote_addr="" -if [ "$git_root" = "$PWD" ]; -then - git_root="." -fi - -branch_o="" -build_o="" -commit_o="" -pr_o="" -prefix_o="" -network_filter_o="" -search_in_o="" -slug_o="" -tag_o="" -url_o="" -git_ls_files_recurse_submodules_o="" -package="bash" - -commit="$VCS_COMMIT_ID" -branch="$VCS_BRANCH_NAME" -pr="$VCS_PULL_REQUEST" -slug="$VCS_SLUG" -tag="$VCS_TAG" -build_url="$CI_BUILD_URL" -build="$CI_BUILD_ID" -job="$CI_JOB_ID" - -beta_xcode_partials="" - -proj_root="$git_root" -gcov_exe="gcov" -gcov_arg="" - -b="\033[0;36m" -g="\033[0;32m" -r="\033[0;31m" -e="\033[0;90m" -y="\033[0;33m" -x="\033[0m" - -show_help() { -cat << EOF - - Codecov Bash $VERSION - - Global report uploading tool for Codecov - Documentation at https://docs.codecov.io/docs - Contribute at https://github.com/codecov/codecov-bash - - - -h Display this help and exit - -f FILE Target file(s) to upload - - -f "path/to/file" only upload this file - skips searching unless provided patterns below - - -f '!*.bar' ignore all files at pattern *.bar - -f '*.foo' include all files at pattern *.foo - Must use single quotes. - This is non-exclusive, use -s "*.foo" to match specific paths. - - -s DIR Directory to search for coverage reports. - Already searches project root and artifact folders. - -t TOKEN Set the private repository token - (option) set environment variable CODECOV_TOKEN=:uuid - - -t @/path/to/token_file - -t uuid - - -n NAME Custom defined name of the upload. Visible in Codecov UI - - -e ENV Specify environment variables to be included with this build - Also accepting environment variables: CODECOV_ENV=VAR,VAR2 - - -e VAR,VAR2 - - -k prefix Prefix filepaths to help resolve path fixing - - -i prefix Only include files in the network with a certain prefix. Useful for upload-specific path fixing - - -X feature Toggle functionalities - - -X gcov Disable gcov - -X coveragepy Disable python coverage - -X fix Disable report fixing - -X search Disable searching for reports - -X xcode Disable xcode processing - -X network Disable uploading the file network - -X gcovout Disable gcov output - -X html Enable coverage for HTML files - -X recursesubs Enable recurse submodules in git projects when searching for source files - -X yaml Enable coverage for YAML files - - -N The commit SHA of the parent for which you are uploading coverage. If not present, - the parent will be determined using the API of your repository provider. - When using the repository provider's API, the parent is determined via finding - the closest ancestor to the commit. - - -R root dir Used when not in git/hg project to identify project root directory - -F flag Flag the upload to group coverage metrics - - -F unittests This upload is only unittests - -F integration This upload is only integration tests - -F ui,chrome This upload is Chrome - UI tests - - -c Move discovered coverage reports to the trash - -z FILE Upload specified file directly to Codecov and bypass all report generation. - This is inteded to be used only with a pre-formatted Codecov report and is not - expected to work under any other circumstances. - -Z Exit with 1 if not successful. Default will Exit with 0 - - -- xcode -- - -D Custom Derived Data Path for Coverage.profdata and gcov processing - Default '~/Library/Developer/Xcode/DerivedData' - -J Specify packages to build coverage. Uploader will only build these packages. - This can significantly reduces time to build coverage reports. - - -J 'MyAppName' Will match "MyAppName" and "MyAppNameTests" - -J '^ExampleApp$' Will match only "ExampleApp" not "ExampleAppTests" - - -- gcov -- - -g GLOB Paths to ignore during gcov gathering - -G GLOB Paths to include during gcov gathering - -p dir Project root directory - Also used when preparing gcov - -x gcovexe gcov executable to run. Defaults to 'gcov' - -a gcovargs extra arguments to pass to gcov - - -- Override CI Environment Variables -- - These variables are automatically detected by popular CI providers - - -B branch Specify the branch name - -C sha Specify the commit sha - -P pr Specify the pull request number - -b build Specify the build number - -T tag Specify the git tag - - -- Enterprise -- - -u URL Set the target url for Enterprise customers - Not required when retrieving the bash uploader from your CCE - (option) Set environment variable CODECOV_URL=https://my-hosted-codecov.com - -r SLUG owner/repo slug used instead of the private repo token in Enterprise - (option) set environment variable CODECOV_SLUG=:owner/:repo - (option) set in your codecov.yml "codecov.slug" - -S PATH File path to your cacert.pem file used to verify ssl with Codecov Enterprise (optional) - (option) Set environment variable: CODECOV_CA_BUNDLE="/path/to/ca.pem" - -U curlargs Extra curl arguments to communicate with Codecov. e.g., -U "--proxy http://http-proxy" - -A curlargs Extra curl arguments to communicate with AWS. - - -- Debugging -- - -d Don't upload, but dump upload file to stdout - -q PATH Write upload file to path - -K Remove color from the output - -v Verbose mode - -EOF -} - - -say() { - echo -e "$1" -} - - -urlencode() { - echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//' -} - -swiftcov() { - _dir=$(dirname "$1" | sed 's/\(Build\).*/\1/g') - for _type in app framework xctest - do - find "$_dir" -name "*.$_type" | while read -r f - do - _proj=${f##*/} - _proj=${_proj%."$_type"} - if [ "$2" = "" ] || [ "$(echo "$_proj" | grep -i "$2")" != "" ]; - then - say " $g+$x Building reports for $_proj $_type" - dest=$([ -f "$f/$_proj" ] && echo "$f/$_proj" || echo "$f/Contents/MacOS/$_proj") - # shellcheck disable=SC2001 - _proj_name=$(echo "$_proj" | sed -e 's/[[:space:]]//g') - # shellcheck disable=SC2086 - xcrun llvm-cov show $beta_xcode_partials -instr-profile "$1" "$dest" > "$_proj_name.$_type.coverage.txt" \ - || say " ${r}x>${x} llvm-cov failed to produce results for $dest" - fi - done - done -} - - -# Credits to: https://gist.github.com/pkuczynski/8665367 -parse_yaml() { - local prefix=$2 - local s='[[:space:]]*' w='[a-zA-Z0-9_]*' - local fs - fs=$(echo @|tr @ '\034') - sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ - -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" | - awk -F"$fs" '{ - indent = length($1)/2; - vname[indent] = $2; - for (i in vname) {if (i > indent) {delete vname[i]}} - if (length($3) > 0) { - vn=""; if (indent > 0) {vn=(vn)(vname[0])("_")} - printf("%s%s%s=\"%s\"\n", "'"$prefix"'",vn, $2, $3); - } - }' -} - -if [ $# != 0 ]; -then - while getopts "a:A:b:B:cC:dD:e:f:F:g:G:hi:J:k:Kn:p:P:Q:q:r:R:s:S:t:T:u:U:vx:X:Zz:N:-" o - do - codecov_flags+=( "$o" ) - case "$o" in - "-") - echo -e "${r}Long options are not supported${x}" - exit 2 - ;; - "?") - ;; - "N") - parent=$OPTARG - ;; - "a") - gcov_arg=$OPTARG - ;; - "A") - curlawsargs="$OPTARG" - ;; - "b") - build_o="$OPTARG" - ;; - "B") - branch_o="$OPTARG" - ;; - "c") - clean="1" - ;; - "C") - commit_o="$OPTARG" - ;; - "d") - dump="1" - ;; - "D") - ddp="$OPTARG" - ;; - "e") - env="$env,$OPTARG" - ;; - "f") - if [ "${OPTARG::1}" = "!" ]; - then - exclude_cov="$exclude_cov -not -path '${OPTARG:1}'" - - elif [[ "$OPTARG" = *"*"* ]]; - then - include_cov="$include_cov -or -path '$OPTARG'" - - else - ft_search=0 - if [ "$files" = "" ]; - then - files="$OPTARG" - else - files="$files -$OPTARG" - fi - fi - ;; - "F") - if [ "$flags" = "" ]; - then - flags="$OPTARG" - else - flags="$flags,$OPTARG" - fi - ;; - "g") - gcov_ignore="$gcov_ignore -not -path '$OPTARG'" - ;; - "G") - gcov_include="$gcov_include -path '$OPTARG'" - ;; - "h") - show_help - exit 0; - ;; - "i") - network_filter_o="$OPTARG" - ;; - "J") - ft_xcodellvm="1" - ft_xcodeplist="0" - if [ "$xp" = "" ]; - then - xp="$OPTARG" - else - xp="$xp\|$OPTARG" - fi - ;; - "k") - prefix_o=$(echo "$OPTARG" | sed -e 's:^/*::' -e 's:/*$::') - ;; - "K") - b="" - g="" - r="" - e="" - x="" - ;; - "n") - name="$OPTARG" - ;; - "p") - proj_root="$OPTARG" - ;; - "P") - pr_o="$OPTARG" - ;; - "Q") - # this is only meant for Codecov packages to overwrite - package="$OPTARG" - ;; - "q") - save_to="$OPTARG" - ;; - "r") - slug_o="$OPTARG" - ;; - "R") - git_root="$OPTARG" - ;; - "s") - if [ "$search_in_o" = "" ]; - then - search_in_o="$OPTARG" - else - search_in_o="$search_in_o $OPTARG" - fi - ;; - "S") - # shellcheck disable=SC2089 - cacert="--cacert \"$OPTARG\"" - ;; - "t") - if [ "${OPTARG::1}" = "@" ]; - then - token=$(< "${OPTARG:1}" tr -d ' \n') - else - token="$OPTARG" - fi - ;; - "T") - tag_o="$OPTARG" - ;; - "u") - url_o=$(echo "$OPTARG" | sed -e 's/\/$//') - ;; - "U") - curlargs="$OPTARG" - ;; - "v") - set -x - curl_s="" - ;; - "x") - gcov_exe=$OPTARG - ;; - "X") - if [ "$OPTARG" = "gcov" ]; - then - ft_gcov="0" - elif [ "$OPTARG" = "coveragepy" ] || [ "$OPTARG" = "py" ]; - then - ft_coveragepy="0" - elif [ "$OPTARG" = "gcovout" ]; - then - ft_gcovout="0" - elif [ "$OPTARG" = "xcodellvm" ]; - then - ft_xcodellvm="1" - ft_xcodeplist="0" - elif [ "$OPTARG" = "fix" ] || [ "$OPTARG" = "fixes" ]; - then - ft_fix="0" - elif [ "$OPTARG" = "xcode" ]; - then - ft_xcodellvm="0" - ft_xcodeplist="0" - elif [ "$OPTARG" = "search" ]; - then - ft_search="0" - elif [ "$OPTARG" = "xcodepartials" ]; - then - beta_xcode_partials="-use-color" - elif [ "$OPTARG" = "network" ]; - then - ft_network="0" - elif [ "$OPTARG" = "s3" ]; - then - ft_s3="0" - elif [ "$OPTARG" = "html" ]; - then - ft_html="1" - elif [ "$OPTARG" = "recursesubs" ]; - then - git_ls_files_recurse_submodules_o="--recurse-submodules" - elif [ "$OPTARG" = "yaml" ]; - then - ft_yaml="1" - fi - ;; - "Z") - exit_with=1 - ;; - "z") - direct_file_upload="$OPTARG" - ft_gcov="0" - ft_coveragepy="0" - ft_fix="0" - ft_search="0" - ft_network="0" - ft_xcodellvm="0" - ft_gcovout="0" - include_cov="" - ;; - *) - echo -e "${r}Unexpected flag not supported${x}" - ;; - esac - done -fi - -say " - _____ _ - / ____| | | -| | ___ __| | ___ ___ _____ __ -| | / _ \\ / _\` |/ _ \\/ __/ _ \\ \\ / / -| |___| (_) | (_| | __/ (_| (_) \\ V / - \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/ - Bash-$VERSION - -" - -# check for installed tools -# git/hg -if [ "$direct_file_upload" = "" ]; -then - if [ -x "$(command -v git)" ]; - then - say "$b==>$x $(git --version) found" - else - say "$y==>$x git not installed, testing for mercurial" - if [ -x "$(command -v hg)" ]; - then - say "$b==>$x $(hg --version) found" - else - say "$r==>$x git nor mercurial are installed. Uploader may fail or have unintended consequences" - fi - fi -fi -# curl -if [ -x "$(command -v curl)" ]; -then - say "$b==>$x $(curl --version)" -else - say "$r==>$x curl not installed. Exiting." - exit ${exit_with}; -fi - -search_in="$proj_root" - -#shellcheck disable=SC2154 -if [ "$JENKINS_URL" != "" ]; -then - say "$e==>$x Jenkins CI detected." - # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project - # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables - service="jenkins" - - # shellcheck disable=SC2154 - if [ "$ghprbSourceBranch" != "" ]; - then - branch="$ghprbSourceBranch" - elif [ "$GIT_BRANCH" != "" ]; - then - branch="$GIT_BRANCH" - elif [ "$BRANCH_NAME" != "" ]; - then - branch="$BRANCH_NAME" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbActualCommit" != "" ]; - then - commit="$ghprbActualCommit" - elif [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbPullId" != "" ]; - then - pr="$ghprbPullId" - elif [ "$CHANGE_ID" != "" ]; - then - pr="$CHANGE_ID" - fi - - build="$BUILD_NUMBER" - # shellcheck disable=SC2153 - build_url=$(urlencode "$BUILD_URL") - -elif [ "$CI" = "true" ] && [ "$TRAVIS" = "true" ] && [ "$SHIPPABLE" != "true" ]; -then - say "$e==>$x Travis CI detected." - # https://docs.travis-ci.com/user/environment-variables/ - service="travis" - commit="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}" - build="$TRAVIS_JOB_NUMBER" - pr="$TRAVIS_PULL_REQUEST" - job="$TRAVIS_JOB_ID" - slug="$TRAVIS_REPO_SLUG" - env="$env,TRAVIS_OS_NAME" - tag="$TRAVIS_TAG" - if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ]; - then - branch="${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" - fi - - language=$(compgen -A variable | grep "^TRAVIS_.*_VERSION$" | head -1) - if [ "$language" != "" ]; - then - env="$env,${!language}" - fi - -elif [ "$CODEBUILD_CI" = "true" ]; -then - say "$e==>$x AWS Codebuild detected." - # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html - service="codebuild" - commit="$CODEBUILD_RESOLVED_SOURCE_VERSION" - build="$CODEBUILD_BUILD_ID" - branch="$(echo "$CODEBUILD_WEBHOOK_HEAD_REF" | sed 's/^refs\/heads\///')" - if [ "${CODEBUILD_SOURCE_VERSION/pr}" = "$CODEBUILD_SOURCE_VERSION" ] ; then - pr="false" - else - pr="$(echo "$CODEBUILD_SOURCE_VERSION" | sed 's/^pr\///')" - fi - job="$CODEBUILD_BUILD_ID" - slug="$(echo "$CODEBUILD_SOURCE_REPO_URL" | sed 's/^.*:\/\/[^\/]*\///' | sed 's/\.git$//')" - -elif [ "$CI" = "true" ] && [ "$CI_NAME" = "codeship" ]; -then - say "$e==>$x Codeship CI detected." - # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/ - service="codeship" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - build_url=$(urlencode "$CI_BUILD_URL") - commit="$CI_COMMIT_ID" - -elif [ -n "$CF_BUILD_URL" ] && [ -n "$CF_BUILD_ID" ]; -then - say "$e==>$x Codefresh CI detected." - # https://docs.codefresh.io/v1.0/docs/variables - service="codefresh" - branch="$CF_BRANCH" - build="$CF_BUILD_ID" - build_url=$(urlencode "$CF_BUILD_URL") - commit="$CF_REVISION" - -elif [ "$TEAMCITY_VERSION" != "" ]; -then - say "$e==>$x TeamCity CI detected." - # https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters - # https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/74847298 - if [ "$TEAMCITY_BUILD_BRANCH" = '' ]; - then - echo " Teamcity does not automatically make build parameters available as environment variables." - echo " Add the following environment parameters to the build configuration" - echo " env.TEAMCITY_BUILD_BRANCH = %teamcity.build.branch%" - echo " env.TEAMCITY_BUILD_ID = %teamcity.build.id%" - echo " env.TEAMCITY_BUILD_URL = %teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%" - echo " env.TEAMCITY_BUILD_COMMIT = %system.build.vcs.number%" - echo " env.TEAMCITY_BUILD_REPOSITORY = %vcsroot..url%" - fi - service="teamcity" - branch="$TEAMCITY_BUILD_BRANCH" - build="$TEAMCITY_BUILD_ID" - build_url=$(urlencode "$TEAMCITY_BUILD_URL") - if [ "$TEAMCITY_BUILD_COMMIT" != "" ]; - then - commit="$TEAMCITY_BUILD_COMMIT" - else - commit="$BUILD_VCS_NUMBER" - fi - remote_addr="$TEAMCITY_BUILD_REPOSITORY" - -elif [ "$CI" = "true" ] && [ "$CIRCLECI" = "true" ]; -then - say "$e==>$x Circle CI detected." - # https://circleci.com/docs/environment-variables - service="circleci" - branch="$CIRCLE_BRANCH" - build="$CIRCLE_BUILD_NUM" - job="$CIRCLE_NODE_INDEX" - if [ "$CIRCLE_PROJECT_REPONAME" != "" ]; - then - slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" - else - # git@github.com:owner/repo.git - slug="${CIRCLE_REPOSITORY_URL##*:}" - # owner/repo.git - slug="${slug%%.git}" - fi - pr="${CIRCLE_PULL_REQUEST##*/}" - commit="$CIRCLE_SHA1" - search_in="$search_in $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS" - -elif [ "$BUDDYBUILD_BRANCH" != "" ]; -then - say "$e==>$x buddybuild detected" - # http://docs.buddybuild.com/v6/docs/custom-prebuild-and-postbuild-steps - service="buddybuild" - branch="$BUDDYBUILD_BRANCH" - build="$BUDDYBUILD_BUILD_NUMBER" - build_url="https://dashboard.buddybuild.com/public/apps/$BUDDYBUILD_APP_ID/build/$BUDDYBUILD_BUILD_ID" - # BUDDYBUILD_TRIGGERED_BY - if [ "$ddp" = "$HOME/Library/Developer/Xcode/DerivedData" ]; - then - ddp="/private/tmp/sandbox/${BUDDYBUILD_APP_ID}/bbtest" - fi - -elif [ "${bamboo_planRepository_revision}" != "" ]; -then - say "$e==>$x Bamboo detected" - # https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html#Bamboovariables-Build-specificvariables - service="bamboo" - commit="${bamboo_planRepository_revision}" - # shellcheck disable=SC2154 - branch="${bamboo_planRepository_branch}" - # shellcheck disable=SC2154 - build="${bamboo_buildNumber}" - # shellcheck disable=SC2154 - build_url="${bamboo_buildResultsUrl}" - # shellcheck disable=SC2154 - remote_addr="${bamboo_planRepository_repositoryUrl}" - -elif [ "$CI" = "true" ] && [ "$BITRISE_IO" = "true" ]; -then - # http://devcenter.bitrise.io/faq/available-environment-variables/ - say "$e==>$x Bitrise CI detected." - service="bitrise" - branch="$BITRISE_GIT_BRANCH" - build="$BITRISE_BUILD_NUMBER" - build_url=$(urlencode "$BITRISE_BUILD_URL") - pr="$BITRISE_PULL_REQUEST" - if [ "$GIT_CLONE_COMMIT_HASH" != "" ]; - then - commit="$GIT_CLONE_COMMIT_HASH" - fi - -elif [ "$CI" = "true" ] && [ "$SEMAPHORE" = "true" ]; -then - say "$e==>$x Semaphore CI detected." -# https://docs.semaphoreci.com/ci-cd-environment/environment-variables/#semaphore-related - service="semaphore" - branch="$SEMAPHORE_GIT_BRANCH" - build="$SEMAPHORE_WORKFLOW_NUMBER" - job="$SEMAPHORE_JOB_ID" - pr="$PULL_REQUEST_NUMBER" - slug="$SEMAPHORE_REPO_SLUG" - commit="$REVISION" - env="$env,SEMAPHORE_TRIGGER_SOURCE" - -elif [ "$CI" = "true" ] && [ "$BUILDKITE" = "true" ]; -then - say "$e==>$x Buildkite CI detected." - # https://buildkite.com/docs/guides/environment-variables - service="buildkite" - branch="$BUILDKITE_BRANCH" - build="$BUILDKITE_BUILD_NUMBER" - job="$BUILDKITE_JOB_ID" - build_url=$(urlencode "$BUILDKITE_BUILD_URL") - slug="$BUILDKITE_PROJECT_SLUG" - commit="$BUILDKITE_COMMIT" - if [[ "$BUILDKITE_PULL_REQUEST" != "false" ]]; then - pr="$BUILDKITE_PULL_REQUEST" - fi - tag="$BUILDKITE_TAG" - -elif [ "$CI" = "drone" ] || [ "$DRONE" = "true" ]; -then - say "$e==>$x Drone CI detected." - # http://docs.drone.io/env.html - # drone commits are not full shas - service="drone.io" - branch="$DRONE_BRANCH" - build="$DRONE_BUILD_NUMBER" - build_url=$(urlencode "${DRONE_BUILD_LINK}") - pr="$DRONE_PULL_REQUEST" - job="$DRONE_JOB_NUMBER" - tag="$DRONE_TAG" - -elif [ "$CI" = "true" ] && [ "$HEROKU_TEST_RUN_BRANCH" != "" ]; -then - say "$e==>$x Heroku CI detected." - # https://devcenter.heroku.com/articles/heroku-ci#environment-variables - service="heroku" - branch="$HEROKU_TEST_RUN_BRANCH" - build="$HEROKU_TEST_RUN_ID" - commit="$HEROKU_TEST_RUN_COMMIT_VERSION" - -elif [[ "$CI" = "true" || "$CI" = "True" ]] && [[ "$APPVEYOR" = "true" || "$APPVEYOR" = "True" ]]; -then - say "$e==>$x Appveyor CI detected." - # http://www.appveyor.com/docs/environment-variables - service="appveyor" - branch="$APPVEYOR_REPO_BRANCH" - build=$(urlencode "$APPVEYOR_JOB_ID") - pr="$APPVEYOR_PULL_REQUEST_NUMBER" - job="$APPVEYOR_ACCOUNT_NAME%2F$APPVEYOR_PROJECT_SLUG%2F$APPVEYOR_BUILD_VERSION" - slug="$APPVEYOR_REPO_NAME" - commit="$APPVEYOR_REPO_COMMIT" - build_url=$(urlencode "${APPVEYOR_URL}/project/${APPVEYOR_REPO_NAME}/builds/$APPVEYOR_BUILD_ID/job/${APPVEYOR_JOB_ID}") - -elif [ "$CI" = "true" ] && [ "$WERCKER_GIT_BRANCH" != "" ]; -then - say "$e==>$x Wercker CI detected." - # http://devcenter.wercker.com/articles/steps/variables.html - service="wercker" - branch="$WERCKER_GIT_BRANCH" - build="$WERCKER_MAIN_PIPELINE_STARTED" - slug="$WERCKER_GIT_OWNER/$WERCKER_GIT_REPOSITORY" - commit="$WERCKER_GIT_COMMIT" - -elif [ "$CI" = "true" ] && [ "$MAGNUM" = "true" ]; -then - say "$e==>$x Magnum CI detected." - # https://magnum-ci.com/docs/environment - service="magnum" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - commit="$CI_COMMIT" - -elif [ "$SHIPPABLE" = "true" ]; -then - say "$e==>$x Shippable CI detected." - # http://docs.shippable.com/ci_configure/ - service="shippable" - # shellcheck disable=SC2153 - branch=$([ "$HEAD_BRANCH" != "" ] && echo "$HEAD_BRANCH" || echo "$BRANCH") - build="$BUILD_NUMBER" - build_url=$(urlencode "$BUILD_URL") - pr="$PULL_REQUEST" - slug="$REPO_FULL_NAME" - # shellcheck disable=SC2153 - commit="$COMMIT" - -elif [ "$TDDIUM" = "true" ]; -then - say "Solano CI detected." - # http://docs.solanolabs.com/Setup/tddium-set-environment-variables/ - service="solano" - commit="$TDDIUM_CURRENT_COMMIT" - branch="$TDDIUM_CURRENT_BRANCH" - build="$TDDIUM_TID" - pr="$TDDIUM_PR_ID" - -elif [ "$GREENHOUSE" = "true" ]; -then - say "$e==>$x Greenhouse CI detected." - # http://docs.greenhouseci.com/docs/environment-variables-files - service="greenhouse" - branch="$GREENHOUSE_BRANCH" - build="$GREENHOUSE_BUILD_NUMBER" - build_url=$(urlencode "$GREENHOUSE_BUILD_URL") - pr="$GREENHOUSE_PULL_REQUEST" - commit="$GREENHOUSE_COMMIT" - search_in="$search_in $GREENHOUSE_EXPORT_DIR" - -elif [ "$GITLAB_CI" != "" ]; -then - say "$e==>$x GitLab CI detected." - # http://doc.gitlab.com/ce/ci/variables/README.html - service="gitlab" - branch="${CI_BUILD_REF_NAME:-$CI_COMMIT_REF_NAME}" - build="${CI_BUILD_ID:-$CI_JOB_ID}" - remote_addr="${CI_BUILD_REPO:-$CI_REPOSITORY_URL}" - commit="${CI_BUILD_REF:-$CI_COMMIT_SHA}" - slug="${CI_PROJECT_PATH}" - -elif [ "$GITHUB_ACTIONS" != "" ]; -then - say "$e==>$x GitHub Actions detected." - say " Env vars used:" - say " -> GITHUB_ACTIONS: ${GITHUB_ACTIONS}" - say " -> GITHUB_HEAD_REF: ${GITHUB_HEAD_REF}" - say " -> GITHUB_REF: ${GITHUB_REF}" - say " -> GITHUB_REPOSITORY: ${GITHUB_REPOSITORY}" - say " -> GITHUB_RUN_ID: ${GITHUB_RUN_ID}" - say " -> GITHUB_SHA: ${GITHUB_SHA}" - say " -> GITHUB_WORKFLOW: ${GITHUB_WORKFLOW}" - - # https://github.com/features/actions - service="github-actions" - - # https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables - branch="${GITHUB_REF#refs/heads/}" - if [ "$GITHUB_HEAD_REF" != "" ]; - then - # PR refs are in the format: refs/pull/7/merge - if [[ "$GITHUB_REF" =~ ^refs\/pull\/[0-9]+\/merge$ ]]; - then - pr="${GITHUB_REF#refs/pull/}" - pr="${pr%/merge}" - fi - branch="${GITHUB_HEAD_REF}" - fi - commit="${GITHUB_SHA}" - slug="${GITHUB_REPOSITORY}" - build="${GITHUB_RUN_ID}" - build_url=$(urlencode "${GITHUB_SERVER_URL:-https://github.com}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}") - job="$(urlencode "${GITHUB_WORKFLOW}")" - - # actions/checkout runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ] && [ "$commit_o" == "" ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - elif [[ "$mc" = "" ]]; - then - say "$r-> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0$x" - fi - fi - -elif [ "$SYSTEM_TEAMFOUNDATIONSERVERURI" != "" ]; -then - say "$e==>$x Azure Pipelines detected." - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&viewFallbackFrom=vsts&tabs=yaml - service="azure_pipelines" - commit="$BUILD_SOURCEVERSION" - build="$BUILD_BUILDNUMBER" - if [ -z "$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" ]; - then - pr="$SYSTEM_PULLREQUEST_PULLREQUESTID" - else - pr="$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" - fi - project="${SYSTEM_TEAMPROJECT}" - server_uri="${SYSTEM_TEAMFOUNDATIONSERVERURI}" - job="${BUILD_BUILDID}" - branch="${BUILD_SOURCEBRANCH#"refs/heads/"}" - build_url=$(urlencode "${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECT}/_build/results?buildId=${BUILD_BUILDID}") - - # azure/pipelines runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - fi - fi - -elif [ "$CI" = "true" ] && [ "$BITBUCKET_BUILD_NUMBER" != "" ]; -then - say "$e==>$x Bitbucket detected." - # https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html - service="bitbucket" - branch="$BITBUCKET_BRANCH" - build="$BITBUCKET_BUILD_NUMBER" - slug="$BITBUCKET_REPO_OWNER/$BITBUCKET_REPO_SLUG" - job="$BITBUCKET_BUILD_NUMBER" - pr="$BITBUCKET_PR_ID" - commit="$BITBUCKET_COMMIT" - # See https://jira.atlassian.com/browse/BCLOUD-19393 - if [ "${#commit}" = 12 ]; - then - commit=$(git rev-parse "$BITBUCKET_COMMIT") - fi - -elif [ "$CI" = "true" ] && [ "$BUDDY" = "true" ]; -then - say "$e==>$x Buddy CI detected." - # https://buddy.works/docs/pipelines/environment-variables - service="buddy" - branch="$BUDDY_EXECUTION_BRANCH" - build="$BUDDY_EXECUTION_ID" - build_url=$(urlencode "$BUDDY_EXECUTION_URL") - commit="$BUDDY_EXECUTION_REVISION" - pr="$BUDDY_EXECUTION_PULL_REQUEST_NO" - tag="$BUDDY_EXECUTION_TAG" - slug="$BUDDY_REPO_SLUG" - -elif [ "$CIRRUS_CI" != "" ]; -then - say "$e==>$x Cirrus CI detected." - # https://cirrus-ci.org/guide/writing-tasks/#environment-variables - service="cirrus-ci" - slug="$CIRRUS_REPO_FULL_NAME" - branch="$CIRRUS_BRANCH" - pr="$CIRRUS_PR" - commit="$CIRRUS_CHANGE_IN_REPO" - build="$CIRRUS_BUILD_ID" - build_url=$(urlencode "https://cirrus-ci.com/task/$CIRRUS_TASK_ID") - job="$CIRRUS_TASK_NAME" - -elif [ "$DOCKER_REPO" != "" ]; -then - say "$e==>$x Docker detected." - # https://docs.docker.com/docker-cloud/builds/advanced/ - service="docker" - branch="$SOURCE_BRANCH" - commit="$SOURCE_COMMIT" - slug="$DOCKER_REPO" - tag="$CACHE_TAG" - env="$env,IMAGE_NAME" - -else - say "${r}x>${x} No CI provider detected." - say " Testing inside Docker? ${b}http://docs.codecov.io/docs/testing-with-docker${x}" - say " Testing with Tox? ${b}https://docs.codecov.io/docs/python#section-testing-with-tox${x}" - -fi - -say " ${e}current dir: ${x} $PWD" -say " ${e}project root:${x} $git_root" - -# find branch, commit, repo from git command -if [ "$GIT_BRANCH" != "" ]; -then - branch="$GIT_BRANCH" - -elif [ "$branch" = "" ]; -then - branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || hg branch 2>/dev/null || echo "") - if [ "$branch" = "HEAD" ]; - then - branch="" - fi -fi - -if [ "$commit_o" = "" ]; -then - if [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - elif [ "$commit" = "" ]; - then - commit=$(git log -1 --format="%H" 2>/dev/null || hg id -i --debug 2>/dev/null | tr -d '+' || echo "") - fi -else - commit="$commit_o" -fi - -if [ "$CODECOV_TOKEN" != "" ] && [ "$token" = "" ]; -then - say "${e}-->${x} token set from env" - token="$CODECOV_TOKEN" -fi - -if [ "$CODECOV_URL" != "" ] && [ "$url_o" = "" ]; -then - say "${e}-->${x} url set from env" - url_o=$(echo "$CODECOV_URL" | sed -e 's/\/$//') -fi - -if [ "$CODECOV_SLUG" != "" ]; -then - say "${e}-->${x} slug set from env" - slug_o="$CODECOV_SLUG" - -elif [ "$slug" = "" ]; -then - if [ "$remote_addr" = "" ]; - then - remote_addr=$(git config --get remote.origin.url || hg paths default || echo '') - fi - if [ "$remote_addr" != "" ]; - then - if echo "$remote_addr" | grep -q "//"; then - # https - slug=$(echo "$remote_addr" | cut -d / -f 4,5 | sed -e 's/\.git$//') - else - # ssh - slug=$(echo "$remote_addr" | cut -d : -f 2 | sed -e 's/\.git$//') - fi - fi - if [ "$slug" = "/" ]; - then - slug="" - fi -fi - -yaml=$(cd "$git_root" && \ - git ls-files "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || hg locate "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || cd "$proj_root" && find . -maxdepth 1 -type f -name '*codecov.y*ml' 2>/dev/null \ - || echo '') -yaml=$(echo "$yaml" | head -1) - -if [ "$yaml" != "" ]; -then - say " ${e}Yaml found at:${x} $yaml" - if [[ "$yaml" != /* ]]; then - # relative path for yaml file given, assume relative to the repo root - yaml="$git_root/$yaml" - fi - config=$(parse_yaml "$yaml" || echo '') - - # TODO validate the yaml here - - if [ "$(echo "$config" | grep 'codecov_token="')" != "" ] && [ "$token" = "" ]; - then - say "${e}-->${x} token set from yaml" - token="$(echo "$config" | grep 'codecov_token="' | sed -e 's/codecov_token="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_url="')" != "" ] && [ "$url_o" = "" ]; - then - say "${e}-->${x} url set from yaml" - url_o="$(echo "$config" | grep 'codecov_url="' | sed -e 's/codecov_url="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_slug="')" != "" ] && [ "$slug_o" = "" ]; - then - say "${e}-->${x} slug set from yaml" - slug_o="$(echo "$config" | grep 'codecov_slug="' | sed -e 's/codecov_slug="//' | sed -e 's/"\.*//')" - fi -else - say " ${g}Yaml not found, that's ok! Learn more at${x} ${b}http://docs.codecov.io/docs/codecov-yaml${x}" -fi - -if [ "$branch_o" != "" ]; -then - branch=$(urlencode "$branch_o") -else - branch=$(urlencode "$branch") -fi - -if [ "$slug_o" = "" ]; -then - urlencoded_slug=$(urlencode "$slug") -else - urlencoded_slug=$(urlencode "$slug_o") -fi - -query="branch=$branch\ - &commit=$commit\ - &build=$([ "$build_o" = "" ] && echo "$build" || echo "$build_o")\ - &build_url=$build_url\ - &name=$(urlencode "$name")\ - &tag=$([ "$tag_o" = "" ] && echo "$tag" || echo "$tag_o")\ - &slug=$urlencoded_slug\ - &service=$service\ - &flags=$flags\ - &pr=$([ "$pr_o" = "" ] && echo "${pr##\#}" || echo "${pr_o##\#}")\ - &job=$job\ - &cmd_args=$(IFS=,; echo "${codecov_flags[*]}")" - -if [ -n "$project" ] && [ -n "$server_uri" ]; -then - query=$(echo "$query&project=$project&server_uri=$server_uri" | tr -d ' ') -fi - -if [ "$parent" != "" ]; -then - query=$(echo "parent=$parent&$query" | tr -d ' ') -fi - -if [ "$ft_search" = "1" ]; -then - # detect bower comoponents location - bower_components="bower_components" - bower_rc=$(cd "$git_root" && cat .bowerrc 2>/dev/null || echo "") - if [ "$bower_rc" != "" ]; - then - bower_components=$(echo "$bower_rc" | tr -d '\n' | grep '"directory"' | cut -d'"' -f4 | sed -e 's/\/$//') - if [ "$bower_components" = "" ]; - then - bower_components="bower_components" - fi - fi - - # Swift Coverage - if [ "$ft_xcodellvm" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode reports via llvm-cov" - say " DerivedData folder: $ddp" - profdata_files=$(find "$ddp" -name '*.profdata' 2>/dev/null || echo '') - if [ "$profdata_files" != "" ]; - then - # xcode via profdata - if [ "$xp" = "" ]; - then - # xp=$(xcodebuild -showBuildSettings 2>/dev/null | grep -i "^\s*PRODUCT_NAME" | sed -e 's/.*= \(.*\)/\1/') - # say " ${e}->${x} Speed up Xcode processing by adding ${e}-J '$xp'${x}" - say " ${g}hint${x} Speed up Swift processing by using use ${g}-J 'AppName'${x} (regexp accepted)" - say " ${g}hint${x} This will remove Pods/ from your report. Also ${b}https://docs.codecov.io/docs/ignoring-paths${x}" - fi - while read -r profdata; - do - if [ "$profdata" != "" ]; - then - swiftcov "$profdata" "$xp" - fi - done <<< "$profdata_files" - else - say " ${e}->${x} No Swift coverage found" - fi - - # Obj-C Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say " ${e}->${x} Running $gcov_exe for Obj-C" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" || true - fi - fi - fi - - if [ "$ft_xcodeplist" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode plists" - plists_files=$(find "$ddp" -name '*.xccoverage' 2>/dev/null || echo '') - if [ "$plists_files" != "" ]; - then - while read -r plist; - do - if [ "$plist" != "" ]; - then - say " ${g}Found${x} plist file at $plist" - plutil -convert xml1 -o "$(basename "$plist").plist" -- "$plist" - fi - done <<< "$plists_files" - fi - fi - - # Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say "${e}==>${x} Running $gcov_exe in $proj_root ${e}(disable via -X gcov)${x}" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true - fi - else - say "${e}==>${x} gcov disabled" - fi - - # Python Coverage - if [ "$ft_coveragepy" = "1" ]; - then - if [ ! -f coverage.xml ]; - then - if command -v coverage >/dev/null 2>&1; - then - say "${e}==>${x} Python coveragepy exists ${e}disable via -X coveragepy${x}" - - dotcoverage=$(find "$git_root" -name '.coverage' -or -name '.coverage.*' | head -1 || echo '') - if [ "$dotcoverage" != "" ]; - then - cd "$(dirname "$dotcoverage")" - if [ ! -f .coverage ]; - then - say " ${e}->${x} Running coverage combine" - coverage combine -a - fi - say " ${e}->${x} Running coverage xml" - if [ "$(coverage xml -i)" != "No data to report." ]; - then - files="$files -$PWD/coverage.xml" - else - say " ${r}No data to report.${x}" - fi - cd "$proj_root" - else - say " ${r}No .coverage file found.${x}" - fi - else - say "${e}==>${x} Python coveragepy not found" - fi - fi - else - say "${e}==>${x} Python coveragepy disabled" - fi - - if [ "$search_in_o" != "" ]; - then - # location override - search_in="$search_in_o" - fi - - say "$e==>$x Searching for coverage reports in:" - for _path in $search_in - do - say " ${g}+${x} $_path" - done - - patterns="find $search_in \( \ - -name vendor \ - -or -name '$bower_components' \ - -or -name '.egg-info*' \ - -or -name 'conftest_*.c.gcov' \ - -or -name .env \ - -or -name .envs \ - -or -name .git \ - -or -name .hg \ - -or -name .tox \ - -or -name .venv \ - -or -name .venvs \ - -or -name .virtualenv \ - -or -name .virtualenvs \ - -or -name .yarn-cache \ - -or -name __pycache__ \ - -or -name env \ - -or -name envs \ - -or -name htmlcov \ - -or -name js/generated/coverage \ - -or -name node_modules \ - -or -name venv \ - -or -name venvs \ - -or -name virtualenv \ - -or -name virtualenvs \ - \) -prune -or \ - -type f \( -name '*coverage*.*' \ - -or -name '*.clover' \ - -or -name '*.codecov.*' \ - -or -name '*.gcov' \ - -or -name '*.lcov' \ - -or -name '*.lst' \ - -or -name 'clover.xml' \ - -or -name 'cobertura.xml' \ - -or -name 'codecov.*' \ - -or -name 'cover.out' \ - -or -name 'codecov-result.json' \ - -or -name 'coverage-final.json' \ - -or -name 'excoveralls.json' \ - -or -name 'gcov.info' \ - -or -name 'jacoco*.xml' \ - -or -name '*Jacoco*.xml' \ - -or -name 'lcov.dat' \ - -or -name 'lcov.info' \ - -or -name 'luacov.report.out' \ - -or -name 'naxsi.info' \ - -or -name 'nosetests.xml' \ - -or -name 'report.xml' \ - $include_cov \) \ - $exclude_cov \ - -not -name '*.am' \ - -not -name '*.bash' \ - -not -name '*.bat' \ - -not -name '*.bw' \ - -not -name '*.cfg' \ - -not -name '*.class' \ - -not -name '*.cmake' \ - -not -name '*.cmake' \ - -not -name '*.conf' \ - -not -name '*.coverage' \ - -not -name '*.cp' \ - -not -name '*.cpp' \ - -not -name '*.crt' \ - -not -name '*.css' \ - -not -name '*.csv' \ - -not -name '*.csv' \ - -not -name '*.data' \ - -not -name '*.db' \ - -not -name '*.dox' \ - -not -name '*.ec' \ - -not -name '*.ec' \ - -not -name '*.egg' \ - -not -name '*.el' \ - -not -name '*.env' \ - -not -name '*.erb' \ - -not -name '*.exe' \ - -not -name '*.ftl' \ - -not -name '*.gif' \ - -not -name '*.gradle' \ - -not -name '*.gz' \ - -not -name '*.h' \ - -not -name '*.html' \ - -not -name '*.in' \ - -not -name '*.jade' \ - -not -name '*.jar*' \ - -not -name '*.jpeg' \ - -not -name '*.jpg' \ - -not -name '*.js' \ - -not -name '*.less' \ - -not -name '*.log' \ - -not -name '*.m4' \ - -not -name '*.mak*' \ - -not -name '*.md' \ - -not -name '*.o' \ - -not -name '*.p12' \ - -not -name '*.pem' \ - -not -name '*.png' \ - -not -name '*.pom*' \ - -not -name '*.profdata' \ - -not -name '*.proto' \ - -not -name '*.ps1' \ - -not -name '*.pth' \ - -not -name '*.py' \ - -not -name '*.pyc' \ - -not -name '*.pyo' \ - -not -name '*.rb' \ - -not -name '*.rsp' \ - -not -name '*.rst' \ - -not -name '*.ru' \ - -not -name '*.sbt' \ - -not -name '*.scss' \ - -not -name '*.scss' \ - -not -name '*.serialized' \ - -not -name '*.sh' \ - -not -name '*.snapshot' \ - -not -name '*.sql' \ - -not -name '*.svg' \ - -not -name '*.tar.tz' \ - -not -name '*.template' \ - -not -name '*.whl' \ - -not -name '*.xcconfig' \ - -not -name '*.xcoverage.*' \ - -not -name '*/classycle/report.xml' \ - -not -name '*codecov.yml' \ - -not -name '*~' \ - -not -name '.*coveragerc' \ - -not -name '.coverage*' \ - -not -name 'coverage-summary.json' \ - -not -name 'createdFiles.lst' \ - -not -name 'fullLocaleNames.lst' \ - -not -name 'include.lst' \ - -not -name 'inputFiles.lst' \ - -not -name 'phpunit-code-coverage.xml' \ - -not -name 'phpunit-coverage.xml' \ - -not -name 'remapInstanbul.coverage*.json' \ - -not -name 'scoverage.measurements.*' \ - -not -name 'test_*_coverage.txt' \ - -not -name 'testrunner-coverage*' \ - -print 2>/dev/null" - files=$(eval "$patterns" || echo '') - -elif [ "$include_cov" != "" ]; -then - files=$(eval "find $search_in -type f \( ${include_cov:5} \)$exclude_cov 2>/dev/null" || echo '') -elif [ "$direct_file_upload" != "" ]; -then - files=$direct_file_upload -fi - -num_of_files=$(echo "$files" | wc -l | tr -d ' ') -if [ "$num_of_files" != '' ] && [ "$files" != '' ]; -then - say " ${e}->${x} Found $num_of_files reports" -fi - -# no files found -if [ "$files" = "" ]; -then - say "${r}-->${x} No coverage report found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - exit ${exit_with}; -fi - -if [ "$ft_network" == "1" ]; -then - say "${e}==>${x} Detecting git/mercurial file structure" - network=$(cd "$git_root" && git ls-files $git_ls_files_recurse_submodules_o 2>/dev/null || hg locate 2>/dev/null || echo "") - if [ "$network" = "" ]; - then - network=$(find "$git_root" \( \ - -name virtualenv \ - -name .virtualenv \ - -name virtualenvs \ - -name .virtualenvs \ - -name '*.png' \ - -name '*.gif' \ - -name '*.jpg' \ - -name '*.jpeg' \ - -name '*.md' \ - -name .env \ - -name .envs \ - -name env \ - -name envs \ - -name .venv \ - -name .venvs \ - -name venv \ - -name venvs \ - -name .git \ - -name .egg-info \ - -name shunit2-2.1.6 \ - -name vendor \ - -name __pycache__ \ - -name node_modules \ - -path "*/$bower_components/*" \ - -path '*/target/delombok/*' \ - -path '*/build/lib/*' \ - -path '*/js/generated/coverage/*' \ - \) -prune -or \ - -type f -print 2>/dev/null || echo '') - fi - - if [ "$network_filter_o" != "" ]; - then - network=$(echo "$network" | grep -e "$network_filter_o/*") - fi - if [ "$prefix_o" != "" ]; - then - network=$(echo "$network" | awk "{print \"$prefix_o/\"\$0}") - fi -fi - -upload_file=$(mktemp /tmp/codecov.XXXXXX) -adjustments_file=$(mktemp /tmp/codecov.adjustments.XXXXXX) - -cleanup() { - rm -f "$upload_file" "$adjustments_file" "$upload_file.gz" -} - -trap cleanup INT ABRT TERM - - -if [ "$env" != "" ]; -then - inc_env="" - say "${e}==>${x} Appending build variables" - for varname in $(echo "$env" | tr ',' ' ') - do - if [ "$varname" != "" ]; - then - say " ${g}+${x} $varname" - inc_env="${inc_env}${varname}=$(eval echo "\$${varname}") -" - fi - done - echo "$inc_env<<<<<< ENV" >> "$upload_file" -fi - -# Append git file list -# write discovered yaml location -if [ "$direct_file_upload" = "" ]; -then - echo "$yaml" >> "$upload_file" -fi - -if [ "$ft_network" == "1" ]; -then - i="woff|eot|otf" # fonts - i="$i|gif|png|jpg|jpeg|psd" # images - i="$i|ptt|pptx|numbers|pages|md|txt|xlsx|docx|doc|pdf|csv" # docs - i="$i|.gitignore" # supporting docs - - if [ "$ft_html" != "1" ]; - then - i="$i|html" - fi - - if [ "$ft_yaml" != "1" ]; - then - i="$i|yml|yaml" - fi - - echo "$network" | grep -vwE "($i)$" >> "$upload_file" -fi -echo "<<<<<< network" >> "$upload_file" - -if [ "$direct_file_upload" = "" ]; -then - fr=0 - say "${e}==>${x} Reading reports" - while IFS='' read -r file; - do - # read the coverage file - if [ "$(echo "$file" | tr -d ' ')" != '' ]; - then - if [ -f "$file" ]; - then - report_len=$(wc -c < "$file") - if [ "$report_len" -ne 0 ]; - then - say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" - # append to to upload - _filename=$(basename "$file") - if [ "${_filename##*.}" = 'gcov' ]; - then - { - echo "# path=$(echo "$file.reduced" | sed "s|^$git_root/||")"; - # get file name - head -1 "$file"; - } >> "$upload_file" - # 1. remove source code - # 2. remove ending bracket lines - # 3. remove whitespace - # 4. remove contextual lines - # 5. remove function names - awk -F': *' '{print $1":"$2":"}' "$file" \ - | sed '\/: *} *$/d' \ - | sed 's/^ *//' \ - | sed '/^-/d' \ - | sed 's/^function.*/func/' >> "$upload_file" - else - { - echo "# path=${file//^$git_root/||}"; - cat "$file"; - } >> "$upload_file" - fi - echo "<<<<<< EOF" >> "$upload_file" - fr=1 - if [ "$clean" = "1" ]; - then - rm "$file" - fi - else - say " ${r}-${x} Skipping empty file $file" - fi - else - say " ${r}-${x} file not found at $file" - fi - fi - done <<< "$(echo -e "$files")" - - if [ "$fr" = "0" ]; - then - say "${r}-->${x} No coverage data found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - say " search for your projects language to learn how to collect reports." - exit ${exit_with}; - fi -else - cp "$direct_file_upload" "$upload_file" - if [ "$clean" = "1" ]; - then - rm "$direct_file_upload" - fi -fi - -if [ "$ft_fix" = "1" ]; -then - say "${e}==>${x} Appending adjustments" - say " ${b}https://docs.codecov.io/docs/fixing-reports${x}" - - empty_line='^[[:space:]]*$' - # // - syntax_comment='^[[:space:]]*//.*' - # /* or */ - syntax_comment_block='^[[:space:]]*(\/\*|\*\/)[[:space:]]*$' - # { or } - syntax_bracket='^[[:space:]]*[\{\}][[:space:]]*(//.*)?$' - # [ or ] - syntax_list='^[[:space:]]*[][][[:space:]]*(//.*)?$' - # func ... { - syntax_go_func='^[[:space:]]*func[[:space:]]*[\{][[:space:]]*$' - - # shellcheck disable=SC2089 - skip_dirs="-not -path '*/$bower_components/*' \ - -not -path '*/node_modules/*'" - - cut_and_join() { - awk 'BEGIN { FS=":" } - $3 ~ /\/\*/ || $3 ~ /\*\// { print $0 ; next } - $1!=key { if (key!="") print out ; key=$1 ; out=$1":"$2 ; next } - { out=out","$2 } - END { print out }' 2>/dev/null - } - - if echo "$network" | grep -m1 '.kt$' 1>/dev/null; - then - # skip brackets and comments - cd "$git_root" && \ - find . -type f \ - -name '*.kt' \ - -exec \ - grep -nIHE -e "$syntax_bracket" \ - -e "$syntax_comment_block" {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # last line in file - cd "$git_root" && \ - find . -type f \ - -name '*.kt' -exec \ - wc -l {} \; \ - | while read -r l; do echo "EOF: $l"; done \ - 2>/dev/null \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.go$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path '*/vendor/*' \ - -not -path '*/caches/*' \ - -name '*.go' \ - -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_comment" \ - -e "$syntax_comment_block" \ - -e "$syntax_bracket" \ - -e "$syntax_go_func" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.dart$' 1>/dev/null; - then - # skip brackets - cd "$git_root" && \ - find . -type f \ - -name '*.dart' \ - -exec \ - grep -nIHE \ - -e "$syntax_bracket" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.php$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path "*/vendor/*" \ - -name '*.php' \ - -exec \ - grep -nIHE \ - -e "$syntax_list" \ - -e "$syntax_bracket" \ - -e '^[[:space:]]*\);[[:space:]]*(//.*)?$' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '\(.c\.cpp\|.cxx\|.h\|.hpp\|.m\|.swift\|.vala\)$' 1>/dev/null; - then - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_bracket" \ - -e '// LCOV_EXCL' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIH '// LCOV_EXCL' \ - {} \; \ - >> "$adjustments_file" \ - || echo '' - - fi - - found=$(< "$adjustments_file" tr -d ' ') - - if [ "$found" != "" ]; - then - say " ${g}+${x} Found adjustments" - { - echo "# path=fixes"; - cat "$adjustments_file"; - echo "<<<<<< EOF"; - } >> "$upload_file" - rm -rf "$adjustments_file" - else - say " ${e}->${x} No adjustments found" - fi -fi - -if [ "$url_o" != "" ]; -then - url="$url_o" -fi - -if [ "$dump" != "0" ]; -then - # trim whitespace from query - say " ${e}->${x} Dumping upload file (no upload)" - echo "$url/upload/v4?$(echo "package=$package-$VERSION&$query" | tr -d ' ')" - cat "$upload_file" -else - if [ "$save_to" != "" ]; - then - say "${e}==>${x} Copying upload file to ${save_to}" - mkdir -p "$(dirname "$save_to")" - cp "$upload_file" "$save_to" - fi - - say "${e}==>${x} Gzipping contents" - gzip -nf9 "$upload_file" - say " $(du -h "$upload_file.gz")" - - query=$(echo "${query}" | tr -d ' ') - say "${e}==>${x} Uploading reports" - say " ${e}url:${x} $url" - say " ${e}query:${x} $query" - - # Full query (to display on terminal output) - query=$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ') - queryNoToken=$(echo "package=$package-$VERSION&token=&$query" | tr -d ' ') - - if [ "$ft_s3" = "1" ]; - then - say "${e}->${x} Pinging Codecov" - say "$url/upload/v4?$queryNoToken" - # shellcheck disable=SC2086,2090 - res=$(curl $curl_s -X POST $cacert \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'X-Reduced-Redundancy: false' \ - -H 'X-Content-Type: application/x-gzip' \ - -H 'Content-Length: 0' \ - -H "X-Upload-Token: ${token}" \ - --write-out "\n%{response_code}\n" \ - $curlargs \ - "$url/upload/v4?$query" || true) - # a good reply is "https://codecov.io" + "\n" + "https://storage.googleapis.com/codecov/..." - s3target=$(echo "$res" | sed -n 2p) - status=$(tail -n1 <<< "$res") - - if [ "$status" = "200" ] && [ "$s3target" != "" ]; - then - say "${e}->${x} Uploading to" - say "${s3target}" - - # shellcheck disable=SC2086 - s3=$(curl -fiX PUT \ - --data-binary @"$upload_file.gz" \ - -H 'Content-Type: application/x-gzip' \ - -H 'Content-Encoding: gzip' \ - $curlawsargs \ - "$s3target" || true) - - if [ "$s3" != "" ]; - then - say " ${g}->${x} Reports have been successfully queued for processing at ${b}$(echo "$res" | sed -n 1p)${x}" - exit 0 - else - say " ${r}X>${x} Failed to upload" - fi - elif [ "$status" = "400" ]; - then - # 400 Error - say "${r}${res}${x}" - exit ${exit_with} - else - say "${r}${res}${x}" - fi - fi - - say "${e}==>${x} Uploading to Codecov" - - # shellcheck disable=SC2086,2090 - res=$(curl -X POST $cacert \ - --data-binary @"$upload_file.gz" \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'Content-Type: text/plain' \ - -H 'Content-Encoding: gzip' \ - -H 'X-Content-Encoding: gzip' \ - -H "X-Upload-Token: ${token}" \ - -H 'Accept: text/plain' \ - $curlargs \ - "$url/upload/v2?$query&attempt=$i" || echo 'HTTP 500') - # {"message": "Coverage reports upload successfully", "uploaded": true, "queued": true, "id": "...", "url": "https://codecov.io/..."\} - uploaded=$(grep -o '\"uploaded\": [a-z]*' <<< "$res" | head -1 | cut -d' ' -f2) - if [ "$uploaded" = "true" ] - then - say " Reports have been successfully queued for processing at ${b}$(echo "$res" | head -2 | tail -1)${x}" - exit 0 - else - say " ${g}${res}${x}" - exit ${exit_with} - fi - - say " ${r}X> Failed to upload coverage reports${x}" -fi - -exit ${exit_with} diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index 694a51d1f82..c0b0f43aed4 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -32,7 +32,5 @@ if [[ $EXITCODE != 0 ]]; then echo "Encountered test failures." else echo "All tests passed!" - # uploading coverage.txt to CodeCov - $(dirname "$0")/codecov -f coverage.txt fi exit $EXITCODE