diff --git a/.ct.yml b/.ct.yml new file mode 100644 index 00000000000..68a9198e920 --- /dev/null +++ b/.ct.yml @@ -0,0 +1,5 @@ +# See: https://github.com/helm/chart-testing +target-branch: develop +chart-dirs: 'charts' +check-version-increment: false +validate-maintainers: false diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index 055960ff282..0047c6a54bd 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -42,14 +42,9 @@ runs: shell: bash run: mkdir -p core/web/assets && touch core/web/assets/index.html - name: Build binary - if: ${{ inputs.go-directory == '.' }} - shell: bash - run: go build ./... - - name: Build binary - if: ${{ inputs.go-directory != '.' }} working-directory: ${{ inputs.go-directory }} shell: bash - run: go build + run: go build ./... - name: golangci-lint uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 with: diff --git a/.github/actions/notify-slack-jobs-result/README.md b/.github/actions/notify-slack-jobs-result/README.md new file mode 100644 index 00000000000..298930c0d95 --- /dev/null +++ b/.github/actions/notify-slack-jobs-result/README.md @@ -0,0 +1,37 @@ +# Notify Slack Jobs Result + +Sends a Slack message to a specified channel detailing the results of one to many GHA job results using a regex. The job results will be grouped by the `github_job_name_regex` and displayed underneath the `message_title`, with the regex matching group displayed as an individual result. This is primarily designed for when you have test groups running in a matrix, and would like condensed reporting on their status by group. It's often accompanied by posting a Slack message before to start a thread, then attaching all the results to that thread like we do in the reporting section of the [live-testnet-test.yml workflow](../../workflows/live-testnet-tests.yml). Check out the example below, where we post an initial summary message, then use this action to thread together specific results: + +```yaml +message_title: Optimism Goerli +github_job_name_regex: ^Optimism Goerli (?.*?) Tests$ # Note that the regex MUST have a capturing group named "cap" +``` + +![example](image.png) + +## Inputs + +```yaml +inputs: + github_token: + description: "The GitHub token to use for authentication (usually ${{ github.token }})" + required: true + github_repository: + description: "The GitHub owner/repository to use for authentication (usually ${{ github.repository }}))" + required: true + workflow_run_id: + description: "The workflow run ID to get the results from (usually ${{ github.run_id }})" + required: true + github_job_name_regex: + description: "The regex to use to match 1..many job name(s) to collect results from. Should include a capture group named 'cap' for the part of the job name you want to display in the Slack message (e.g. ^Client Compatability Test (?.*?)$)" + required: true + message_title: + description: "The title of the Slack message" + required: true + slack_channel_id: + description: "The Slack channel ID to post the message to" + required: true + slack_thread_ts: + description: "The Slack thread timestamp to post the message to, handy for keeping multiple related results in a single thread" + required: false +``` diff --git a/.github/actions/notify-slack-jobs-result/action.yml b/.github/actions/notify-slack-jobs-result/action.yml new file mode 100644 index 00000000000..63840cfa393 --- /dev/null +++ b/.github/actions/notify-slack-jobs-result/action.yml @@ -0,0 +1,110 @@ +name: Notify Slack Jobs Result +description: Will send a notification in Slack for the result of a GitHub action run, typically for test results +inputs: + github_token: + description: "The GitHub token to use for authentication (usually github.token)" + required: true + github_repository: + description: "The GitHub owner/repository to use for authentication (usually github.repository))" + required: true + workflow_run_id: + description: "The workflow run ID to get the results from (usually github.run_id)" + required: true + github_job_name_regex: + description: "The regex to use to match 1..many job name(s) to collect results from. Should include a capture group named 'cap' for the part of the job name you want to display in the Slack message (e.g. ^Client Compatability Test (?.*?)$)" + required: true + message_title: + description: "The title of the Slack message" + required: true + slack_channel_id: + description: "The Slack channel ID to post the message to" + required: true + slack_bot_token: + description: "The Slack bot token to use for authentication which needs permission and an installed app in the channel" + required: true + slack_thread_ts: + description: "The Slack thread timestamp to post the message to, handy for keeping multiple related results in a single thread" + required: false + +runs: + using: composite + steps: + - name: Get Results + shell: bash + id: test-results + run: | + # I feel like there's some clever, fully jq way to do this, but I ain't got the motivation to figure it out + echo "Querying test results at https://api.github.com/repos/${{inputs.github_repository}}/actions/runs/${{ inputs.workflow_run_id }}/jobs" + + PARSED_RESULTS=$(curl \ + -H "Authorization: Bearer ${{ inputs.github_token }}" \ + 'https://api.github.com/repos/${{inputs.github_repository}}/actions/runs/${{ inputs.workflow_run_id }}/jobs' \ + | jq -r --arg pattern "${{ inputs.github_job_name_regex }}" '.jobs[] + | select(.name | test($pattern)) as $job + | $job.steps[] + | select(.name == "Run Tests") + | { conclusion: (if .conclusion == "success" then ":white_check_mark:" else ":x:" end), cap: ("*" + ($job.name | capture($pattern).cap) + "*"), html_url: $job.html_url }') + + echo "Parsed Results:" + echo $PARSED_RESULTS + + ALL_SUCCESS=true + echo "Checking for failures" + echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")' + for row in $(echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")'); do + ALL_SUCCESS=false + break + done + echo "Success: $ALL_SUCCESS" + + echo all_success=$ALL_SUCCESS >> $GITHUB_OUTPUT + + FORMATTED_RESULTS=$(echo $PARSED_RESULTS | jq -s '[.[] + | { + conclusion: .conclusion, + cap: .cap, + html_url: .html_url + } + ] + | map("{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"<\(.html_url)|\(.cap)>: \(.conclusion)\"}}") + | join(",")') + + echo "Formatted Results:" + echo $FORMATTED_RESULTS + + # Cleans out backslashes and quotes from jq + CLEAN_RESULTS=$(echo "$FORMATTED_RESULTS" | sed 's/\\\"/"/g' | sed 's/^"//;s/"$//') + + echo "Clean Results" + echo $CLEAN_RESULTS + + echo results=$CLEAN_RESULTS >> $GITHUB_OUTPUT + - name: Post Results + uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + env: + SLACK_BOT_TOKEN: ${{ inputs.slack_bot_token }} + with: + channel-id: ${{ inputs.slack_channel_id }} + payload: | + { + "thread_ts": "${{ inputs.slack_thread_ts }}", + "attachments": [ + { + "color": "${{ steps.test-results.outputs.all_success == 'true' && '#2E7D32' || '#C62828' }}", + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "${{ inputs.message_title }} ${{ steps.test-results.outputs.all_success == 'true' && ':white_check_mark:' || ':x:'}}", + "emoji": true + } + }, + { + "type": "divider" + }, + ${{ steps.test-results.outputs.results }} + ] + } + ] + } diff --git a/.github/actions/notify-slack-jobs-result/image.png b/.github/actions/notify-slack-jobs-result/image.png new file mode 100644 index 00000000000..3bd398101fb Binary files /dev/null and b/.github/actions/notify-slack-jobs-result/image.png differ diff --git a/.github/tracing/README.md b/.github/tracing/README.md index feba31feb65..04f0216e25f 100644 --- a/.github/tracing/README.md +++ b/.github/tracing/README.md @@ -48,4 +48,55 @@ This folder contains the following config files: These config files are for an OTEL collector, grafana Tempo, and a grafana UI instance to run as containers on the same network. `otel-collector-dev.yaml` is the configuration for dev (i.e. your local machine) environments, and forwards traces from the otel collector to the grafana tempo instance on the same network. -`otel-collector-ci.yaml` is the configuration for the CI runs, and exports the trace data to the artifact from the github run. \ No newline at end of file +`otel-collector-ci.yaml` is the configuration for the CI runs, and exports the trace data to the artifact from the github run. + +## Adding Traces to Plugins and to core + +Adding traces requires identifying an observability gap in a related group of code executions or a critical path in your application. This is intuitive for the developer: + +- "What's the flow of component interaction in this distributed system?" +- "What's the behavior of the JobProcessorOne component when jobs with [x, y, z] attributes are processed?" +- "Is this critical path workflow behaving the way we expect?" + +The developer will measure a flow of execution from end to end in one trace. Each logically separate measure of this flow is called a span. Spans have either one or no parent span and multiple children span. The relationship between parent and child spans in agreggate will form a directed acyclic graph. The trace begins at the root of this graph. + +The most trivial application of a span is measuring top level performance in one critical path. There is much more you can do, including creating human readable and timestamped events within a span (useful for monitoring concurrent access to resources), recording errors, linking parent and children spans through large parts of an application, and even extending a span beyond a single process. + +Spans are created by `tracers` and passed through go applications by `Context`s. A tracer must be initialized first. Both core and plugin developers will initialize a tracer from the globally registered trace provider: + +``` +tracer := otel.GetTracerProvider().Tracer("example.com/foo") +``` + +The globally registered tracer provider is available for plugins after they are initialized, and available in core after configuration is processed (`initGlobals`). + +Add spans by: +``` + func interestingFunc() { + // Assuming there is an appropriate parentContext + ctx, span := tracer.Start(parentContext, "hello-span") + defer span.End() + + // do some work to track with hello-span + } +``` +As implied by the example, `span` is a child of its parent span captured by `parentContext`. + + +Note that in certain situations, there are 3rd party libraries that will setup spans. For instance: + +``` +import ( + "github.com/gin-gonic/gin" + "go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin" +) + +router := gin.Default() +router.Use(otelgin.Middleware("service-name")) +``` + +The developer aligns with best practices when they: +- Start with critical paths +- Measure paths from end to end (Context is wired all the way through) +- Emphasize broadness of measurement over depth +- Use automatic instrumentation if possible \ No newline at end of file diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index b19ac8fd24c..96dffa01db9 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -22,6 +22,10 @@ on: description: TestInputs required: false type: string + ConfigOverride: + description: ConfigOverride + required: false + type: string slackMemberID: description: Notifies test results (Not your @) required: true @@ -43,6 +47,7 @@ jobs: SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: C03KJ5S7KEK TEST_INPUTS: ${{ inputs.TestInputs }} + CONFIG_OVERRIDE: ${{ inputs.ConfigOverride }} CHAINLINK_ENV_USER: ${{ github.actor }} REF_NAME: ${{ github.head_ref || github.ref_name }} steps: diff --git a/.github/workflows/ci-chaincli.yml b/.github/workflows/ci-chaincli.yml deleted file mode 100644 index 8a9ab03d766..00000000000 --- a/.github/workflows/ci-chaincli.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: chaincli CI - -on: - push: - pull_request: - -jobs: - golangci: - if: ${{ github.event_name == 'pull_request' || github.event_name == 'schedule' }} - name: chaincli-lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - name: Golang Lint - uses: ./.github/actions/golangci-lint - with: - name: chaincli-lint - go-directory: core/scripts/chaincli - go-version-file: core/scripts/go.mod - go-module-file: core/scripts/go.sum - gc-basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_CLOUD_HOST }} diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index bac6f763892..0d9d2912718 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -50,7 +50,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup node - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs with: @@ -97,7 +97,7 @@ jobs: working-directory: ./.github/actions/setup-postgres - name: Store logs artifacts if: always() - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: name: ${{ matrix.cmd }}_logs path: | @@ -136,7 +136,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup node - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs with: @@ -154,7 +154,7 @@ jobs: - name: Setup DB run: ./chainlink.test local db preparetest - name: Load test outputs - uses: actions/download-artifact@v3 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: path: ./artifacts - name: Build flakey test runner diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml new file mode 100644 index 00000000000..dd46dfd7799 --- /dev/null +++ b/.github/workflows/ci-scripts.yml @@ -0,0 +1,45 @@ +name: CI Scripts + +on: + push: + pull_request: + +jobs: + lint-scripts: + if: ${{ github.event_name == 'pull_request' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Golang Lint + uses: ./.github/actions/golangci-lint + with: + name: lint-scripts + go-directory: core/scripts + go-version-file: core/scripts/go.mod + go-module-file: core/scripts/go.sum + gc-basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + gc-host: ${{ secrets.GRAFANA_CLOUD_HOST }} + + test-scripts: + if: ${{ github.event_name == 'pull_request' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Setup Go + uses: ./.github/actions/setup-go + with: + go-version-file: core/scripts/go.mod + go-module-file: core/scripts/go.sum + - name: Run Tests + shell: bash + working-directory: core/scripts + run: go test ./... + - name: Collect Metrics + if: always() + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: test-scripts + continue-on-error: true diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml new file mode 100644 index 00000000000..865c72258cd --- /dev/null +++ b/.github/workflows/client-compatibility-tests.yml @@ -0,0 +1,260 @@ +name: Client Compatibility Tests +on: + schedule: + - cron: "30 5 * * *" # Run every night at midnight + 30min EST + push: + tags: + - "*" + workflow_dispatch: + +env: + CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink + INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com + MOD_CACHE_VERSION: 2 + +jobs: + # Build Test Dependencies + + build-chainlink: + environment: integration + permissions: + id-token: write + contents: read + name: Build Chainlink Image + runs-on: ubuntu-latest + steps: + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: Build Chainlink Image + continue-on-error: true + - name: Checkout the repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + - name: Build Chainlink Image + uses: ./.github/actions/build-chainlink-image + with: + tag_suffix: "" + dockerfile: core/chainlink.Dockerfile + git_commit_sha: ${{ github.sha }} + GRAFANA_CLOUD_BASIC_AUTH: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + GRAFANA_CLOUD_HOST: ${{ secrets.GRAFANA_CLOUD_HOST }} + AWS_REGION: ${{ secrets.QA_AWS_REGION }} + AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + + build-tests: + environment: integration + permissions: + id-token: write + contents: read + name: Build Tests Binary + runs-on: ubuntu-latest + steps: + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: Build Tests Binary + continue-on-error: true + - name: Checkout the repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + - name: Build Tests + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-tests@912bed7e07a1df4d06ea53a031e9773bb65dc7bd # v2.3.0 + with: + test_download_vendor_packages_command: cd ./integration-tests && go mod download + token: ${{ secrets.GITHUB_TOKEN }} + go_mod_path: ./integration-tests/go.mod + cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} + cache_restore_only: "true" + binary_name: tests + + # End Build Test Dependencies + + client-compatibility-matrix: + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + needs: [build-chainlink, build-tests] + env: + SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 + CHAINLINK_COMMIT_SHA: ${{ github.sha }} + CHAINLINK_ENV_USER: ${{ github.actor }} + TEST_LOG_LEVEL: debug + strategy: + fail-fast: false + matrix: + include: + - name: ocr-geth + os: ubuntu-latest + test: TestOCRBasic + file: ocr + client: geth + pyroscope_env: ci-smoke-ocr-geth-simulated + # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE + # - name: ocr-nethermind + # test: TestOCRBasic + # file: ocr + # client: nethermind + # pyroscope_env: ci-smoke-ocr-nethermind-simulated + - name: ocr-besu + test: TestOCRBasic + file: ocr + client: besu + pyroscope_env: ci-smoke-ocr-besu-simulated + - name: ocr-erigon + test: TestOCRBasic + file: ocr + client: erigon + pyroscope_env: ci-smoke-ocr-erigon-simulated + - name: ocr2-geth + test: TestOCRv2Basic + file: ocr2 + client: geth + pyroscope_env: ci-smoke-ocr2-geth-simulated + # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE + # - name: ocr2-nethermind + # test: TestOCRv2Basic + # file: ocr2 + # client: nethermind + # pyroscope_env: ci-smoke-nethermind-evm-simulated + - name: ocr2-besu + test: TestOCRv2Basic + file: ocr2 + client: besu + pyroscope_env: ci-smoke-ocr2-besu-simulated + - name: ocr2-erigon + test: TestOCRv2Basic + file: ocr2 + client: erigon + pyroscope_env: ci-smoke-ocr2-erigon-simulated + runs-on: ubuntu-latest + name: Client Compatibility Test ${{ matrix.name }} + steps: + - name: Download Tests Binary + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: tests + - name: Run Tests + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@912bed7e07a1df4d06ea53a031e9773bb65dc7bd # v2.3.0 + env: + PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} + PYROSCOPE_ENVIRONMENT: ci-client-compatability-${{ matrix.client }}-testnet + PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + ETH2_EL_CLIENT: ${{matrix.client}} + with: + test_command_to_run: ./tests -test.timeout 30m -test.run ${{ matrix.test }} + binary_name: tests + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ github.sha }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} + dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} + artifacts_location: ./logs + token: ${{ secrets.GITHUB_TOKEN }} + cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} + 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 }} + + start-slack-thread: + name: Start Slack Thread + if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} + environment: integration + outputs: + thread_ts: ${{ steps.slack.outputs.thread_ts }} + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + runs-on: ubuntu-latest + needs: [client-compatibility-matrix] + steps: + - name: Debug Result + run: echo ${{ join(needs.*.result, ',') }} + - name: Main Slack Notification + uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + id: slack + with: + channel-id: ${{ secrets.QA_SLACK_CHANNEL }} + payload: | + { + "attachments": [ + { + "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}", + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "Client Compatability Test Results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", + "emoji": true + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ contains(join(needs.*.result, ','), 'failure') && 'Some tests failed, notifying <@U01Q4N37KFG> and <@U060CGGPY8H>' || 'All Good!' }}" + } + }, + { + "type": "divider" + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" + } + } + ] + } + ] + } + env: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + + post-test-results-to-slack: + name: Post Test Results for ${{matrix.product}} + if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + runs-on: ubuntu-latest + needs: start-slack-thread + strategy: + fail-fast: false + matrix: + product: [ocr, ocr2] + steps: + - name: Checkout the repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + - name: Post Test Results to Slack + uses: ./.github/actions/notify-slack-jobs-result + with: + github_token: ${{ github.token }} + github_repository: ${{ github.repository }} + workflow_run_id: ${{ github.run_id }} + github_job_name_regex: ^Client Compatibility Test ${{ matrix.product }}-(?.*?)$ + message_title: ${{ matrix.product }} + slack_channel_id: ${{ secrets.QA_SLACK_CHANNEL }} + slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} + slack_thread_ts: ${{ needs.start-slack-thread.outputs.thread_ts }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8bc066f408c..5b846d8708d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -26,7 +26,7 @@ jobs: - name: Set up Go if: ${{ matrix.language == 'go' }} - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version-file: 'go.mod' diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml index dbf08895757..0143042abd9 100644 --- a/.github/workflows/dependency-check.yml +++ b/.github/workflows/dependency-check.yml @@ -29,7 +29,7 @@ jobs: - name: Set up Go if: needs.changes.outputs.src == 'true' - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version-file: 'go.mod' id: go diff --git a/.github/workflows/helm-publish.yml b/.github/workflows/helm-chart-publish.yml similarity index 92% rename from .github/workflows/helm-publish.yml rename to .github/workflows/helm-chart-publish.yml index 6ea46e6a52d..156268d66b0 100644 --- a/.github/workflows/helm-publish.yml +++ b/.github/workflows/helm-chart-publish.yml @@ -31,7 +31,7 @@ jobs: uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5 - name: Run chart-releaser - uses: helm/chart-releaser-action@be16258da8010256c6e82849661221415f031968 # v1.5.0 + uses: helm/chart-releaser-action@a917fd15b20e8b64b94d9158ad54cd6345335584 # v1.6.0 with: charts_dir: charts config: .github/cr.yaml diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml new file mode 100644 index 00000000000..c988d14f30c --- /dev/null +++ b/.github/workflows/helm-chart.yml @@ -0,0 +1,25 @@ +name: Helm Chart + +on: + pull_request: + paths: + - "charts/**" + - ".github/workflows/helm-chart.yml" + +jobs: + ci-lint-helm-charts: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + actions: read + steps: + - name: ci-lint-helm-charts + uses: smartcontractkit/.github/actions/ci-lint-charts@9fd15fe8e698a5e28bfd06b3a91471c56568dcb3 # ci-lint-charts@0.1.1 + with: + # chart testing inputs + chart-testing-extra-args: "--lint-conf=lintconf.yaml" + # grafana inputs + metrics-job-name: ci-lint-helm-charts + gc-basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + gc-host: ${{ secrets.GRAFANA_CLOUD_HOST }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 6ffd1a14ff2..75184a47965 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -207,8 +207,8 @@ jobs: id: build-test-matrix-list run: | cd ./integration-tests - MATRIX_JSON_AUTOMATION=$(./scripts/buildTestMatrixList.sh ./smoke/automation_test.go automation ubuntu20.04-8cores-32GB 1) - MATRIX_JSON_KEEPER=$(./scripts/buildTestMatrixList.sh ./smoke/keeper_test.go keeper ubuntu20.04-8cores-32GB 1) + MATRIX_JSON_AUTOMATION=$(./scripts/buildTestMatrixList.sh ./smoke/automation_test.go automation ubuntu-latest 1) + MATRIX_JSON_KEEPER=$(./scripts/buildTestMatrixList.sh ./smoke/keeper_test.go keeper ubuntu-latest 1) COMBINED_ARRAY=$(jq -c -n "$MATRIX_JSON_AUTOMATION + $MATRIX_JSON_KEEPER") # if we running a PR against the develop branch we should only run the automation tests unless we are in the merge group event @@ -324,78 +324,18 @@ jobs: pyroscope_env: "" - name: ocr nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRJobReplacement + os: ubuntu-latest file: ocr pyroscope_env: ci-smoke-ocr-evm-simulated - - name: ocr-geth - nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRBasic - file: ocr - client: geth - pyroscope_env: ci-smoke-ocr-evm-simulated - # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE - # - name: ocr-nethermind - # nodes: 1 - # os: ubuntu20.04-8cores-32GB - # run: -run TestOCRBasic - # file: ocr - # client: nethermind - # pyroscope_env: ci-smoke-ocr-evm-simulated - - name: ocr-besu - nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRBasic - file: ocr - client: besu - pyroscope_env: ci-smoke-ocr-evm-simulated - - name: ocr-erigon - nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRBasic - file: ocr - client: erigon - pyroscope_env: ci-smoke-ocr-evm-simulated - name: ocr2 nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRv2JobReplacement + os: ubuntu-latest file: ocr2 pyroscope_env: ci-smoke-ocr2-evm-simulated - - name: ocr2-geth - nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRv2Basic - file: ocr2 - client: geth - pyroscope_env: ci-smoke-ocr2-evm-simulated - # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE - # - name: ocr2-nethermind - # nodes: 1 - # os: ubuntu20.04-8cores-32GB - # run: -run TestOCRv2Basic - # file: ocr2 - # client: nethermind - # pyroscope_env: ci-smoke-ocr2-evm-simulated - - name: ocr2-besu - nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRv2Basic - file: ocr2 - client: besu - pyroscope_env: ci-smoke-ocr2-evm-simulated - - name: ocr2-erigon - nodes: 1 - os: ubuntu20.04-8cores-32GB - run: -run TestOCRv2Basic - file: ocr2 - client: erigon - pyroscope_env: ci-smoke-ocr2-evm-simulated - name: ocr2 nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-ocr2-evm-simulated + os: ubuntu-latest + pyroscope_env: ci-smoke-ocr2-plugins-evm-simulated tag_suffix: "-plugins" - name: runlog nodes: 1 @@ -403,25 +343,23 @@ jobs: pyroscope_env: "" - name: vrf nodes: 1 - os: ubuntu20.04-8cores-32GB + os: ubuntu-latest pyroscope_env: ci-smoke-vrf-evm-simulated - name: vrfv2 nodes: 1 - run: -run TestVRFv2MultipleSendingKeys - file: vrfv2 - os: ubuntu20.04-8cores-32GB + os: ubuntu-latest pyroscope_env: ci-smoke-vrf2-evm-simulated - name: vrfv2plus nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-vrf2plus-evm-simulated + os: ubuntu-latest + pyroscope_env: ci-smoke-vrf2plus-evm-simulated - name: forwarder_ocr nodes: 1 - os: ubuntu20.04-8cores-32GB + os: ubuntu-latest pyroscope_env: ci-smoke-forwarder-ocr-evm-simulated - name: forwarders_ocr2 nodes: 1 - os: ubuntu20.04-8cores-32GB + os: ubuntu-latest pyroscope_env: ci-smoke-forwarder-ocr-evm-simulated runs-on: ${{ matrix.product.os }} name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }} @@ -499,7 +437,6 @@ jobs: PYROSCOPE_SERVER: ${{ matrix.product.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.product.pyroscope_env }} PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - ETH2_EL_CLIENT: ${{matrix.product.client}} LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} @@ -555,7 +492,7 @@ jobs: ls -l ./integration-tests/smoke/traces - name: Upload Trace Data if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: name: trace-data path: ./integration-tests/smoke/traces/trace-data.json @@ -852,7 +789,7 @@ jobs: ref: ${{ needs.get_solana_sha.outputs.sha }} - name: Build contracts if: needs.changes.outputs.src == 'true' && needs.solana-test-image-exists.outputs.exists == 'false' - uses: smartcontractkit/chainlink-solana/.github/actions/build_contract_artifacts@23816fcf7d380a30c87b6d87e4fb0ca94419b259 # stable action on April 17 2023 + uses: smartcontractkit/chainlink-solana/.github/actions/build_contract_artifacts@21675b3a7dcdff8e790391708d4763020cace21e # stable action on December 18 2023 with: ref: ${{ needs.get_solana_sha.outputs.sha }} diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml index d060b5c510d..3298c45813a 100644 --- a/.github/workflows/live-testnet-tests.yml +++ b/.github/workflows/live-testnet-tests.yml @@ -10,7 +10,7 @@ name: Live Testnet Tests on: schedule: - - cron: "0 0 * * *" # Run every Sunday at midnight + - cron: "0 5 * * *" # Run every night at midnight EST push: tags: - "*" @@ -66,7 +66,7 @@ env: jobs: # Build Test Dependencies - + build-chainlink: environment: integration permissions: @@ -144,7 +144,7 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - needs: [sepolia-smoke-tests, bsc-testnet-tests, optimism-sepolia-smoke-tests, arbitrum-sepolia-smoke-tests, base-goerli-smoke-tests, base-sepolia-smoke-tests, polygon-mumbai-smoke-tests, avalanche-fuji-smoke-tests, fantom-testnet-smoke-tests, celo-alfajores-smoke-tests, scroll-sepolia-smoke-tests, linea-goerli-smoke-tests] + needs: [sepolia-smoke-tests, optimism-sepolia-smoke-tests, arbitrum-sepolia-smoke-tests, base-goerli-smoke-tests, base-sepolia-smoke-tests, polygon-mumbai-smoke-tests, avalanche-fuji-smoke-tests, fantom-testnet-smoke-tests, celo-alfajores-smoke-tests, linea-goerli-smoke-tests] steps: - name: Debug Result run: echo ${{ join(needs.*.result, ',') }} @@ -205,86 +205,23 @@ jobs: strategy: fail-fast: false matrix: - network: [Sepolia, Optimism Sepolia, Arbitrum Sepolia, Base Goerli, Base Sepolia, Polygon Mumbai, Avalanche Fuji, Fantom Testnet, Celo Alfajores, Scroll Sepolia, Linea Goerli] + network: [Sepolia, Optimism Sepolia, Arbitrum Sepolia, Base Goerli, Base Sepolia, Polygon Mumbai, Avalanche Fuji, Fantom Testnet, Celo Alfajores, Linea Goerli] steps: - - name: Get Results - id: test-results - run: | - # I feel like there's some clever, fully jq way to do this, but I ain't got the motivation to figure it out - echo "Querying test results" - - PARSED_RESULTS=$(curl \ - -H "Authorization: Bearer ${{ github.token }}" \ - 'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \ - | jq -r --arg pattern "^${{ matrix.network }} (?.*?) Tests$" '.jobs[] - | select(.name | test($pattern)) as $job - | $job.steps[] - | select(.name == "Run Tests") - | { conclusion: (if .conclusion == "success" then ":white_check_mark:" else ":x:" end), product: ("*" + ($job.name | capture($pattern).product) + "*") }') - - echo "Parsed Results:" - echo $PARSED_RESULTS - - ALL_SUCCESS=true - echo "Checking for failures" - echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")' - for row in $(echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")'); do - ALL_SUCCESS=false - break - done - echo "Success: $ALL_SUCCESS" - - echo all_success=$ALL_SUCCESS >> $GITHUB_OUTPUT - - FORMATTED_RESULTS=$(echo $PARSED_RESULTS | jq -s '[.[] - | { - conclusion: .conclusion, - product: .product - } - ] - | map("{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"\(.product): \(.conclusion)\"}}") - | join(",")') - - echo "Formatted Results:" - echo $FORMATTED_RESULTS - - # Cleans out backslashes and quotes from jq - CLEAN_RESULTS=$(echo "$FORMATTED_RESULTS" | sed 's/\\\"/"/g' | sed 's/^"//;s/"$//') - - echo "Clean Results" - echo $CLEAN_RESULTS - - echo results=$CLEAN_RESULTS >> $GITHUB_OUTPUT - - - name: Test Details - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + - name: Checkout the repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: - channel-id: ${{ secrets.QA_SLACK_CHANNEL }} - payload: | - { - "thread_ts": "${{ needs.start-slack-thread.outputs.thread_ts }}", - "attachments": [ - { - "color": "${{ steps.test-results.outputs.all_success == 'true' && '#2E7D32' || '#C62828' }}", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "${{ matrix.network }} ${{ steps.test-results.outputs.all_success == 'true' && ':white_check_mark:' || ':x:'}}", - "emoji": true - } - }, - { - "type": "divider" - }, - ${{ steps.test-results.outputs.results }} - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + - name: Post Test Results + uses: ./.github/actions/notify-slack-jobs-result + with: + github_token: ${{ github.token }} + github_repository: ${{ github.repository }} + workflow_run_id: ${{ github.run_id }} + github_job_name_regex: ^${{ matrix.network }} (?.*?) Tests$ + message_title: ${{ matrix.network }} + slack_channel_id: ${{ secrets.QA_SLACK_CHANNEL }} + slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} + slack_thread_ts: ${{ needs.start-slack-thread.outputs.thread_ts }} # End Reporting Jobs @@ -339,6 +276,8 @@ jobs: QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} bsc-testnet-tests: + # TODO: BSC RPCs are all in a bad state right now, so we're skipping these tests until they're fixed + if: false environment: integration permissions: checks: write @@ -775,8 +714,10 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - + scroll-sepolia-smoke-tests: + # TODO: Disabled until bug TT-767 is fixed + if: false environment: integration permissions: checks: write diff --git a/.github/workflows/on-demand-log-poller.yml b/.github/workflows/on-demand-log-poller.yml index 42f901ec304..4658e188bac 100644 --- a/.github/workflows/on-demand-log-poller.yml +++ b/.github/workflows/on-demand-log-poller.yml @@ -76,7 +76,7 @@ jobs: with: ref: ${{ env.REF_NAME }} - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version-file: "integration-tests/go.mod" cache: true diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index a4289dd0129..32e080aafca 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -15,6 +15,7 @@ on: - "CELO_ALFAJORES" - "CELO_MAINNET" - "BASE_GOERLI" + - "BASE_SEPOLIA" - "BASE_MAINNET" - "BSC_MAINNET" - "BSC_TESTNET" diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml index 4b6dd1a2280..7b9eef7fccc 100644 --- a/.github/workflows/performance-tests.yml +++ b/.github/workflows/performance-tests.yml @@ -31,7 +31,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - name: Build and Push - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 with: context: . file: core/chainlink.Dockerfile @@ -72,7 +72,7 @@ jobs: QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - name: Publish pprof artifacts if: ${{ success() }} - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: name: pprof_results path: ./integration-tests/performance/logs diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml new file mode 100644 index 00000000000..66ef95434cf --- /dev/null +++ b/.github/workflows/pr-labels.yml @@ -0,0 +1,54 @@ +name: PR Labels + +on: + pull_request: + types: [labeled] + +jobs: + crib: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Comment on PR + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const labelsToCheck = ["crib"]; + const { owner, repo, number: prNumber } = context.issue; + const { data: labels } = await github.rest.issues.listLabelsOnIssue({ owner, repo, issue_number: prNumber }); + const labelMatches = labels.some(label => labelsToCheck.includes(label.name)); + + if (!labelMatches) { + core.info("No 'crib' PR label found. Proceeding."); + return; + } + + const comment = `## CRIB Environment Details :information_source: + + CRIB activated via the 'crib' label. To destroy the environment, remove the 'crib' PR label or close the PR. + + Please review the following details: + + ### Subdomains + + _Use these subdomains to access the CRIB environment. They are prefixes to the internal base domain._ + + - crib-chain-${prNumber}-node1. + - crib-chain-${prNumber}-node2. + - crib-chain-${prNumber}-node3. + - crib-chain-${prNumber}-node4. + - crib-chain-${prNumber}-node5. + - crib-chain-${prNumber}-node6. + - crib-chain-${prNumber}-geth-http. + - crib-chain-${prNumber}-geth-ws. + - crib-chain-${prNumber}-mockserver. + `; + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: comment + }); diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 129f37c0de6..9301c6f3967 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -84,7 +84,7 @@ jobs: - name: Rename coverage run: mv ./contracts/coverage.json ./contracts/coverage-${{ matrix.split.idx }}.json - name: Upload coverage - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: name: solidity-coverage-${{ matrix.split.idx }} path: ./contracts/coverage-${{ matrix.split.idx }}.json @@ -110,7 +110,7 @@ jobs: - name: Make coverage directory run: mkdir ./contracts/coverage-reports - name: Download coverage - uses: actions/download-artifact@v3 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: path: ./contracts/coverage-reports - name: Display structure of downloaded files diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 6c5207e0f05..8eb95f4147c 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -18,7 +18,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} exempt-all-pr-assignees: true diff --git a/GNUmakefile b/GNUmakefile index 09b1dfe87a3..a6e886b7f6c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ GO_LDFLAGS := $(shell tools/bin/ldflags) GOFLAGS = -ldflags "$(GO_LDFLAGS)" .PHONY: install -install: operator-ui-autoinstall install-chainlink-autoinstall ## Install chainlink and all its dependencies. +install: install-chainlink-autoinstall ## Install chainlink and all its dependencies. .PHONY: install-git-hooks install-git-hooks: ## Install git hooks. @@ -14,8 +14,6 @@ install-git-hooks: ## Install git hooks. .PHONY: install-chainlink-autoinstall install-chainlink-autoinstall: | pnpmdep gomod install-chainlink ## Autoinstall chainlink. -.PHONY: operator-ui-autoinstall -operator-ui-autoinstall: | operator-ui ## Autoinstall frontend UI. .PHONY: pnpmdep pnpmdep: ## Install solidity contract dependencies through pnpm @@ -44,13 +42,13 @@ godoc: ## Install and run godoc install-chainlink: operator-ui ## Install the chainlink binary. go install $(GOFLAGS) . -chainlink: operator-ui ## Build the chainlink binary. +chainlink: ## Build the chainlink binary. go build $(GOFLAGS) . -chainlink-dev: operator-ui ## Build a dev build of chainlink binary. +chainlink-dev: ## Build a dev build of chainlink binary. go build -tags dev $(GOFLAGS) . -chainlink-test: operator-ui ## Build a test build of chainlink binary. +chainlink-test: ## Build a test build of chainlink binary. go build $(GOFLAGS) . .PHONY: chainlink-local-start diff --git a/charts/chainlink-cluster/.gitignore b/charts/chainlink-cluster/.gitignore new file mode 100644 index 00000000000..3ee791f740a --- /dev/null +++ b/charts/chainlink-cluster/.gitignore @@ -0,0 +1,3 @@ +# Helm +charts/ +requirements.lock diff --git a/charts/chainlink-cluster/Chart.yaml b/charts/chainlink-cluster/Chart.yaml index 127f5b6e326..498b0670812 100644 --- a/charts/chainlink-cluster/Chart.yaml +++ b/charts/chainlink-cluster/Chart.yaml @@ -1,10 +1,10 @@ -apiVersion: v1 +apiVersion: v2 name: chainlink-cluster description: Chainlink nodes cluster -version: 0.1.3 +version: 0.2.0 appVersion: "2.6.0" dependencies: - name: mockserver version: "5.14.0" - repository: "@mockserver" - condition: mockserver.enabled \ No newline at end of file + repository: "https://www.mock-server.com" + condition: mockserver.enabled diff --git a/charts/chainlink-cluster/devspace.yaml b/charts/chainlink-cluster/devspace.yaml index bd50a469ded..902925b278e 100644 --- a/charts/chainlink-cluster/devspace.yaml +++ b/charts/chainlink-cluster/devspace.yaml @@ -18,11 +18,12 @@ pipelines: # You can run this pipeline via `devspace deploy` (or `devspace run-pipeline deploy`) deploy: run: |- - run_dependencies --all # 1. Deploy any projects this project needs (see "dependencies") - ensure_pull_secrets --all # 2. Ensure pull secrets - build_images --all -t $(git rev-parse --short HEAD) # 3. Build, tag (git commit hash) and push all images (see "images") - create_deployments --all # 5. Deploy Helm charts and manifests specfied as "deployments" + run_dependencies --all + ensure_pull_secrets --all + build_images ---var DOCKER_DEFAULT_PLATFORM=linux/amd64 --all -t $(git rev-parse --short HEAD) kubectl annotate namespace ${DEVSPACE_NAMESPACE} janitor/ttl=${NS_TTL} + kubectl label namespace/${DEVSPACE_NAMESPACE} network=crib + create_deployments --all echo "Namespace ${DEVSPACE_NAMESPACE} will be deleted in ${NS_TTL}" purge: run: |- diff --git a/charts/chainlink-cluster/templates/ingress.yaml b/charts/chainlink-cluster/templates/ingress.yaml new file mode 100644 index 00000000000..f7d9791155b --- /dev/null +++ b/charts/chainlink-cluster/templates/ingress.yaml @@ -0,0 +1,42 @@ +{{- 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 + {{- 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/values.yaml b/charts/chainlink-cluster/values.yaml index feba1414444..9394bda1213 100644 --- a/charts/chainlink-cluster/values.yaml +++ b/charts/chainlink-cluster/values.yaml @@ -135,6 +135,8 @@ geth: mockserver: enabled: true releasenameOverride: mockserver + service: + type: ClusterIP app: runAsUser: 999 readOnlyRootFilesystem: false @@ -178,6 +180,101 @@ runner: type: NodePort port: 8080 +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 # monitoring.coreos.com/v1 PodMonitor for each node prometheusMonitor: true diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index a62b3df8699..9f2204f37e2 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -485,22 +485,9 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) proc return false, nil } n++ - var a txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] - var retryable bool - a, _, _, retryable, err = eb.NewTxAttempt(ctx, *etx, eb.lggr) - if err != nil { - return retryable, fmt.Errorf("processUnstartedTxs failed on NewAttempt: %w", err) - } - - if err := eb.txStore.UpdateTxUnstartedToInProgress(ctx, etx, &a); errors.Is(err, ErrTxRemoved) { - eb.lggr.Debugw("tx removed", "txID", etx.ID, "subject", etx.Subject) - continue - } else if err != nil { - return true, fmt.Errorf("processUnstartedTxs failed on UpdateTxUnstartedToInProgress: %w", err) - } - if err, retryable := eb.handleInProgressTx(ctx, *etx, a, time.Now()); err != nil { - return retryable, fmt.Errorf("processUnstartedTxs failed on handleInProgressTx: %w", err) + if err, retryable := eb.handleUnstartedTx(ctx, etx); err != nil { + return retryable, fmt.Errorf("processUnstartedTxs failed on handleUnstartedTx: %w", err) } } } @@ -520,11 +507,14 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand return nil, false } -// There can be at most one in_progress transaction per address. -// Here we complete the job that we didn't finish last time. -func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) handleInProgressTx(ctx context.Context, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], initialBroadcastAt time.Time) (error, bool) { - if etx.State != TxInProgress { - return fmt.Errorf("invariant violation: expected transaction %v to be in_progress, it was %s", etx.ID, etx.State), false +func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) handleUnstartedTx(ctx context.Context, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) (error, bool) { + if etx.State != TxUnstarted { + return fmt.Errorf("invariant violation: expected transaction %v to be unstarted, it was %s", etx.ID, etx.State), false + } + + attempt, _, _, retryable, err := eb.NewTxAttempt(ctx, *etx, eb.lggr) + if err != nil { + return fmt.Errorf("processUnstartedTxs failed on NewAttempt: %w", err), retryable } checkerSpec, err := etx.GetChecker() @@ -541,19 +531,40 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand // If the transmit check does not complete within the timeout, the transaction will be sent // anyway. + // It's intentional that we only run `Check` for unstarted transactions. + // Running it on other states might lead to nonce duplication, as we might mark applied transactions as fatally errored. + checkCtx, cancel := context.WithTimeout(ctx, TransmitCheckTimeout) defer cancel() - err = checker.Check(checkCtx, lgr, etx, attempt) + err = checker.Check(checkCtx, lgr, *etx, attempt) if errors.Is(err, context.Canceled) { lgr.Warn("Transmission checker timed out, sending anyway") } else if err != nil { etx.Error = null.StringFrom(err.Error()) lgr.Warnw("Transmission checker failed, fatally erroring transaction.", "err", err) - return eb.saveFatallyErroredTransaction(lgr, &etx), true + return eb.saveFatallyErroredTransaction(lgr, etx), true } cancel() - lgr.Infow("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", etx.FeeLimit, "attempt", attempt, "etx", etx) + if err = eb.txStore.UpdateTxUnstartedToInProgress(ctx, etx, &attempt); errors.Is(err, ErrTxRemoved) { + eb.lggr.Debugw("tx removed", "txID", etx.ID, "subject", etx.Subject) + return nil, false + } else if err != nil { + return fmt.Errorf("processUnstartedTxs failed on UpdateTxUnstartedToInProgress: %w", err), true + } + + return eb.handleInProgressTx(ctx, *etx, attempt, time.Now()) +} + +// There can be at most one in_progress transaction per address. +// Here we complete the job that we didn't finish last time. +func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) handleInProgressTx(ctx context.Context, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], initialBroadcastAt time.Time) (error, bool) { + if etx.State != TxInProgress { + return fmt.Errorf("invariant violation: expected transaction %v to be in_progress, it was %s", etx.ID, etx.State), false + } + + lgr := etx.GetLogger(logger.With(eb.lggr, "fee", attempt.TxFee)) + lgr.Infow("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "meta", etx.Meta, "feeLimit", etx.FeeLimit, "attempt", attempt, "etx", etx) errType, err := eb.client.SendTransactionReturnCode(ctx, etx, attempt, lgr) if errType != client.Fatal { @@ -647,7 +658,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand // If there is only one RPC node, or all RPC nodes have the same // configured cap, this transaction will get stuck and keep repeating // forever until the issue is resolved. - lgr.Criticalw(`RPC node rejected this tx as outside Fee Cap`) + lgr.Criticalw(`RPC node rejected this tx as outside Fee Cap`, "attempt", attempt) fallthrough default: // Every error that doesn't fall under one of the above categories will be treated as Unknown. @@ -655,7 +666,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand case client.Unknown: eb.SvcErrBuffer.Append(err) lgr.Criticalw(`Unknown error occurred while handling tx queue in ProcessUnstartedTxs. This chain/RPC client may not be supported. `+ - `Urgent resolution required, Chainlink is currently operating in a degraded state and may miss transactions`, "err", err, "etx", etx, "attempt", attempt) + `Urgent resolution required, Chainlink is currently operating in a degraded state and may miss transactions`, "attempt", attempt) nextSequence, e := eb.client.PendingSequenceAt(ctx, etx.FromAddress) if e != nil { err = multierr.Combine(e, err) @@ -760,8 +771,8 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) save func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) saveFatallyErroredTransaction(lgr logger.Logger, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { ctx, cancel := eb.chStop.NewCtx() defer cancel() - if etx.State != TxInProgress { - return fmt.Errorf("can only transition to fatal_error from in_progress, transaction is currently %s", etx.State) + if etx.State != TxInProgress && etx.State != TxUnstarted { + return fmt.Errorf("can only transition to fatal_error from in_progress or unstarted, transaction is currently %s", etx.State) } if !etx.Error.Valid { return errors.New("expected error field to be set") diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index fbc6ea8a108..f10481fef56 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chains/label" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/utils" + commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/common/client" @@ -824,7 +824,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han case client.Underpriced: // This should really not ever happen in normal operation since we // already bumped above the required minimum in broadcaster. - ec.lggr.Warnw("Got terminally underpriced error for gas bump, this should never happen unless the remote RPC node changed its configuration on the fly, or you are using multiple RPC nodes with different minimum gas price requirements. This is not recommended", "err", sendError, "attempt", attempt) + ec.lggr.Warnw("Got terminally underpriced error for gas bump, this should never happen unless the remote RPC node changed its configuration on the fly, or you are using multiple RPC nodes with different minimum gas price requirements. This is not recommended", "attempt", attempt) // "Lazily" load attempts here since the overwhelmingly common case is // that we don't need them unless we enter this path if err := ec.txStore.LoadTxAttempts(ctx, &etx); err != nil { @@ -867,10 +867,9 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han // Broadcaster can never create a TxAttempt that will // fatally error. lggr.Criticalw("Invariant violation: fatal error while re-attempting transaction", - "err", sendError, "fee", attempt.TxFee, "feeLimit", etx.FeeLimit, - "signedRawTx", utils.EnsureHexPrefix(hex.EncodeToString(attempt.SignedRawTx)), + "signedRawTx", commonhex.EnsurePrefix(hex.EncodeToString(attempt.SignedRawTx)), "blockHeight", blockHeight, ) ec.SvcErrBuffer.Append(sendError) @@ -879,7 +878,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han case client.TransactionAlreadyKnown: // Sequence too low indicated that a transaction at this sequence was confirmed already. // Mark confirmed_missing_receipt and wait for the next cycle to try to get a receipt - lggr.Debugw("Sequence already used", "txAttemptID", attempt.ID, "txHash", attempt.Hash.String(), "err", sendError) + lggr.Debugw("Sequence already used", "txAttemptID", attempt.ID, "txHash", attempt.Hash.String()) timeout := ec.dbConfig.DefaultQueryTimeout() return ec.txStore.SaveConfirmedMissingReceiptAttempt(ctx, timeout, &attempt, now) case client.InsufficientFunds: diff --git a/contracts/package.json b/contracts/package.json index abbf722140c..4dabbdb0509 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -43,49 +43,49 @@ "@nomiclabs/hardhat-etherscan": "^3.1.7", "@nomiclabs/hardhat-waffle": "2.0.6", "@openzeppelin/hardhat-upgrades": "1.28.0", - "@scroll-tech/contracts": "0.1.0", "@openzeppelin/test-helpers": "^0.5.16", "@typechain/ethers-v5": "^7.2.0", "@typechain/hardhat": "^7.0.0", "@types/cbor": "5.0.1", - "@types/chai": "^4.3.10", + "@types/chai": "^4.3.11", "@types/debug": "^4.1.12", "@types/deep-equal-in-any-order": "^1.0.3", - "@types/mocha": "^10.0.4", - "@types/node": "^16.18.61", - "@typescript-eslint/eslint-plugin": "^6.11.0", - "@typescript-eslint/parser": "^6.11.0", + "@types/mocha": "^10.0.6", + "@types/node": "^16.18.68", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", "abi-to-sol": "^0.6.6", "cbor": "^5.2.0", "chai": "^4.3.10", "debug": "^4.3.4", - "eslint": "^8.53.0", - "eslint-config-prettier": "^9.0.0", + "eslint": "^8.55.0", + "eslint-config-prettier": "^9.1.0", "deep-equal-in-any-order": "^2.0.6", "eslint-plugin-prettier": "^5.0.1", "ethereum-waffle": "^3.4.4", "ethers": "~5.7.2", - "hardhat": "~2.19.1", + "hardhat": "~2.19.2", "hardhat-abi-exporter": "^2.10.1", "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.6", "istanbul": "^0.4.5", "moment": "^2.29.4", - "prettier": "^3.1.0", + "prettier": "^3.1.1", "prettier-plugin-solidity": "1.2.0", "rlp": "^2.2.7", "solhint": "^4.0.0", "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.0", "solhint-plugin-prettier": "^0.1.0", "solidity-coverage": "^0.8.5", - "ts-node": "^10.9.1", + "ts-node": "^10.9.2", "tslib": "^2.6.2", "typechain": "^8.2.1", - "typescript": "^5.2.2" + "typescript": "^5.3.3" }, "dependencies": { - "@eth-optimism/contracts": "0.5.37", + "@eth-optimism/contracts": "0.6.0", + "@scroll-tech/contracts": "0.1.0", "@openzeppelin/contracts": "4.9.3", "@openzeppelin/contracts-upgradeable": "4.9.3" } diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index dffcb0a7c7c..1b18835dc2e 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -9,14 +9,17 @@ overrides: dependencies: '@eth-optimism/contracts': - specifier: 0.5.37 - version: 0.5.37(ethers@5.7.2) + specifier: 0.6.0 + version: 0.6.0(ethers@5.7.2) '@openzeppelin/contracts': specifier: 4.9.3 version: 4.9.3 '@openzeppelin/contracts-upgradeable': specifier: 4.9.3 version: 4.9.3 + '@scroll-tech/contracts': + specifier: 0.1.0 + version: 0.1.0 devDependencies: '@ethereum-waffle/mock-contract': @@ -39,37 +42,34 @@ devDependencies: version: 5.7.0 '@nomicfoundation/hardhat-network-helpers': specifier: ^1.0.9 - version: 1.0.9(hardhat@2.19.1) + version: 1.0.9(hardhat@2.19.2) '@nomiclabs/hardhat-ethers': specifier: ^2.2.3 - version: 2.2.3(ethers@5.7.2)(hardhat@2.19.1) + version: 2.2.3(ethers@5.7.2)(hardhat@2.19.2) '@nomiclabs/hardhat-etherscan': specifier: ^3.1.7 - version: 3.1.7(hardhat@2.19.1) + version: 3.1.7(hardhat@2.19.2) '@nomiclabs/hardhat-waffle': specifier: 2.0.6 - version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.1) + version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.2) '@openzeppelin/hardhat-upgrades': specifier: 1.28.0 - version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.1) + version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.2) '@openzeppelin/test-helpers': specifier: ^0.5.16 version: 0.5.16(bn.js@4.12.0) - '@scroll-tech/contracts': - specifier: 0.1.0 - version: 0.1.0 '@typechain/ethers-v5': specifier: ^7.2.0 - version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2) + version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.3.3) '@typechain/hardhat': specifier: ^7.0.0 - version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.1)(typechain@8.3.2) + version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.2)(typechain@8.3.2) '@types/cbor': specifier: 5.0.1 version: 5.0.1 '@types/chai': - specifier: ^4.3.10 - version: 4.3.10 + specifier: ^4.3.11 + version: 4.3.11 '@types/debug': specifier: ^4.1.12 version: 4.1.12 @@ -77,17 +77,17 @@ devDependencies: specifier: ^1.0.3 version: 1.0.3 '@types/mocha': - specifier: ^10.0.4 - version: 10.0.4 + specifier: ^10.0.6 + version: 10.0.6 '@types/node': - specifier: ^16.18.61 - version: 16.18.61 + specifier: ^16.18.68 + version: 16.18.68 '@typescript-eslint/eslint-plugin': - specifier: ^6.11.0 - version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2) + specifier: ^6.14.0 + version: 6.14.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.11.0 - version: 6.11.0(eslint@8.53.0)(typescript@5.2.2) + specifier: ^6.14.0 + version: 6.14.0(eslint@8.55.0)(typescript@5.3.3) abi-to-sol: specifier: ^0.6.6 version: 0.6.6 @@ -104,32 +104,32 @@ devDependencies: specifier: ^2.0.6 version: 2.0.6 eslint: - specifier: ^8.53.0 - version: 8.53.0 + specifier: ^8.55.0 + version: 8.55.0 eslint-config-prettier: - specifier: ^9.0.0 - version: 9.0.0(eslint@8.53.0) + specifier: ^9.1.0 + version: 9.1.0(eslint@8.55.0) eslint-plugin-prettier: specifier: ^5.0.1 - version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.53.0)(prettier@3.1.0) + version: 5.0.1(eslint-config-prettier@9.1.0)(eslint@8.55.0)(prettier@3.1.1) ethereum-waffle: specifier: ^3.4.4 - version: 3.4.4(typescript@5.2.2) + version: 3.4.4(typescript@5.3.3) ethers: specifier: ~5.7.2 version: 5.7.2 hardhat: - specifier: ~2.19.1 - version: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + specifier: ~2.19.2 + version: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) hardhat-abi-exporter: specifier: ^2.10.1 - version: 2.10.1(hardhat@2.19.1) + version: 2.10.1(hardhat@2.19.2) hardhat-contract-sizer: specifier: ^2.10.0 - version: 2.10.0(hardhat@2.19.1) + version: 2.10.0(hardhat@2.19.2) hardhat-gas-reporter: specifier: ^1.0.9 - version: 1.0.9(debug@4.3.4)(hardhat@2.19.1) + version: 1.0.9(debug@4.3.4)(hardhat@2.19.2) hardhat-ignore-warnings: specifier: ^0.2.6 version: 0.2.9 @@ -140,11 +140,11 @@ devDependencies: specifier: ^2.29.4 version: 2.29.4 prettier: - specifier: ^3.1.0 - version: 3.1.0 + specifier: ^3.1.1 + version: 3.1.1 prettier-plugin-solidity: specifier: 1.2.0 - version: 1.2.0(prettier@3.1.0) + version: 1.2.0(prettier@3.1.1) rlp: specifier: ^2.2.7 version: 2.2.7 @@ -156,22 +156,22 @@ devDependencies: version: github.com/smartcontractkit/chainlink-solhint-rules/cfc50b32f95b730304a50deb2e27e88d87115874 solhint-plugin-prettier: specifier: ^0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.0) + version: 0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.1) solidity-coverage: specifier: ^0.8.5 - version: 0.8.5(hardhat@2.19.1) + version: 0.8.5(hardhat@2.19.2) ts-node: - specifier: ^10.9.1 - version: 10.9.1(@types/node@16.18.61)(typescript@5.2.2) + specifier: ^10.9.2 + version: 10.9.2(@types/node@16.18.68)(typescript@5.3.3) tslib: specifier: ^2.6.2 version: 2.6.2 typechain: specifier: ^8.2.1 - version: 8.3.2(typescript@5.2.2) + version: 8.3.2(typescript@5.3.3) typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages: @@ -327,13 +327,13 @@ packages: deprecated: Please use @ensdomains/ens-contracts dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.53.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.53.0 + eslint: 8.55.0 eslint-visitor-keys: 3.4.3 dev: true @@ -342,8 +342,8 @@ packages: engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true - /@eslint/eslintrc@2.1.3: - resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 @@ -359,17 +359,17 @@ packages: - supports-color dev: true - /@eslint/js@8.53.0: - resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==} + /@eslint/js@8.55.0: + resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@eth-optimism/contracts@0.5.37(ethers@5.7.2): - resolution: {integrity: sha512-HbNUUDIM1dUAM0hWPfGp3l9/Zte40zi8QhVbUSIwdYRA7jG7cZgbteqavrjW8wwFqxkWX9IrtA0KAR7pNlSAIQ==} + /@eth-optimism/contracts@0.6.0(ethers@5.7.2): + resolution: {integrity: sha512-vQ04wfG9kMf1Fwy3FEMqH2QZbgS0gldKhcBeBUPfO8zu68L61VI97UDXmsMQXzTsEAxK8HnokW3/gosl4/NW3w==} peerDependencies: ethers: ^5 dependencies: - '@eth-optimism/core-utils': 0.10.1 + '@eth-optimism/core-utils': 0.12.0 '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 ethers: 5.7.2 @@ -378,8 +378,8 @@ packages: - utf-8-validate dev: false - /@eth-optimism/core-utils@0.10.1: - resolution: {integrity: sha512-IJvG5UtYvyz6An9QdohlCLoeB3NBFxx2lRJKlPzvYYlfugUNNCHsajRIWIwJTcPRRma0WPd46JUsKACLJDdNrA==} + /@eth-optimism/core-utils@0.12.0: + resolution: {integrity: sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==} dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-provider': 5.7.0 @@ -415,7 +415,7 @@ packages: - utf-8-validate dev: true - /@ethereum-waffle/compiler@3.4.4(typescript@5.2.2): + /@ethereum-waffle/compiler@3.4.4(typescript@5.3.3): resolution: {integrity: sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ==} engines: {node: '>=10.0'} dependencies: @@ -429,7 +429,7 @@ packages: node-fetch: 2.6.7 solc: 0.6.12 ts-generator: 0.1.1 - typechain: 3.0.0(typescript@5.2.2) + typechain: 3.0.0(typescript@5.3.3) transitivePeerDependencies: - bufferutil - encoding @@ -1040,13 +1040,13 @@ packages: - utf-8-validate dev: true - /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.19.1): + /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.19.2): resolution: {integrity: sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==} peerDependencies: hardhat: ^2.9.5 dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0: @@ -1155,17 +1155,17 @@ packages: '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.0 dev: true - /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.19.1): + /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.19.2): resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} peerDependencies: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: ethers: 5.7.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true - /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.19.1): + /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.19.2): resolution: {integrity: sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==} peerDependencies: hardhat: ^2.0.4 @@ -1176,7 +1176,7 @@ packages: chalk: 2.4.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 7.0.1 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) lodash: 4.17.21 semver: 6.3.0 table: 6.8.1 @@ -1185,7 +1185,7 @@ packages: - supports-color dev: true - /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.1): + /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.2): resolution: {integrity: sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==} peerDependencies: '@nomiclabs/hardhat-ethers': ^2.0.0 @@ -1194,11 +1194,11 @@ packages: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.1) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.2) '@types/sinon-chai': 3.2.8 - ethereum-waffle: 3.4.4(typescript@5.2.2) + ethereum-waffle: 3.4.4(typescript@5.3.3) ethers: 5.7.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true /@openzeppelin/contract-loader@0.6.3: @@ -1229,7 +1229,7 @@ packages: - encoding dev: true - /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.1): + /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.2): resolution: {integrity: sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==} hasBin: true peerDependencies: @@ -1242,15 +1242,15 @@ packages: '@nomiclabs/harhdat-etherscan': optional: true dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.1) - '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.19.1) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.2) + '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.19.2) '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) '@openzeppelin/platform-deploy-client': 0.8.0(debug@4.3.4) '@openzeppelin/upgrades-core': 1.30.1 chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) ethers: 5.7.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) proper-lockfile: 4.1.2 transitivePeerDependencies: - encoding @@ -1341,12 +1341,12 @@ packages: config-chain: 1.1.13 dev: true - /@prettier/sync@0.3.0(prettier@3.1.0): + /@prettier/sync@0.3.0(prettier@3.1.1): resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} peerDependencies: prettier: ^3.0.0 dependencies: - prettier: 3.1.0 + prettier: 3.1.1 dev: true /@resolver-engine/core@0.3.3: @@ -1392,7 +1392,7 @@ packages: /@scroll-tech/contracts@0.1.0: resolution: {integrity: sha512-aBbDOc3WB/WveZdpJYcrfvMYMz7ZTEiW8M9XMJLba8p9FAR5KGYB/cV+8+EUsq3MKt7C1BfR+WnXoTVdvwIY6w==} - dev: true + dev: false /@scure/base@1.1.1: resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} @@ -1667,10 +1667,10 @@ packages: typechain: ^3.0.0 dependencies: ethers: 5.7.2 - typechain: 3.0.0(typescript@5.2.2) + typechain: 3.0.0(typescript@5.3.3) dev: true - /@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2): + /@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.3.3): resolution: {integrity: sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==} peerDependencies: '@ethersproject/abi': ^5.0.0 @@ -1685,12 +1685,12 @@ packages: '@ethersproject/providers': 5.7.2 ethers: 5.7.2 lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@5.2.2) - typechain: 8.3.2(typescript@5.2.2) - typescript: 5.2.2 + ts-essentials: 7.0.3(typescript@5.3.3) + typechain: 8.3.2(typescript@5.3.3) + typescript: 5.3.3 dev: true - /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.1)(typechain@8.3.2): + /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.2)(typechain@8.3.2): resolution: {integrity: sha512-XB79i5ewg9Met7gMVGfgVkmypicbnI25T5clJBEooMoW2161p4zvKFpoS2O+lBppQyMrPIZkdvl2M3LMDayVcA==} peerDependencies: '@ethersproject/abi': ^5.4.7 @@ -1702,23 +1702,23 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2) + '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.3.3) ethers: 5.7.2 fs-extra: 9.1.0 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) - typechain: 8.3.2(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) + typechain: 8.3.2(typescript@5.3.3) dev: true /@types/bn.js@4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/bn.js@5.1.1: resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/cacheable-request@6.0.2: @@ -1726,24 +1726,24 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 16.18.61 + '@types/node': 16.18.68 '@types/responselike': 1.0.0 dev: true /@types/cbor@5.0.1: resolution: {integrity: sha512-zVqJy2KzusZPLOgyGJDnOIbu3DxIGGqxYbEwtEEe4Z+la8jwIhOyb+GMrlHafs5tvKruwf8f8qOYP6zTvse/pw==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true - /@types/chai@4.3.10: - resolution: {integrity: sha512-of+ICnbqjmFCiixUnqRulbylyXQrPqIGf/B3Jax1wIF3DvSheysQxAWvqHhZiW3IQrycvokcLcFQlveGp+vyNg==} + /@types/chai@4.3.11: + resolution: {integrity: sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==} dev: true /@types/concat-stream@1.6.1: resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/debug@4.1.12: @@ -1763,7 +1763,7 @@ packages: /@types/form-data@0.0.33: resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/glob@7.1.1: @@ -1771,7 +1771,7 @@ packages: dependencies: '@types/events': 3.0.0 '@types/minimatch': 3.0.3 - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/http-cache-semantics@4.0.1: @@ -1785,7 +1785,7 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/lru-cache@5.1.1: @@ -1799,11 +1799,11 @@ packages: /@types/mkdirp@0.5.2: resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true - /@types/mocha@10.0.4: - resolution: {integrity: sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==} + /@types/mocha@10.0.6: + resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} dev: true /@types/ms@0.7.31: @@ -1813,7 +1813,7 @@ packages: /@types/node-fetch@2.6.2: resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 form-data: 3.0.1 dev: true @@ -1825,8 +1825,8 @@ packages: resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==} dev: true - /@types/node@16.18.61: - resolution: {integrity: sha512-k0N7BqGhJoJzdh6MuQg1V1ragJiXTh8VUBAZTWjJ9cUq23SG0F0xavOwZbhiP4J3y20xd6jxKx+xNUhkMAi76Q==} + /@types/node@16.18.68: + resolution: {integrity: sha512-sG3hPIQwJLoewrN7cr0dwEy+yF5nD4D/4FxtQpFciRD/xwUzgD+G05uxZHv5mhfXo4F9Jkp13jjn0CC2q325sg==} dev: true /@types/node@8.10.66: @@ -1836,7 +1836,7 @@ packages: /@types/pbkdf2@3.1.0: resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/prettier@2.7.1: @@ -1850,26 +1850,26 @@ packages: /@types/readable-stream@2.3.15: resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 safe-buffer: 5.1.2 dev: true /@types/resolve@0.0.8: resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/responselike@1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/secp256k1@4.0.3: resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/semver@7.5.0: @@ -1879,7 +1879,7 @@ packages: /@types/sinon-chai@3.2.8: resolution: {integrity: sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g==} dependencies: - '@types/chai': 4.3.10 + '@types/chai': 4.3.11 '@types/sinon': 10.0.13 dev: true @@ -1893,8 +1893,8 @@ packages: resolution: {integrity: sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==} dev: true - /@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==} + /@typescript-eslint/eslint-plugin@6.14.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -1905,25 +1905,25 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.8.0 - '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2) - '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/parser': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/type-utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 + eslint: 8.55.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==} + /@typescript-eslint/parser@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1932,27 +1932,27 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 - typescript: 5.2.2 + eslint: 8.55.0 + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager@6.11.0: - resolution: {integrity: sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==} + /@typescript-eslint/scope-manager@6.14.0: + resolution: {integrity: sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 dev: true - /@typescript-eslint/type-utils@6.11.0(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==} + /@typescript-eslint/type-utils@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1961,23 +1961,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) - '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + eslint: 8.55.0 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types@6.11.0: - resolution: {integrity: sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==} + /@typescript-eslint/types@6.14.0: + resolution: {integrity: sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.11.0(typescript@5.2.2): - resolution: {integrity: sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==} + /@typescript-eslint/typescript-estree@6.14.0(typescript@5.3.3): + resolution: {integrity: sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1985,42 +1985,42 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@6.11.0(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==} + /@typescript-eslint/utils@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) - eslint: 8.53.0 + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + eslint: 8.55.0 semver: 7.5.4 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys@6.11.0: - resolution: {integrity: sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==} + /@typescript-eslint/visitor-keys@6.14.0: + resolution: {integrity: sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.11.0 + '@typescript-eslint/types': 6.14.0 eslint-visitor-keys: 3.4.3 dev: true @@ -4714,16 +4714,16 @@ packages: source-map: 0.2.0 dev: true - /eslint-config-prettier@9.0.0(eslint@8.53.0): - resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} + /eslint-config-prettier@9.1.0(eslint@8.55.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.53.0 + eslint: 8.55.0 dev: true - /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.0.0)(eslint@8.53.0)(prettier@3.1.0): + /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.1.0)(eslint@8.55.0)(prettier@3.1.1): resolution: {integrity: sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -4737,9 +4737,9 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.53.0 - eslint-config-prettier: 9.0.0(eslint@8.53.0) - prettier: 3.1.0 + eslint: 8.55.0 + eslint-config-prettier: 9.1.0(eslint@8.55.0) + prettier: 3.1.1 prettier-linter-helpers: 1.0.0 synckit: 0.8.5 dev: true @@ -4757,15 +4757,15 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.53.0: - resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==} + /eslint@8.55.0: + resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) '@eslint-community/regexpp': 4.8.0 - '@eslint/eslintrc': 2.1.3 - '@eslint/js': 8.53.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.55.0 '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -5060,13 +5060,13 @@ packages: '@scure/bip39': 1.1.0 dev: true - /ethereum-waffle@3.4.4(typescript@5.2.2): + /ethereum-waffle@3.4.4(typescript@5.3.3): resolution: {integrity: sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q==} engines: {node: '>=10.0'} hasBin: true dependencies: '@ethereum-waffle/chai': 3.4.4 - '@ethereum-waffle/compiler': 3.4.4(typescript@5.2.2) + '@ethereum-waffle/compiler': 3.4.4(typescript@5.3.3) '@ethereum-waffle/mock-contract': 3.4.4 '@ethereum-waffle/provider': 3.4.4 ethers: 5.7.2 @@ -6218,7 +6218,7 @@ packages: har-schema: 2.0.0 dev: true - /hardhat-abi-exporter@2.10.1(hardhat@2.19.1): + /hardhat-abi-exporter@2.10.1(hardhat@2.19.2): resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==} engines: {node: '>=14.14.0'} peerDependencies: @@ -6226,28 +6226,28 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 delete-empty: 3.0.0 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true - /hardhat-contract-sizer@2.10.0(hardhat@2.19.1): + /hardhat-contract-sizer@2.10.0(hardhat@2.19.2): resolution: {integrity: sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==} peerDependencies: hardhat: ^2.0.0 dependencies: chalk: 4.1.2 cli-table3: 0.6.3 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) strip-ansi: 6.0.1 dev: true - /hardhat-gas-reporter@1.0.9(debug@4.3.4)(hardhat@2.19.1): + /hardhat-gas-reporter@1.0.9(debug@4.3.4)(hardhat@2.19.2): resolution: {integrity: sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==} peerDependencies: hardhat: ^2.0.2 dependencies: array-uniq: 1.0.3 eth-gas-reporter: 0.2.27(debug@4.3.4) - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) sha1: 1.1.1 transitivePeerDependencies: - '@codechecks/client' @@ -6264,8 +6264,8 @@ packages: solidity-comments: 0.0.2 dev: true - /hardhat@2.19.1(ts-node@10.9.1)(typescript@5.2.2): - resolution: {integrity: sha512-bsWa63g1GB78ZyMN08WLhFElLPA+J+pShuKD1BFO2+88g3l+BL3R07vj9deIi9dMbssxgE714Gof1dBEDGqnCw==} + /hardhat@2.19.2(ts-node@10.9.2)(typescript@5.3.3): + resolution: {integrity: sha512-CRU3+0Cc8Qh9UpxKd8cLADDPes7ZDtKj4dTK+ERtLBomEzhRPLWklJn4VKOwjre9/k8GNd/e9DYxpfuzcxbXPQ==} hasBin: true peerDependencies: ts-node: '*' @@ -6320,9 +6320,9 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.1(@types/node@16.18.61)(typescript@5.2.2) + ts-node: 10.9.2(@types/node@16.18.68)(typescript@5.3.3) tsort: 0.0.1 - typescript: 5.2.2 + typescript: 5.3.3 undici: 5.19.1 uuid: 8.3.2 ws: 7.5.9 @@ -8909,14 +8909,14 @@ packages: dev: true optional: true - /prettier-plugin-solidity@1.2.0(prettier@3.1.0): + /prettier-plugin-solidity@1.2.0(prettier@3.1.1): resolution: {integrity: sha512-fgxcUZpVAP+LlRfy5JI5oaAkXGkmsje2VJ5krv/YMm+rcTZbIUwFguSw5f+WFuttMjpDm6wB4UL7WVkArEfiVA==} engines: {node: '>=16'} peerDependencies: prettier: '>=2.3.0' dependencies: '@solidity-parser/parser': 0.16.2 - prettier: 3.1.0 + prettier: 3.1.1 semver: 7.5.4 solidity-comments-extractor: 0.0.7 dev: true @@ -8927,8 +8927,8 @@ packages: hasBin: true dev: true - /prettier@3.1.0: - resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==} + /prettier@3.1.1: + resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} engines: {node: '>=14'} hasBin: true dev: true @@ -9960,16 +9960,16 @@ packages: - debug dev: true - /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.0): + /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.1): resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} peerDependencies: prettier: ^3.0.0 prettier-plugin-solidity: ^1.0.0 dependencies: - '@prettier/sync': 0.3.0(prettier@3.1.0) - prettier: 3.1.0 + '@prettier/sync': 0.3.0(prettier@3.1.1) + prettier: 3.1.1 prettier-linter-helpers: 1.0.0 - prettier-plugin-solidity: 1.2.0(prettier@3.1.0) + prettier-plugin-solidity: 1.2.0(prettier@3.1.1) dev: true /solhint@4.0.0: @@ -10114,7 +10114,7 @@ packages: solidity-comments-win32-x64-msvc: 0.0.2 dev: true - /solidity-coverage@0.8.5(hardhat@2.19.1): + /solidity-coverage@0.8.5(hardhat@2.19.2): resolution: {integrity: sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==} hasBin: true peerDependencies: @@ -10130,7 +10130,7 @@ packages: ghost-testrpc: 0.0.2 global-modules: 2.0.0 globby: 10.0.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) jsonschema: 1.4.0 lodash: 4.17.21 mocha: 10.2.0 @@ -10719,13 +10719,13 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ts-api-utils@1.0.3(typescript@5.2.2): + /ts-api-utils@1.0.3(typescript@5.3.3): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.3 dev: true /ts-command-line-args@2.5.1: @@ -10742,20 +10742,20 @@ packages: resolution: {integrity: sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==} dev: true - /ts-essentials@6.0.7(typescript@5.2.2): + /ts-essentials@6.0.7(typescript@5.3.3): resolution: {integrity: sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==} peerDependencies: typescript: '>=3.7.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.3 dev: true - /ts-essentials@7.0.3(typescript@5.2.2): + /ts-essentials@7.0.3(typescript@5.3.3): resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} peerDependencies: typescript: '>=3.7.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.3 dev: true /ts-generator@0.1.1: @@ -10773,8 +10773,8 @@ packages: ts-essentials: 1.0.4 dev: true - /ts-node@10.9.1(@types/node@16.18.61)(typescript@5.2.2): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + /ts-node@10.9.2(@types/node@16.18.68)(typescript@5.3.3): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: '@swc/core': '>=1.2.50' @@ -10792,14 +10792,14 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.3 - '@types/node': 16.18.61 + '@types/node': 16.18.68 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.2.2 + typescript: 5.3.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 dev: true @@ -10884,7 +10884,7 @@ packages: resolution: {integrity: sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==} dev: true - /typechain@3.0.0(typescript@5.2.2): + /typechain@3.0.0(typescript@5.3.3): resolution: {integrity: sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg==} hasBin: true dependencies: @@ -10893,14 +10893,14 @@ packages: fs-extra: 7.0.1 js-sha3: 0.8.0 lodash: 4.17.21 - ts-essentials: 6.0.7(typescript@5.2.2) + ts-essentials: 6.0.7(typescript@5.3.3) ts-generator: 0.1.1 transitivePeerDependencies: - supports-color - typescript dev: true - /typechain@8.3.2(typescript@5.2.2): + /typechain@8.3.2(typescript@5.3.3): resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} hasBin: true peerDependencies: @@ -10915,8 +10915,8 @@ packages: mkdirp: 1.0.4 prettier: 2.8.8 ts-command-line-args: 2.5.1 - ts-essentials: 7.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-essentials: 7.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -10969,8 +10969,8 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true - /typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} hasBin: true dev: true diff --git a/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol b/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol index 563c1354b66..979cc6138ac 100644 --- a/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol +++ b/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol @@ -4,6 +4,12 @@ pragma solidity 0.8.6; import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +struct CheckData { + uint256 checkBurnAmount; + uint256 performBurnAmount; + bytes32 eventSig; +} + contract SimpleLogUpkeepCounter is ILogAutomation { event PerformingUpkeep( address indexed from, @@ -11,14 +17,17 @@ contract SimpleLogUpkeepCounter is ILogAutomation { uint256 lastBlock, uint256 previousBlock, uint256 counter, - uint256 timeToPerform + uint256 timeToPerform, + bool isRecovered ); + mapping(bytes32 => bool) public dummyMap; // used to force storage lookup uint256 public lastBlock; uint256 public previousPerformBlock; uint256 public initialBlock; uint256 public counter; uint256 public timeToPerform; + bool public isRecovered; constructor() { previousPerformBlock = 0; @@ -27,8 +36,27 @@ contract SimpleLogUpkeepCounter is ILogAutomation { counter = 0; } - function checkLog(Log calldata log, bytes memory) external view override returns (bool, bytes memory) { - return (true, abi.encode(log)); + function _checkDataConfig(CheckData memory) external {} + + function checkLog(Log calldata log, bytes calldata checkData) external view override returns (bool, bytes memory) { + (uint256 checkBurnAmount, uint256 performBurnAmount, bytes32 eventSig) = abi.decode( + checkData, + (uint256, uint256, bytes32) + ); + uint256 startGas = gasleft(); + bytes32 dummyIndex = blockhash(block.number - 1); + bool dummy; + // burn gas + if (checkBurnAmount > 0) { + while (startGas - gasleft() < checkBurnAmount) { + dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads + dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); + } + } + if (log.topics[2] == eventSig) { + return (true, abi.encode(log, block.number, checkData)); + } + return (false, abi.encode(log, block.number, checkData)); } function performUpkeep(bytes calldata performData) external override { @@ -38,8 +66,34 @@ contract SimpleLogUpkeepCounter is ILogAutomation { lastBlock = block.number; counter = counter + 1; previousPerformBlock = lastBlock; - Log memory log = abi.decode(performData, (Log)); + (Log memory log, uint256 checkBlock, bytes memory extraData) = abi.decode(performData, (Log, uint256, bytes)); timeToPerform = block.timestamp - log.timestamp; - emit PerformingUpkeep(tx.origin, initialBlock, lastBlock, previousPerformBlock, counter, timeToPerform); + isRecovered = false; + if (checkBlock != log.blockNumber) { + isRecovered = true; + } + (uint256 checkBurnAmount, uint256 performBurnAmount, bytes32 eventSig) = abi.decode( + extraData, + (uint256, uint256, bytes32) + ); + uint256 startGas = gasleft(); + bytes32 dummyIndex = blockhash(block.number - 1); + bool dummy; + // burn gas + if (performBurnAmount > 0) { + while (startGas - gasleft() < performBurnAmount) { + dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads + dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); + } + } + emit PerformingUpkeep( + tx.origin, + initialBlock, + lastBlock, + previousPerformBlock, + counter, + timeToPerform, + isRecovered + ); } } diff --git a/contracts/src/v0.8/tests/LogEmitter.sol b/contracts/src/v0.8/tests/LogEmitter.sol index d3f950c5ccb..37306cc2bc5 100644 --- a/contracts/src/v0.8/tests/LogEmitter.sol +++ b/contracts/src/v0.8/tests/LogEmitter.sol @@ -5,6 +5,7 @@ contract LogEmitter { event Log1(uint256); event Log2(uint256 indexed); event Log3(string); + event Log4(uint256 indexed, uint256 indexed); function EmitLog1(uint256[] memory v) public { for (uint256 i = 0; i < v.length; i++) { @@ -23,4 +24,10 @@ contract LogEmitter { emit Log3(v[i]); } } + + function EmitLog4(uint256 v, uint256 w, uint256 c) public { + for (uint256 i = 0; i < c; i++) { + emit Log4(v, w); + } + } } diff --git a/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol b/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol index d7cc5b86c5a..9d4acecdef9 100644 --- a/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol +++ b/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol @@ -83,8 +83,8 @@ abstract contract SubscriptionAPI is ConfirmedOwner, IERC677Receiver, IVRFSubscr // A discrepancy with this contract's native balance indicates someone // sent native using transfer and so we may need to use recoverNativeFunds. uint96 public s_totalNativeBalance; - mapping(address => uint96) /* oracle */ /* LINK balance */ internal s_withdrawableTokens; - mapping(address => uint96) /* oracle */ /* native balance */ internal s_withdrawableNative; + uint96 internal s_withdrawableTokens; + uint96 internal s_withdrawableNative; event SubscriptionCreated(uint256 indexed subId, address owner); event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); @@ -204,18 +204,19 @@ abstract contract SubscriptionAPI is ConfirmedOwner, IERC677Receiver, IVRFSubscr } /* - * @notice Oracle withdraw LINK earned through fulfilling requests + * @notice withdraw LINK earned through fulfilling requests * @param recipient where to send the funds * @param amount amount to withdraw */ - function oracleWithdraw(address recipient, uint96 amount) external nonReentrant { + function withdraw(address recipient) external nonReentrant onlyOwner { if (address(LINK) == address(0)) { revert LinkNotSet(); } - if (s_withdrawableTokens[msg.sender] < amount) { + if (s_withdrawableTokens == 0) { revert InsufficientBalance(); } - s_withdrawableTokens[msg.sender] -= amount; + uint96 amount = s_withdrawableTokens; + s_withdrawableTokens -= amount; s_totalBalance -= amount; if (!LINK.transfer(recipient, amount)) { revert InsufficientBalance(); @@ -223,16 +224,17 @@ abstract contract SubscriptionAPI is ConfirmedOwner, IERC677Receiver, IVRFSubscr } /* - * @notice Oracle withdraw native earned through fulfilling requests + * @notice withdraw native earned through fulfilling requests * @param recipient where to send the funds * @param amount amount to withdraw */ - function oracleWithdrawNative(address payable recipient, uint96 amount) external nonReentrant { - if (s_withdrawableNative[msg.sender] < amount) { + function withdrawNative(address payable recipient) external nonReentrant onlyOwner { + if (s_withdrawableNative == 0) { revert InsufficientBalance(); } // Prevent re-entrancy by updating state before transfer. - s_withdrawableNative[msg.sender] -= amount; + uint96 amount = s_withdrawableNative; + s_withdrawableNative -= amount; s_totalNativeBalance -= amount; (bool sent, ) = recipient.call{value: amount}(""); if (!sent) { diff --git a/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol b/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol index e0e46fe67b7..a265cea4ed9 100644 --- a/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol +++ b/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol @@ -44,11 +44,11 @@ contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { address sender; bytes extraArgs; } - mapping(bytes32 => address) /* keyHash */ /* oracle */ public s_provingKeys; + mapping(bytes32 => bool) /* keyHash */ /* exists */ public s_provingKeys; bytes32[] public s_provingKeyHashes; mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; - event ProvingKeyRegistered(bytes32 keyHash, address indexed oracle); - event ProvingKeyDeregistered(bytes32 keyHash, address indexed oracle); + event ProvingKeyRegistered(bytes32 keyHash); + event ProvingKeyDeregistered(bytes32 keyHash); event RandomWordsRequested( bytes32 indexed keyHash, uint256 requestId, @@ -94,28 +94,26 @@ contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { } /** - * @notice Registers a proving key to an oracle. - * @param oracle address of the oracle + * @notice Registers a proving key to. * @param publicProvingKey key that oracle can use to submit vrf fulfillments */ - function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { + function registerProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh] != address(0)) { + if (s_provingKeys[kh]) { revert ProvingKeyAlreadyRegistered(kh); } - s_provingKeys[kh] = oracle; + s_provingKeys[kh] = true; s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh, oracle); + emit ProvingKeyRegistered(kh); } /** - * @notice Deregisters a proving key to an oracle. + * @notice Deregisters a proving key. * @param publicProvingKey key that oracle can use to submit vrf fulfillments */ function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { bytes32 kh = hashOfKey(publicProvingKey); - address oracle = s_provingKeys[kh]; - if (oracle == address(0)) { + if (!s_provingKeys[kh]) { revert NoSuchProvingKey(kh); } delete s_provingKeys[kh]; @@ -127,7 +125,7 @@ contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { s_provingKeyHashes.pop(); } } - emit ProvingKeyDeregistered(kh, oracle); + emit ProvingKeyDeregistered(kh); } /** @@ -355,8 +353,7 @@ contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { ) internal view returns (Output memory) { bytes32 keyHash = hashOfKey(proof.pk); // Only registered proving keys are permitted. - address oracle = s_provingKeys[keyHash]; - if (oracle == address(0)) { + if (!s_provingKeys[keyHash]) { revert NoSuchProvingKey(keyHash); } uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); @@ -423,7 +420,7 @@ contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; // We want to charge users exactly for how much gas they use in their callback. // The gasAfterPaymentCalculation is meant to cover these additional operations where we - // decrement the subscription balance and increment the oracles withdrawable balance. + // decrement the subscription balance and increment the withdrawable balance. uint96 payment = _calculatePaymentAmount( startGas, s_config.gasAfterPaymentCalculation, @@ -435,13 +432,13 @@ contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { revert InsufficientBalance(); } s_subscriptions[rc.subId].nativeBalance -= payment; - s_withdrawableNative[s_provingKeys[output.keyHash]] += payment; + s_withdrawableNative += payment; } else { if (s_subscriptions[rc.subId].balance < payment) { revert InsufficientBalance(); } s_subscriptions[rc.subId].balance -= payment; - s_withdrawableTokens[s_provingKeys[output.keyHash]] += payment; + s_withdrawableTokens += payment; } // Include payment in the event for tracking costs. diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol b/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol index 02cb15e38a4..ded916699b8 100644 --- a/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol +++ b/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol @@ -50,19 +50,19 @@ contract ExposedVRFCoordinatorV2_5 is VRFCoordinatorV2_5 { s_totalNativeBalance = newBalance; } - function setWithdrawableTokensTestingOnlyXXX(address oracle, uint96 newBalance) external { - s_withdrawableTokens[oracle] = newBalance; + function setWithdrawableTokensTestingOnlyXXX(uint96 newBalance) external { + s_withdrawableTokens = newBalance; } - function getWithdrawableTokensTestingOnlyXXX(address oracle) external view returns (uint96) { - return s_withdrawableTokens[oracle]; + function getWithdrawableTokensTestingOnlyXXX() external view returns (uint96) { + return s_withdrawableTokens; } - function setWithdrawableNativeTestingOnlyXXX(address oracle, uint96 newBalance) external { - s_withdrawableNative[oracle] = newBalance; + function setWithdrawableNativeTestingOnlyXXX(uint96 newBalance) external { + s_withdrawableNative = newBalance; } - function getWithdrawableNativeTestingOnlyXXX(address oracle) external view returns (uint96) { - return s_withdrawableNative[oracle]; + function getWithdrawableNativeTestingOnlyXXX() external view returns (uint96) { + return s_withdrawableNative; } } diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol index 4837411955c..ca29adac87c 100644 --- a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol @@ -56,11 +56,11 @@ contract VRFCoordinatorV2PlusUpgradedVersion is bytes extraArgs; } - mapping(bytes32 => address) /* keyHash */ /* oracle */ internal s_provingKeys; + mapping(bytes32 => bool) /* keyHash */ /* exists */ internal s_provingKeys; bytes32[] public s_provingKeyHashes; mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; - event ProvingKeyRegistered(bytes32 keyHash, address indexed oracle); + event ProvingKeyRegistered(bytes32 keyHash); event RandomWordsRequested( bytes32 indexed keyHash, uint256 requestId, @@ -108,17 +108,16 @@ contract VRFCoordinatorV2PlusUpgradedVersion is /** * @notice Registers a proving key to an oracle. - * @param oracle address of the oracle * @param publicProvingKey key that oracle can use to submit vrf fulfillments */ - function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { + function registerProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh] != address(0)) { + if (s_provingKeys[kh]) { revert ProvingKeyAlreadyRegistered(kh); } - s_provingKeys[kh] = oracle; + s_provingKeys[kh] = true; s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh, oracle); + emit ProvingKeyRegistered(kh); } /** @@ -346,8 +345,7 @@ contract VRFCoordinatorV2PlusUpgradedVersion is ) internal view returns (Output memory) { bytes32 keyHash = hashOfKey(proof.pk); // Only registered proving keys are permitted. - address oracle = s_provingKeys[keyHash]; - if (oracle == address(0)) { + if (!s_provingKeys[keyHash]) { revert NoSuchProvingKey(keyHash); } uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); @@ -426,13 +424,13 @@ contract VRFCoordinatorV2PlusUpgradedVersion is revert InsufficientBalance(); } s_subscriptions[rc.subId].nativeBalance -= payment; - s_withdrawableNative[s_provingKeys[output.keyHash]] += payment; + s_withdrawableNative += payment; } else { if (s_subscriptions[rc.subId].balance < payment) { revert InsufficientBalance(); } s_subscriptions[rc.subId].balance -= payment; - s_withdrawableTokens[s_provingKeys[output.keyHash]] += payment; + s_withdrawableTokens += payment; } // Include payment in the event for tracking costs. diff --git a/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Plus_Migration.t.sol b/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Plus_Migration.t.sol index d7a54d6223c..b6056286261 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Plus_Migration.t.sol +++ b/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Plus_Migration.t.sol @@ -331,8 +331,8 @@ contract VRFCoordinatorV2Plus_Migration is BaseTest { function registerProvingKey() public { uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(UNCOMPRESSED_PUBLIC_KEY); - v1Coordinator.registerProvingKey(OWNER, uncompressedKeyParts); - v1Coordinator_noLink.registerProvingKey(OWNER, uncompressedKeyParts); + v1Coordinator.registerProvingKey(uncompressedKeyParts); + v1Coordinator_noLink.registerProvingKey(uncompressedKeyParts); } // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and diff --git a/contracts/test/v0.8/foundry/vrf/VRFV2Plus.t.sol b/contracts/test/v0.8/foundry/vrf/VRFV2Plus.t.sol index e2734f17288..62c08533d3f 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFV2Plus.t.sol +++ b/contracts/test/v0.8/foundry/vrf/VRFV2Plus.t.sol @@ -124,12 +124,12 @@ contract VRFV2Plus is BaseTest { // Should revert when already registered. uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.ProvingKeyAlreadyRegistered.selector, vrfKeyHash)); - s_testCoordinator.registerProvingKey(LINK_WHALE, uncompressedKeyParts); + s_testCoordinator.registerProvingKey(uncompressedKeyParts); } function registerProvingKey() public { uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); - s_testCoordinator.registerProvingKey(LINK_WHALE, uncompressedKeyParts); + s_testCoordinator.registerProvingKey(uncompressedKeyParts); } // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and diff --git a/contracts/test/v0.8/foundry/vrf/VRFV2PlusSubscriptionAPI.t.sol b/contracts/test/v0.8/foundry/vrf/VRFV2PlusSubscriptionAPI.t.sol index 335e64ff7ef..0f34003d9ae 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFV2PlusSubscriptionAPI.t.sol +++ b/contracts/test/v0.8/foundry/vrf/VRFV2PlusSubscriptionAPI.t.sol @@ -315,25 +315,25 @@ contract VRFV2PlusSubscriptionAPITest is BaseTest { assertEq(address(s_subscriptionAPI).balance, s_subscriptionAPI.s_totalNativeBalance()); } - function testOracleWithdrawNoLink() public { + function testWithdrawNoLink() public { // CASE: no link token set vm.expectRevert(SubscriptionAPI.LinkNotSet.selector); - s_subscriptionAPI.oracleWithdraw(OWNER, 1 ether); + s_subscriptionAPI.withdraw(OWNER); } - function testOracleWithdrawInsufficientBalance() public { + function testWithdrawInsufficientBalance() public { // CASE: link token set, trying to withdraw // more than balance MockLinkToken linkToken = new MockLinkToken(); s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - // call oracleWithdraw + // call withdraw vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); - s_subscriptionAPI.oracleWithdraw(OWNER, 1 ether); + s_subscriptionAPI.withdraw(OWNER); } - function testOracleWithdrawSufficientBalanceLinkSet() public { + function testWithdrawSufficientBalanceLinkSet() public { // CASE: link token set, trying to withdraw // less than balance MockLinkToken linkToken = new MockLinkToken(); @@ -344,58 +344,72 @@ contract VRFV2PlusSubscriptionAPITest is BaseTest { bool success = linkToken.transfer(address(s_subscriptionAPI), 10 ether); assertTrue(success, "failed link transfer"); - // set the withdrawable tokens of the oracle to be 1 ether - address oracle = makeAddr("oracle"); - s_subscriptionAPI.setWithdrawableTokensTestingOnlyXXX(oracle, 1 ether); - assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(oracle), 1 ether); + // set the withdrawable tokens of the contract to be 1 ether + s_subscriptionAPI.setWithdrawableTokensTestingOnlyXXX(1 ether); + assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(), 1 ether); // set the total balance to be the same as the link balance for consistency // (this is not necessary for the test, but just to be sane) s_subscriptionAPI.setTotalBalanceTestingOnlyXXX(10 ether); - // call oracleWithdraw from oracle address - changePrank(oracle); - s_subscriptionAPI.oracleWithdraw(oracle, 1 ether); - // assert link balance of oracle - assertEq(linkToken.balanceOf(oracle), 1 ether, "oracle link balance incorrect"); + // call Withdraw from owner address + uint256 ownerBalance = linkToken.balanceOf(OWNER); + changePrank(OWNER); + s_subscriptionAPI.withdraw(OWNER); + // assert link balance of owner + assertEq(linkToken.balanceOf(OWNER) - ownerBalance, 1 ether, "owner link balance incorrect"); // assert state of subscription api - assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(oracle), 0, "oracle withdrawable tokens incorrect"); + assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(), 0, "owner withdrawable tokens incorrect"); // assert that total balance is changed by the withdrawn amount assertEq(s_subscriptionAPI.s_totalBalance(), 9 ether, "total balance incorrect"); } - function testOracleWithdrawNativeInsufficientBalance() public { + function testWithdrawNativeInsufficientBalance() public { // CASE: trying to withdraw more than balance // should revert with InsufficientBalance - // call oracleWithdrawNative + // call WithdrawNative + changePrank(OWNER); vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); - s_subscriptionAPI.oracleWithdrawNative(payable(OWNER), 1 ether); + s_subscriptionAPI.withdrawNative(payable(OWNER)); + } + + function testWithdrawLinkInvalidOwner() public { + address invalidAddress = makeAddr("invalidAddress"); + changePrank(invalidAddress); + vm.expectRevert("Only callable by owner"); + s_subscriptionAPI.withdraw(payable(OWNER)); } - function testOracleWithdrawNativeSufficientBalance() public { + function testWithdrawNativeInvalidOwner() public { + address invalidAddress = makeAddr("invalidAddress"); + changePrank(invalidAddress); + vm.expectRevert("Only callable by owner"); + s_subscriptionAPI.withdrawNative(payable(OWNER)); + } + + function testWithdrawNativeSufficientBalance() public { // CASE: trying to withdraw less than balance // should withdraw successfully // transfer 10 ether to the contract to withdraw vm.deal(address(s_subscriptionAPI), 10 ether); - // set the withdrawable eth of the oracle to be 1 ether - address oracle = makeAddr("oracle"); - s_subscriptionAPI.setWithdrawableNativeTestingOnlyXXX(oracle, 1 ether); - assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(oracle), 1 ether); + // set the withdrawable eth of the contract to be 1 ether + s_subscriptionAPI.setWithdrawableNativeTestingOnlyXXX(1 ether); + assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(), 1 ether); // set the total balance to be the same as the eth balance for consistency // (this is not necessary for the test, but just to be sane) s_subscriptionAPI.setTotalNativeBalanceTestingOnlyXXX(10 ether); - // call oracleWithdrawNative from oracle address - changePrank(oracle); - s_subscriptionAPI.oracleWithdrawNative(payable(oracle), 1 ether); - // assert native balance of oracle - assertEq(address(oracle).balance, 1 ether, "oracle native balance incorrect"); + // call WithdrawNative from owner address + changePrank(OWNER); + s_subscriptionAPI.withdrawNative(payable(OWNER)); + // assert native balance + assertEq(address(OWNER).balance, 1 ether, "owner native balance incorrect"); // assert state of subscription api - assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(oracle), 0, "oracle withdrawable native incorrect"); + assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(), 0, "owner withdrawable native incorrect"); // assert that total balance is changed by the withdrawn amount assertEq(s_subscriptionAPI.s_totalNativeBalance(), 9 ether, "total native balance incorrect"); } diff --git a/core/cbor/cbor_test.go b/core/cbor/cbor_test.go index 39a2da479b7..cf1390cc908 100644 --- a/core/cbor/cbor_test.go +++ b/core/cbor/cbor_test.go @@ -10,14 +10,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_ParseCBOR(t *testing.T) { t.Parallel() - address, err := utils.TryParseHex("0x8bd112d3f8f92e41c861939545ad387307af9703") + address, err := hex.DecodeString("0x8bd112d3f8f92e41c861939545ad387307af9703") require.NoError(t, err) tests := []struct { diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index 255d802720a..5dd70992382 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -216,7 +216,8 @@ func (c *chainClient) SendTransaction(ctx context.Context, tx *types.Transaction func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) { err := c.SendTransaction(ctx, tx) - return ClassifySendError(err, c.logger, tx, fromAddress, c.IsL2()) + returnCode := ClassifySendError(err, c.logger, tx, fromAddress, c.IsL2()) + return returnCode, err } func (c *chainClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (evmtypes.Nonce, error) { diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go index f32ec011445..61635c59c6b 100644 --- a/core/chains/evm/client/client.go +++ b/core/chains/evm/client/client.go @@ -14,8 +14,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/common/config" htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -220,7 +220,8 @@ func (client *client) HeaderByHash(ctx context.Context, h common.Hash) (*types.H func (client *client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) { err := client.SendTransaction(ctx, tx) - return ClassifySendError(err, client.logger, tx, fromAddress, client.pool.ChainType().IsL2()) + returnCode := ClassifySendError(err, client.logger, tx, fromAddress, client.pool.ChainType().IsL2()) + return returnCode, err } // SendTransaction also uses the sendonly HTTP RPC URLs if set diff --git a/core/chains/evm/client/client_test.go b/core/chains/evm/client/client_test.go index 631b5722dec..281b8bf4227 100644 --- a/core/chains/evm/client/client_test.go +++ b/core/chains/evm/client/client_test.go @@ -26,9 +26,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func mustNewClient(t *testing.T, wsURL string, sendonlys ...url.URL) client.Client { @@ -417,7 +417,7 @@ func TestEthClient_HeaderByNumber(t *testing.T) { func TestEthClient_SendTransaction_NoSecondaryURL(t *testing.T) { t.Parallel() - tx := types.NewTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := cltest.NewLegacyTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) wsURL := testutils.NewWSServer(t, &cltest.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { switch method { @@ -449,7 +449,7 @@ func TestEthClient_SendTransaction_NoSecondaryURL(t *testing.T) { func TestEthClient_SendTransaction_WithSecondaryURLs(t *testing.T) { t.Parallel() - tx := types.NewTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := cltest.NewLegacyTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) wsURL := testutils.NewWSServer(t, &cltest.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { switch method { @@ -494,7 +494,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { t.Parallel() fromAddress := testutils.NewAddress() - tx := types.NewTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := cltest.NewLegacyTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) t.Run("returns Fatal error type when error message is fatal", func(t *testing.T) { wsURL := testutils.NewWSServer(t, &cltest.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index 66cc30f74b4..bb748cb52fb 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -413,63 +413,67 @@ func ExtractRPCError(baseErr error) (*JsonError, error) { return &jErr, nil } -func ClassifySendError(err error, lggr logger.SugaredLogger, tx *types.Transaction, fromAddress common.Address, isL2 bool) (commonclient.SendTxReturnCode, error) { +func ClassifySendError(err error, lggr logger.SugaredLogger, tx *types.Transaction, fromAddress common.Address, isL2 bool) commonclient.SendTxReturnCode { sendError := NewSendError(err) if sendError == nil { - return commonclient.Successful, err + return commonclient.Successful } if sendError.Fatal() { lggr.Criticalw("Fatal error sending transaction", "err", sendError, "etx", tx) // Attempt is thrown away in this case; we don't need it since it never got accepted by a node - return commonclient.Fatal, err + return commonclient.Fatal } if sendError.IsNonceTooLowError() || sendError.IsTransactionAlreadyMined() { + lggr.Debugw("Transaction already confirmed for this nonce: %d", tx.Nonce(), "err", sendError, "etx", tx) // Nonce too low indicated that a transaction at this nonce was confirmed already. // Mark it as TransactionAlreadyKnown. - return commonclient.TransactionAlreadyKnown, err + return commonclient.TransactionAlreadyKnown } if sendError.IsReplacementUnderpriced() { lggr.Errorw(fmt.Sprintf("Replacement transaction underpriced for eth_tx %x. "+ - "Eth node returned error: '%s'. "+ "Please note that using your node's private keys outside of the chainlink node is NOT SUPPORTED and can lead to missed transactions.", - tx.Hash(), err), "gasPrice", tx.GasPrice, "gasTipCap", tx.GasTipCap, "gasFeeCap", tx.GasFeeCap) + tx.Hash()), "gasPrice", tx.GasPrice, "gasTipCap", tx.GasTipCap, "gasFeeCap", tx.GasFeeCap, "err", sendError, "etx", tx) // Assume success and hand off to the next cycle. - return commonclient.Successful, err + return commonclient.Successful } if sendError.IsTransactionAlreadyInMempool() { - lggr.Debugw("Transaction already in mempool", "txHash", tx.Hash, "nodeErr", sendError.Error()) - return commonclient.Successful, err + lggr.Debugw("Transaction already in mempool", "etx", tx, "err", sendError) + return commonclient.Successful } if sendError.IsTemporarilyUnderpriced() { - lggr.Infow("Transaction temporarily underpriced", "err", sendError.Error()) - return commonclient.Successful, err + lggr.Infow("Transaction temporarily underpriced", "err", sendError) + return commonclient.Successful } if sendError.IsTerminallyUnderpriced() { - return commonclient.Underpriced, err + lggr.Errorw("Transaction terminally underpriced", "etx", tx, "err", sendError) + return commonclient.Underpriced } if sendError.L2FeeTooLow() || sendError.IsL2FeeTooHigh() || sendError.IsL2Full() { if isL2 { - return commonclient.FeeOutOfValidRange, err + lggr.Errorw("Transaction fee out of range", "err", sendError, "etx", tx) + return commonclient.FeeOutOfValidRange } - return commonclient.Unsupported, errors.Wrap(sendError, "this error type only handled for L2s") + lggr.Errorw("this error type only handled for L2s", "err", sendError, "etx", tx) + return commonclient.Unsupported } if sendError.IsNonceTooHighError() { // This error occurs when the tx nonce is greater than current_nonce + tx_count_in_mempool, // instead of keeping the tx in mempool. This can happen if previous transactions haven't // reached the client yet. The correct thing to do is to mark it as retryable. - lggr.Warnw("Transaction has a nonce gap.", "err", err) - return commonclient.Retryable, err + lggr.Warnw("Transaction has a nonce gap.", "err", sendError, "etx", tx) + return commonclient.Retryable } if sendError.IsInsufficientEth() { lggr.Criticalw(fmt.Sprintf("Tx %x with type 0x%d was rejected due to insufficient eth: %s\n"+ "ACTION REQUIRED: Chainlink wallet with address 0x%x is OUT OF FUNDS", tx.Hash(), tx.Type(), sendError.Error(), fromAddress, - ), "err", sendError) - return commonclient.InsufficientFunds, err + ), "err", sendError, "etx", tx) + return commonclient.InsufficientFunds } if sendError.IsTimeout() { - return commonclient.Retryable, errors.Wrapf(sendError, "timeout while sending transaction %s", tx.Hash().Hex()) + lggr.Errorw("timeout while sending transaction %x", tx.Hash(), "err", sendError, "etx", tx) + return commonclient.Retryable } if sendError.IsTxFeeExceedsCap() { lggr.Criticalw(fmt.Sprintf("Sending transaction failed: %s", label.RPCTxFeeCapConfiguredIncorrectlyWarning), @@ -477,9 +481,10 @@ func ClassifySendError(err error, lggr logger.SugaredLogger, tx *types.Transacti "err", sendError, "id", "RPCTxFeeCapExceeded", ) - return commonclient.ExceedsMaxFee, err + return commonclient.ExceedsMaxFee } - return commonclient.Unknown, err + lggr.Errorw("Unknown error encountered when sending transaction", "err", err, "etx", tx) + return commonclient.Unknown } // ClassifySendOnlyError handles SendOnly nodes error codes. In that case, we don't assume there is another transaction that will be correctly diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 627a2833109..ce3a67162ed 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -24,8 +24,8 @@ import ( commontypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // RPCCLient includes all the necessary generalized RPC methods along with any additional chain-specific methods. diff --git a/core/chains/evm/client/send_only_node_test.go b/core/chains/evm/client/send_only_node_test.go index 760f7f4d3eb..c2fdad06ec1 100644 --- a/core/chains/evm/client/send_only_node_test.go +++ b/core/chains/evm/client/send_only_node_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -95,7 +96,7 @@ func createSignedTx(t *testing.T, chainID *big.Int, nonce uint64, data []byte) * require.NoError(t, err) sender, err := bind.NewKeyedTransactorWithChainID(key, chainID) require.NoError(t, err) - tx := types.NewTransaction( + tx := cltest.NewLegacyTransaction( nonce, sender.From, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), data, diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 16ad74dbca2..292db56f817 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -6,13 +6,14 @@ import ( "slices" "strconv" - "github.com/ethereum/go-ethereum/core/txpool" + "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/pelletier/go-toml/v2" "github.com/shopspring/decimal" "go.uber.org/multierr" "gopkg.in/guregu/null.v4" commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/common/config" @@ -21,9 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/store/models" - configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) type HasEVMConfigs interface { @@ -38,41 +37,41 @@ func (cs EVMConfigs) ValidateConfig() (err error) { func (cs EVMConfigs) validateKeys() (err error) { // Unique chain IDs - chainIDs := configutils.UniqueStrings{} + chainIDs := commonconfig.UniqueStrings{} for i, c := range cs { if chainIDs.IsDupeFmt(c.ChainID) { - err = multierr.Append(err, configutils.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), c.ChainID.String())) + err = multierr.Append(err, commonconfig.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), c.ChainID.String())) } } // Unique node names - names := configutils.UniqueStrings{} + names := commonconfig.UniqueStrings{} for i, c := range cs { for j, n := range c.Nodes { if names.IsDupe(n.Name) { - err = multierr.Append(err, configutils.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) + err = multierr.Append(err, commonconfig.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) } } } // Unique node WSURLs - wsURLs := configutils.UniqueStrings{} + wsURLs := commonconfig.UniqueStrings{} for i, c := range cs { for j, n := range c.Nodes { u := (*url.URL)(n.WSURL) if wsURLs.IsDupeFmt(u) { - err = multierr.Append(err, configutils.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.WSURL", i, j), u.String())) + err = multierr.Append(err, commonconfig.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.WSURL", i, j), u.String())) } } } // Unique node HTTPURLs - httpURLs := configutils.UniqueStrings{} + httpURLs := commonconfig.UniqueStrings{} for i, c := range cs { for j, n := range c.Nodes { u := (*url.URL)(n.HTTPURL) if httpURLs.IsDupeFmt(u) { - err = multierr.Append(err, configutils.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.HTTPURL", i, j), u.String())) + err = multierr.Append(err, commonconfig.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.HTTPURL", i, j), u.String())) } } } @@ -107,7 +106,7 @@ func (cs EVMConfigs) totalChains() int { } return total } -func (cs EVMConfigs) Chains(ids ...relay.ChainID) (r []commontypes.ChainStatus, total int, err error) { +func (cs EVMConfigs) Chains(ids ...string) (r []commontypes.ChainStatus, total int, err error) { total = cs.totalChains() for _, ch := range cs { if ch == nil { @@ -154,7 +153,7 @@ func (cs EVMConfigs) NodeStatus(name string) (commontypes.NodeStatus, error) { for i := range cs { for _, n := range cs[i].Nodes { if n.Name != nil && *n.Name == name { - return nodeStatus(n, relay.ChainID(cs[i].ChainID.String())) + return nodeStatus(n, cs[i].ChainID.String()) } } } @@ -179,7 +178,7 @@ func legacyNode(n *Node, chainID *big.Big) (v2 types.Node) { return } -func nodeStatus(n *Node, chainID relay.ChainID) (commontypes.NodeStatus, error) { +func nodeStatus(n *Node, chainID string) (commontypes.NodeStatus, error) { var s commontypes.NodeStatus s.ChainID = chainID s.Name = *n.Name @@ -191,7 +190,7 @@ func nodeStatus(n *Node, chainID relay.ChainID) (commontypes.NodeStatus, error) return s, nil } -func (cs EVMConfigs) nodes(id relay.ChainID) (ns EVMNodes) { +func (cs EVMConfigs) nodes(id string) (ns EVMNodes) { for _, c := range cs { if c.ChainID.String() == id { return c.Nodes @@ -200,7 +199,7 @@ func (cs EVMConfigs) nodes(id relay.ChainID) (ns EVMNodes) { return nil } -func (cs EVMConfigs) Nodes(chainID relay.ChainID) (ns []types.Node, err error) { +func (cs EVMConfigs) Nodes(chainID string) (ns []types.Node, err error) { evmID, err := ChainIDInt64(chainID) if err != nil { return nil, fmt.Errorf("invalid evm chain id %q : %w", chainID, err) @@ -220,14 +219,14 @@ func (cs EVMConfigs) Nodes(chainID relay.ChainID) (ns []types.Node, err error) { return } -func (cs EVMConfigs) NodeStatuses(chainIDs ...relay.ChainID) (ns []commontypes.NodeStatus, err error) { +func (cs EVMConfigs) NodeStatuses(chainIDs ...string) (ns []commontypes.NodeStatus, err error) { if len(chainIDs) == 0 { for i := range cs { for _, n := range cs[i].Nodes { if n == nil { continue } - n2, err := nodeStatus(n, relay.ChainID(cs[i].ChainID.String())) + n2, err := nodeStatus(n, cs[i].ChainID.String()) if err != nil { return nil, err } @@ -291,29 +290,29 @@ func (c *EVMConfig) SetFrom(f *EVMConfig) { func (c *EVMConfig) ValidateConfig() (err error) { if c.ChainID == nil { - err = multierr.Append(err, configutils.ErrMissing{Name: "ChainID", Msg: "required for all chains"}) + err = multierr.Append(err, commonconfig.ErrMissing{Name: "ChainID", Msg: "required for all chains"}) } else if c.ChainID.String() == "" { - err = multierr.Append(err, configutils.ErrEmpty{Name: "ChainID", Msg: "required for all chains"}) + err = multierr.Append(err, commonconfig.ErrEmpty{Name: "ChainID", Msg: "required for all chains"}) } else if must, ok := ChainTypeForID(c.ChainID); ok { // known chain id if c.ChainType == nil && must != "" { - err = multierr.Append(err, configutils.ErrMissing{Name: "ChainType", + err = multierr.Append(err, commonconfig.ErrMissing{Name: "ChainType", Msg: fmt.Sprintf("only %q can be used with this chain id", must)}) } else if c.ChainType != nil && *c.ChainType != string(must) { if *c.ChainType == "" { - err = multierr.Append(err, configutils.ErrEmpty{Name: "ChainType", + err = multierr.Append(err, commonconfig.ErrEmpty{Name: "ChainType", Msg: fmt.Sprintf("only %q can be used with this chain id", must)}) } else if must == "" { - err = multierr.Append(err, configutils.ErrInvalid{Name: "ChainType", Value: *c.ChainType, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: *c.ChainType, Msg: "must not be set with this chain id"}) } else { - err = multierr.Append(err, configutils.ErrInvalid{Name: "ChainType", Value: *c.ChainType, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: *c.ChainType, Msg: fmt.Sprintf("only %q can be used with this chain id", must)}) } } } if len(c.Nodes) == 0 { - err = multierr.Append(err, configutils.ErrMissing{Name: "Nodes", Msg: "must have at least one node"}) + err = multierr.Append(err, commonconfig.ErrMissing{Name: "Nodes", Msg: "must have at least one node"}) } else { var hasPrimary bool for _, n := range c.Nodes { @@ -324,7 +323,7 @@ func (c *EVMConfig) ValidateConfig() (err error) { break } if !hasPrimary { - err = multierr.Append(err, configutils.ErrMissing{Name: "Nodes", + err = multierr.Append(err, commonconfig.ErrMissing{Name: "Nodes", Msg: "must have at least one primary node with WSURL"}) } } @@ -378,24 +377,24 @@ func (c *Chain) ValidateConfig() (err error) { chainType = config.ChainType(*c.ChainType) } if !chainType.IsValid() { - err = multierr.Append(err, configutils.ErrInvalid{Name: "ChainType", Value: *c.ChainType, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: *c.ChainType, Msg: config.ErrInvalidChainType.Error()}) } if c.GasEstimator.BumpTxDepth != nil && uint32(*c.GasEstimator.BumpTxDepth) > *c.Transactions.MaxInFlight { - err = multierr.Append(err, configutils.ErrInvalid{Name: "GasEstimator.BumpTxDepth", Value: *c.GasEstimator.BumpTxDepth, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "GasEstimator.BumpTxDepth", Value: *c.GasEstimator.BumpTxDepth, Msg: "must be less than or equal to Transactions.MaxInFlight"}) } if *c.HeadTracker.HistoryDepth < *c.FinalityDepth { - err = multierr.Append(err, configutils.ErrInvalid{Name: "HeadTracker.HistoryDepth", Value: *c.HeadTracker.HistoryDepth, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "HeadTracker.HistoryDepth", Value: *c.HeadTracker.HistoryDepth, Msg: "must be equal to or greater than FinalityDepth"}) } if *c.FinalityDepth < 1 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "FinalityDepth", Value: *c.FinalityDepth, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "FinalityDepth", Value: *c.FinalityDepth, Msg: "must be greater than or equal to 1"}) } if *c.MinIncomingConfirmations < 1 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "MinIncomingConfirmations", Value: *c.MinIncomingConfirmations, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "MinIncomingConfirmations", Value: *c.MinIncomingConfirmations, Msg: "must be greater than or equal to 1"}) } return @@ -487,37 +486,37 @@ type GasEstimator struct { } func (e *GasEstimator) ValidateConfig() (err error) { - if uint64(*e.BumpPercent) < txpool.DefaultConfig.PriceBump { - err = multierr.Append(err, configutils.ErrInvalid{Name: "BumpPercent", Value: *e.BumpPercent, - Msg: fmt.Sprintf("may not be less than Geth's default of %d", txpool.DefaultConfig.PriceBump)}) + if uint64(*e.BumpPercent) < legacypool.DefaultConfig.PriceBump { + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "BumpPercent", Value: *e.BumpPercent, + Msg: fmt.Sprintf("may not be less than Geth's default of %d", legacypool.DefaultConfig.PriceBump)}) } if e.TipCapDefault.Cmp(e.TipCapMin) < 0 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "TipCapDefault", Value: e.TipCapDefault, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "TipCapDefault", Value: e.TipCapDefault, Msg: "must be greater than or equal to TipCapMinimum"}) } if e.FeeCapDefault.Cmp(e.TipCapDefault) < 0 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "FeeCapDefault", Value: e.TipCapDefault, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "FeeCapDefault", Value: e.TipCapDefault, Msg: "must be greater than or equal to TipCapDefault"}) } if *e.Mode == "FixedPrice" && *e.BumpThreshold == 0 && *e.EIP1559DynamicFees && e.FeeCapDefault.Cmp(e.PriceMax) != 0 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "FeeCapDefault", Value: e.FeeCapDefault, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "FeeCapDefault", Value: e.FeeCapDefault, Msg: fmt.Sprintf("must be equal to PriceMax (%s) since you are using FixedPrice estimation with gas bumping disabled in "+ "EIP1559 mode - PriceMax will be used as the FeeCap for transactions instead of FeeCapDefault", e.PriceMax)}) } else if e.FeeCapDefault.Cmp(e.PriceMax) > 0 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "FeeCapDefault", Value: e.FeeCapDefault, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "FeeCapDefault", Value: e.FeeCapDefault, Msg: fmt.Sprintf("must be less than or equal to PriceMax (%s)", e.PriceMax)}) } if e.PriceMin.Cmp(e.PriceDefault) > 0 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "PriceMin", Value: e.PriceMin, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "PriceMin", Value: e.PriceMin, Msg: "must be less than or equal to PriceDefault"}) } if e.PriceMax.Cmp(e.PriceDefault) < 0 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "PriceMax", Value: e.PriceMin, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "PriceMax", Value: e.PriceMin, Msg: "must be greater than or equal to PriceDefault"}) } if *e.Mode == "BlockHistory" && *e.BlockHistory.BlockHistorySize <= 0 { - err = multierr.Append(err, configutils.ErrInvalid{Name: "BlockHistory.BlockHistorySize", Value: *e.BlockHistory.BlockHistorySize, + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "BlockHistory.BlockHistorySize", Value: *e.BlockHistory.BlockHistorySize, Msg: "must be greater than or equal to 1 with BlockHistory Mode"}) } @@ -644,7 +643,7 @@ func (ks KeySpecificConfig) ValidateConfig() (err error) { for _, k := range ks { addr := k.Key.String() if _, ok := addrs[addr]; ok { - err = multierr.Append(err, configutils.NewErrDuplicate("Key", addr)) + err = multierr.Append(err, commonconfig.NewErrDuplicate("Key", addr)) } else { addrs[addr] = struct{}{} } @@ -751,9 +750,9 @@ type Node struct { func (n *Node) ValidateConfig() (err error) { if n.Name == nil { - err = multierr.Append(err, configutils.ErrMissing{Name: "Name", Msg: "required for all nodes"}) + err = multierr.Append(err, commonconfig.ErrMissing{Name: "Name", Msg: "required for all nodes"}) } else if *n.Name == "" { - err = multierr.Append(err, configutils.ErrEmpty{Name: "Name", Msg: "required for all nodes"}) + err = multierr.Append(err, commonconfig.ErrEmpty{Name: "Name", Msg: "required for all nodes"}) } var sendOnly bool @@ -762,34 +761,34 @@ func (n *Node) ValidateConfig() (err error) { } if n.WSURL == nil { if !sendOnly { - err = multierr.Append(err, configutils.ErrMissing{Name: "WSURL", Msg: "required for primary nodes"}) + err = multierr.Append(err, commonconfig.ErrMissing{Name: "WSURL", Msg: "required for primary nodes"}) } } else if n.WSURL.IsZero() { if !sendOnly { - err = multierr.Append(err, configutils.ErrEmpty{Name: "WSURL", Msg: "required for primary nodes"}) + err = multierr.Append(err, commonconfig.ErrEmpty{Name: "WSURL", Msg: "required for primary nodes"}) } } else { switch n.WSURL.Scheme { case "ws", "wss": default: - err = multierr.Append(err, configutils.ErrInvalid{Name: "WSURL", Value: n.WSURL.Scheme, Msg: "must be ws or wss"}) + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "WSURL", Value: n.WSURL.Scheme, Msg: "must be ws or wss"}) } } if n.HTTPURL == nil { - err = multierr.Append(err, configutils.ErrMissing{Name: "HTTPURL", Msg: "required for all nodes"}) + err = multierr.Append(err, commonconfig.ErrMissing{Name: "HTTPURL", Msg: "required for all nodes"}) } else if n.HTTPURL.IsZero() { - err = multierr.Append(err, configutils.ErrEmpty{Name: "HTTPURL", Msg: "required for all nodes"}) + err = multierr.Append(err, commonconfig.ErrEmpty{Name: "HTTPURL", Msg: "required for all nodes"}) } else { switch n.HTTPURL.Scheme { case "http", "https": default: - err = multierr.Append(err, configutils.ErrInvalid{Name: "HTTPURL", Value: n.HTTPURL.Scheme, Msg: "must be http or https"}) + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "HTTPURL", Value: n.HTTPURL.Scheme, Msg: "must be http or https"}) } } if n.Order != nil && (*n.Order < 1 || *n.Order > 100) { - err = multierr.Append(err, configutils.ErrInvalid{Name: "Order", Value: *n.Order, Msg: "must be between 1 and 100"}) + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "Order", Value: *n.Order, Msg: "must be between 1 and 100"}) } else if n.Order == nil { z := int32(100) n.Order = &z @@ -816,6 +815,6 @@ func (n *Node) SetFrom(f *Node) { } } -func ChainIDInt64(cid relay.ChainID) (int64, error) { +func ChainIDInt64(cid string) (int64, error) { return strconv.ParseInt(cid, 10, 64) } diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go index 27127993d8a..5e9a10de003 100644 --- a/core/chains/evm/config/toml/defaults.go +++ b/core/chains/evm/config/toml/defaults.go @@ -8,9 +8,9 @@ import ( "slices" "strings" + cconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) var ( @@ -40,7 +40,7 @@ func init() { Chain }{} - if err := configutils.DecodeTOML(bytes.NewReader(b), &config); err != nil { + if err := cconfig.DecodeTOML(bytes.NewReader(b), &config); err != nil { log.Fatalf("failed to decode %q: %v", path, err) } if fe.Name() == "fallback.toml" { diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go index ee020f67002..ca819ba04b3 100644 --- a/core/chains/evm/gas/arbitrum_estimator.go +++ b/core/chains/evm/gas/arbitrum_estimator.go @@ -15,11 +15,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ArbConfig interface { diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index 43ea3e0bb79..eae6fbc2ad3 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -25,11 +25,11 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func NewEvmHash() common.Hash { diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go index ce1a50aa320..8df817f7864 100644 --- a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go +++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go @@ -14,11 +14,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name ethClient --output ./mocks/ --case=underscore --structname ETHClient diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go index 2e0d32bfc94..3b02b7f4362 100644 --- a/core/chains/evm/gas/suggested_price_estimator.go +++ b/core/chains/evm/gas/suggested_price_estimator.go @@ -11,12 +11,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go index 21c864eda69..eb4daa6fde4 100644 --- a/core/chains/evm/headtracker/head_broadcaster_test.go +++ b/core/chains/evm/headtracker/head_broadcaster_test.go @@ -12,13 +12,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" commonhtrk "github.com/smartcontractkit/chainlink/v2/common/headtracker" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -27,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func waitHeadBroadcasterToStart(t *testing.T, hb types.HeadBroadcaster) { @@ -73,7 +72,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { orm := headtracker.NewORM(db, logger, cfg.Database(), *ethClient.ConfiguredChainID()) hs := headtracker.NewHeadSaver(logger, orm, evmCfg.EVM(), evmCfg.EVM().HeadTracker()) - mailMon := mailbox.NewMonitor(t.Name()) + mailMon := mailboxtest.NewMonitor(t) servicetest.Run(t, mailMon) hb := headtracker.NewHeadBroadcaster(logger) servicetest.Run(t, hb) diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 67e76aee52b..38cbe1fbfe4 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -23,12 +23,14 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -37,7 +39,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func firstHead(t *testing.T, db *sqlx.DB) (h evmtypes.Head) { @@ -994,7 +995,7 @@ func createHeadTracker(t *testing.T, ethClient evmclient.Client, config headtrac lggr := logger.Test(t) hb := headtracker.NewHeadBroadcaster(lggr) hs := headtracker.NewHeadSaver(lggr, orm, config, htConfig) - mailMon := mailbox.NewMonitor(t.Name()) + mailMon := mailboxtest.NewMonitor(t) return &headTrackerUniverse{ mu: new(sync.Mutex), headTracker: headtracker.NewHeadTracker(lggr, ethClient, config, htConfig, hb, hs, mailMon), @@ -1009,7 +1010,7 @@ func createHeadTrackerWithNeverSleeper(t *testing.T, ethClient evmclient.Client, lggr := logger.Test(t) hb := headtracker.NewHeadBroadcaster(lggr) hs := headtracker.NewHeadSaver(lggr, orm, evmcfg.EVM(), evmcfg.EVM().HeadTracker()) - mailMon := mailbox.NewMonitor(t.Name()) + mailMon := mailboxtest.NewMonitor(t) ht := headtracker.NewHeadTracker(lggr, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), hb, hs, mailMon) _, err := hs.Load(testutils.Context(t)) require.NoError(t, err) @@ -1027,7 +1028,7 @@ func createHeadTrackerWithChecker(t *testing.T, ethClient evmclient.Client, conf hb := headtracker.NewHeadBroadcaster(lggr) hs := headtracker.NewHeadSaver(lggr, orm, config, htConfig) hb.Subscribe(checker) - mailMon := mailbox.NewMonitor(t.Name()) + mailMon := mailboxtest.NewMonitor(t) ht := headtracker.NewHeadTracker(lggr, ethClient, config, htConfig, hb, hs, mailMon) return &headTrackerUniverse{ mu: new(sync.Mutex), diff --git a/core/chains/evm/headtracker/heads_test.go b/core/chains/evm/headtracker/heads_test.go index 11c1bfd4f7a..9fa5ed4e548 100644 --- a/core/chains/evm/headtracker/heads_test.go +++ b/core/chains/evm/headtracker/heads_test.go @@ -10,9 +10,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestHeads_LatestHead(t *testing.T) { diff --git a/core/chains/evm/log/broadcaster.go b/core/chains/evm/log/broadcaster.go index 393d1c1b266..55a53211fc9 100644 --- a/core/chains/evm/log/broadcaster.go +++ b/core/chains/evm/log/broadcaster.go @@ -14,15 +14,16 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name Broadcaster --output ./mocks/ --case=underscore --structname Broadcaster --filename broadcaster.go @@ -394,7 +395,7 @@ func (b *broadcaster) reinitialize() (backfillStart *int64, abort bool) { ctx, cancel := b.chStop.NewCtx() defer cancel() - utils.RetryWithBackoff(ctx, func() bool { + evmutils.RetryWithBackoff(ctx, func() bool { var err error backfillStart, err = b.orm.Reinitialize(pg.WithParentCtx(ctx)) if err != nil { diff --git a/core/chains/evm/log/eth_subscriber.go b/core/chains/evm/log/eth_subscriber.go index 96a7a8248a6..2f9cbb07cb3 100644 --- a/core/chains/evm/log/eth_subscriber.go +++ b/core/chains/evm/log/eth_subscriber.go @@ -14,8 +14,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/null" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ( diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index cea2e361184..35db8f7f7bf 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -22,7 +22,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -30,6 +30,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" @@ -42,7 +43,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) type broadcasterHelper struct { @@ -90,7 +90,7 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, }) config := evmtest.NewChainScopedConfig(t, globalConfig) lggr := logger.Test(t) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) db := pgtest.NewSqlxDB(t) orm := log.NewORM(db, lggr, config.Database(), cltest.FixtureChainID) @@ -105,7 +105,12 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, LogBroadcaster: &log.NullBroadcaster{}, MailMon: mailMon, }) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(cc) + + m := make(map[string]legacyevm.Chain) + for _, r := range cc.Slice() { + m[r.Chain().ID().String()] = r.Chain() + } + legacyChains := legacyevm.NewLegacyChains(m, cc.AppConfig().EVMConfigs()) pipelineHelper := cltest.NewJobPipelineV2(t, config.WebServer(), config.JobPipeline(), config.Database(), legacyChains, db, kst, nil, nil) return &broadcasterHelper{ diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go index b26e87e668c..02a30c6d93f 100644 --- a/core/chains/evm/log/integration_test.go +++ b/core/chains/evm/log/integration_test.go @@ -18,19 +18,19 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestBroadcaster_AwaitsInitialSubscribersOnStartup(t *testing.T) { @@ -1326,7 +1326,7 @@ func TestBroadcaster_AppendLogChannel(t *testing.T) { ch3 := make(chan types.Log) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - mailMon := servicetest.RunHealthy(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.RunHealthy(t, mailboxtest.NewMonitor(t)) lb := log.NewBroadcaster(nil, ethClient, nil, logger.Test(t), nil, mailMon) chCombined := lb.ExportedAppendLogChannel(ch1, ch2) chCombined = lb.ExportedAppendLogChannel(chCombined, ch3) diff --git a/core/chains/evm/log/orm.go b/core/chains/evm/log/orm.go index 3feb4bb836b..51ed9f2f132 100644 --- a/core/chains/evm/log/orm.go +++ b/core/chains/evm/log/orm.go @@ -12,9 +12,10 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ORM is the interface for log broadcasts. diff --git a/core/chains/evm/log/registrations_test.go b/core/chains/evm/log/registrations_test.go index 0682564fe72..2be01dca2bf 100644 --- a/core/chains/evm/log/registrations_test.go +++ b/core/chains/evm/log/registrations_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var _ Listener = testListener{} diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 7bc131afef4..f82cec62b74 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -22,13 +22,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name LogPoller --output ./mocks/ --case=underscore --structname LogPoller --filename log_poller.go diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index 09e1deb864f..863ab0fddea 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -26,11 +26,11 @@ import ( evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index ed2d617065b..81d1b74e42d 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -27,9 +27,12 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/logger" + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "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" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" @@ -38,7 +41,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func logRuntime(t testing.TB, start time.Time) { @@ -1294,7 +1296,7 @@ func TestLogPoller_DBErrorHandling(t *testing.T) { require.ErrorContains(t, err, "Invalid replay block number") // Force a db error while loading the filters (tx aborted, already rolled back) - require.Error(t, utils.JustError(db.Exec(`invalid query`))) + require.Error(t, commonutils.JustError(db.Exec(`invalid query`))) go func() { err = lp.Replay(ctx, 2) assert.ErrorContains(t, err, "current transaction is aborted") diff --git a/core/chains/evm/logpoller/observability_test.go b/core/chains/evm/logpoller/observability_test.go index 749934dc4b5..eb81273af2c 100644 --- a/core/chains/evm/logpoller/observability_test.go +++ b/core/chains/evm/logpoller/observability_test.go @@ -16,11 +16,11 @@ import ( "github.com/prometheus/client_golang/prometheus/testutil" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestMultipleMetricsArePublished(t *testing.T) { diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index 3c54b3cf654..b8468d28e98 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -18,12 +18,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "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/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type block struct { diff --git a/core/chains/evm/logpoller/query_test.go b/core/chains/evm/logpoller/query_test.go index bc2b20c85c2..70ace713228 100644 --- a/core/chains/evm/logpoller/query_test.go +++ b/core/chains/evm/logpoller/query_test.go @@ -8,8 +8,8 @@ import ( "github.com/lib/pq" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_QueryArgs(t *testing.T) { diff --git a/core/chains/evm/monitor/balance.go b/core/chains/evm/monitor/balance.go index c3b9a49c7af..b0f0fbc9c91 100644 --- a/core/chains/evm/monitor/balance.go +++ b/core/chains/evm/monitor/balance.go @@ -15,13 +15,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name BalanceMonitor --output ../mocks/ --case=underscore @@ -42,7 +42,7 @@ type ( ethKeyStore keystore.Eth ethBalances map[gethCommon.Address]*assets.Eth ethBalancesMtx *sync.RWMutex - sleeperTask utils.SleeperTask + sleeperTask *utils.SleeperTask } NullBalanceMonitor struct{} diff --git a/core/chains/evm/monitor/balance_helpers_test.go b/core/chains/evm/monitor/balance_helpers_test.go index 624aa69f061..ed949882295 100644 --- a/core/chains/evm/monitor/balance_helpers_test.go +++ b/core/chains/evm/monitor/balance_helpers_test.go @@ -1,7 +1,5 @@ package monitor func (bm *balanceMonitor) WorkDone() <-chan struct{} { - return bm.sleeperTask.(interface { - WorkDone() <-chan struct{} - }).WorkDone() + return bm.sleeperTask.WorkDone() } diff --git a/core/chains/evm/txmgr/attempts.go b/core/chains/evm/txmgr/attempts.go index 37626f4550e..ab143a0c963 100644 --- a/core/chains/evm/txmgr/attempts.go +++ b/core/chains/evm/txmgr/attempts.go @@ -3,6 +3,7 @@ package txmgr import ( "bytes" "context" + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -119,9 +120,17 @@ func (c *evmTxAttemptBuilder) NewEmptyTxAttempt(nonce evmtypes.Nonce, feeLimit u return attempt, errors.New("NewEmptyTranscation: legacy fee cannot be nil") } - tx := types.NewTransaction(uint64(nonce), fromAddress, value, uint64(feeLimit), fee.Legacy.ToInt(), payload) + tx := newLegacyTransaction( + uint64(nonce), + fromAddress, + value, + uint32(feeLimit), + fee.Legacy, + payload, + ) - hash, signedTxBytes, err := c.SignTx(fromAddress, tx) + transaction := types.NewTx(&tx) + hash, signedTxBytes, err := c.SignTx(fromAddress, transaction) if err != nil { return attempt, errors.Wrapf(err, "error using account %s to sign empty transaction", fromAddress.String()) } @@ -295,7 +304,7 @@ func newLegacyTransaction(nonce uint64, to common.Address, value *big.Int, gasLi func (c *evmTxAttemptBuilder) SignTx(address common.Address, tx *types.Transaction) (common.Hash, []byte, error) { signedTx, err := c.keystore.SignTx(address, tx, &c.chainID) if err != nil { - return common.Hash{}, nil, errors.Wrap(err, "SignTx failed") + return common.Hash{}, nil, fmt.Errorf("failed to sign tx: %w", err) } rlp := new(bytes.Buffer) if err := signedTx.EncodeRLP(rlp); err != nil { diff --git a/core/chains/evm/txmgr/attempts_test.go b/core/chains/evm/txmgr/attempts_test.go index 131115e6fae..5635972d7ae 100644 --- a/core/chains/evm/txmgr/attempts_test.go +++ b/core/chains/evm/txmgr/attempts_test.go @@ -6,6 +6,7 @@ import ( "testing" gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" @@ -85,6 +86,44 @@ func TestTxm_SignTx(t *testing.T) { require.NotNil(t, rawBytes) require.Equal(t, "0xdd68f554373fdea7ec6713a6e437e7646465d553a6aa0b43233093366cc87ef0", hash.String()) }) + t.Run("can properly encoded and decode raw transaction for LegacyTx", func(t *testing.T) { + chainID := big.NewInt(1) + kst := ksmocks.NewEth(t) + kst.On("SignTx", to, tx, chainID).Return(tx, nil).Once() + cks := txmgr.NewEvmTxAttemptBuilder(*chainID, newFeeConfig(), kst, nil) + + _, rawBytes, err := cks.SignTx(addr, tx) + require.NoError(t, err) + require.NotNil(t, rawBytes) + require.Equal(t, "0xe42a82015681f294b921f7763960b296b9cbad586ff066a18d749724818e83010203808080", hexutil.Encode(rawBytes)) + + var decodedTx *gethtypes.Transaction + decodedTx, err = txmgr.GetGethSignedTx(rawBytes) + require.NoError(t, err) + require.Equal(t, tx.Hash(), decodedTx.Hash()) + }) + t.Run("can properly encoded and decode raw transaction for DynamicFeeTx", func(t *testing.T) { + chainID := big.NewInt(1) + kst := ksmocks.NewEth(t) + typedTx := gethtypes.NewTx(&gethtypes.DynamicFeeTx{ + Nonce: 42, + To: &to, + Value: big.NewInt(142), + Gas: 242, + Data: []byte{1, 2, 3}, + }) + kst.On("SignTx", to, typedTx, chainID).Return(typedTx, nil).Once() + cks := txmgr.NewEvmTxAttemptBuilder(*chainID, newFeeConfig(), kst, nil) + _, rawBytes, err := cks.SignTx(addr, typedTx) + require.NoError(t, err) + require.NotNil(t, rawBytes) + require.Equal(t, "0xa702e5802a808081f294b921f7763960b296b9cbad586ff066a18d749724818e83010203c0808080", hexutil.Encode(rawBytes)) + + var decodedTx *gethtypes.Transaction + decodedTx, err = txmgr.GetGethSignedTx(rawBytes) + require.NoError(t, err) + require.Equal(t, typedTx.Hash(), decodedTx.Hash()) + }) } func TestTxm_NewDynamicFeeTx(t *testing.T) { diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 68a81299bf9..a0711a55a56 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" @@ -37,6 +38,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" @@ -47,7 +49,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // NewEthBroadcaster creates a new txmgr.EthBroadcaster for use in testing. @@ -649,7 +650,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi } // Simulate a "PruneQueue" call - assert.NoError(t, utils.JustError(db.Exec(`DELETE FROM evm.txes WHERE state = 'unstarted'`))) + assert.NoError(t, commonutils.JustError(db.Exec(`DELETE FROM evm.txes WHERE state = 'unstarted'`))) close(chBlock) }() @@ -1009,7 +1010,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, evmcfg, &testCheckerFactory{}, false) ctx := testutils.Context(t) - require.NoError(t, utils.JustError(db.Exec(`SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`))) + require.NoError(t, commonutils.JustError(db.Exec(`SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`))) t.Run("if external wallet sent a transaction from the account and now the nonce is one higher than it should be and we got replacement underpriced then we assume a previous transaction of ours was the one that succeeded, and hand off to EthConfirmer", func(t *testing.T) { mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go index dc7b62647c0..0aa03536276 100644 --- a/core/chains/evm/txmgr/client.go +++ b/core/chains/evm/txmgr/client.go @@ -14,11 +14,12 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + commonclient "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var _ TxmClient = (*evmTxmClient)(nil) @@ -77,10 +78,14 @@ func (c *evmTxmClient) BatchSendTransactions( // convert to tx for logging purposes - exits early if error occurs tx, signedErr := GetGethSignedTx(attempts[i].SignedRawTx) if signedErr != nil { - processingErr[i] = fmt.Errorf("failed to process tx (index %d): %w", i, signedErr) + signedErrMsg := fmt.Sprintf("failed to process tx (index %d)", i) + lggr.Errorw(signedErrMsg, "err", signedErr) + processingErr[i] = fmt.Errorf("%s: %w", signedErrMsg, signedErr) return } - codes[i], txErrs[i] = client.ClassifySendError(reqs[i].Error, lggr, tx, attempts[i].Tx.FromAddress, c.client.IsL2()) + sendErr := reqs[i].Error + codes[i] = client.ClassifySendError(sendErr, lggr, tx, attempts[i].Tx.FromAddress, c.client.IsL2()) + txErrs[i] = sendErr }(index) } wg.Wait() diff --git a/core/chains/evm/txmgr/common.go b/core/chains/evm/txmgr/common.go index 1956476f8dd..d1e851f0c21 100644 --- a/core/chains/evm/txmgr/common.go +++ b/core/chains/evm/txmgr/common.go @@ -35,12 +35,25 @@ func batchSendTransactions( reqs := make([]rpc.BatchElem, len(attempts)) ethTxIDs := make([]int64, len(attempts)) hashes := make([]string, len(attempts)) + now := time.Now() + successfulBroadcast := []int64{} for i, attempt := range attempts { ethTxIDs[i] = attempt.TxID hashes[i] = attempt.Hash.String() + // Decode the signed raw tx back into a Transaction object + signedTx, decodeErr := GetGethSignedTx(attempt.SignedRawTx) + if decodeErr != nil { + return reqs, now, successfulBroadcast, fmt.Errorf("failed to decode signed raw tx into Transaction object: %w", decodeErr) + } + // Get the canonical encoding of the Transaction object needed for the eth_sendRawTransaction request + // The signed raw tx cannot be used directly because it uses a different encoding + txBytes, marshalErr := signedTx.MarshalBinary() + if marshalErr != nil { + return reqs, now, successfulBroadcast, fmt.Errorf("failed to marshal tx into canonical encoding: %w", marshalErr) + } req := rpc.BatchElem{ Method: "eth_sendRawTransaction", - Args: []interface{}{hexutil.Encode(attempt.SignedRawTx)}, + Args: []interface{}{hexutil.Encode(txBytes)}, Result: &common.Hash{}, } reqs[i] = req @@ -48,12 +61,10 @@ func batchSendTransactions( logger.Debugw(fmt.Sprintf("Batch sending %d unconfirmed transactions.", len(attempts)), "n", len(attempts), "ethTxIDs", ethTxIDs, "hashes", hashes) - now := time.Now() if batchSize == 0 { batchSize = len(reqs) } - successfulBroadcast := []int64{} for i := 0; i < len(reqs); i += batchSize { j := i + batchSize if j > len(reqs) { diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 30b2a391a7f..8fa791a141e 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -33,6 +33,7 @@ import ( gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "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" @@ -41,7 +42,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func newTestChainScopedConfig(t *testing.T) evmconfig.ChainScopedConfig { @@ -2984,13 +2984,19 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) + done := make(chan struct{}) + t.Cleanup(func() { <-done }) go func() { + defer close(done) err2 := ec.ResumePendingTaskRuns(testutils.Context(t), &head) - require.NoError(t, err2) + if !assert.NoError(t, err2) { + return + } // Retrieve Tx to check if callback completed flag was set to true updateTx, err3 := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, nonce) - require.NoError(t, err3) - require.Equal(t, true, updateTx.CallbackCompleted) + if assert.NoError(t, err3) { + assert.Equal(t, true, updateTx.CallbackCompleted) + } }() select { @@ -3032,13 +3038,19 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) + done := make(chan struct{}) + t.Cleanup(func() { <-done }) go func() { + defer close(done) err2 := ec.ResumePendingTaskRuns(testutils.Context(t), &head) - require.NoError(t, err2) + if !assert.NoError(t, err2) { + return + } // Retrieve Tx to check if callback completed flag was set to true updateTx, err3 := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, nonce) - require.NoError(t, err3) - require.Equal(t, true, updateTx.CallbackCompleted) + if assert.NoError(t, err3) { + assert.Equal(t, true, updateTx.CallbackCompleted) + } }() select { diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index f9014163675..da206c46c7d 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -71,6 +71,11 @@ type TestEvmTxStore interface { InsertTxAttempt(attempt *TxAttempt) error LoadTxesAttempts(etxs []*Tx, qopts ...pg.QOpt) error GetFatalTransactions(ctx context.Context) (txes []*Tx, err error) + GetAllTxes(ctx context.Context) (txes []*Tx, err error) + GetAllTxAttempts(ctx context.Context) (attempts []TxAttempt, err error) + CountTxesByStateAndSubject(ctx context.Context, state txmgrtypes.TxState, subject uuid.UUID) (count int, err error) + FindTxesByFromAddressAndState(ctx context.Context, fromAddress common.Address, state string) (txes []*Tx, err error) + UpdateTxAttemptBroadcastBeforeBlockNum(ctx context.Context, id int64, blockNum uint) error } type evmTxStore struct { @@ -1556,8 +1561,8 @@ func (o *evmTxStore) UpdateTxFatalError(ctx context.Context, etx *Tx) error { ctx, cancel = o.mergeContexts(ctx) defer cancel() qq := o.q.WithOpts(pg.WithParentCtx(ctx)) - if etx.State != txmgr.TxInProgress { - return pkgerrors.Errorf("can only transition to fatal_error from in_progress, transaction is currently %s", etx.State) + if etx.State != txmgr.TxInProgress && etx.State != txmgr.TxUnstarted { + return pkgerrors.Errorf("can only transition to fatal_error from in_progress or unstarted, transaction is currently %s", etx.State) } if !etx.Error.Valid { return errors.New("expected error field to be set") @@ -2011,6 +2016,66 @@ func (o *evmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Co return txes, pkgerrors.Wrap(err, "FindTxesWithAttemptsAndReceiptsByIdsAndState failed") } +// For testing only, get all txes in the DB +func (o *evmTxStore) GetAllTxes(ctx context.Context) (txes []*Tx, err error) { + var cancel context.CancelFunc + ctx, cancel = o.mergeContexts(ctx) + defer cancel() + qq := o.q.WithOpts(pg.WithParentCtx(ctx)) + var dbEtxs []DbEthTx + sql := "SELECT * FROM evm.txes" + err = qq.Select(&dbEtxs, sql) + txes = make([]*Tx, len(dbEtxs)) + dbEthTxsToEvmEthTxPtrs(dbEtxs, txes) + return txes, err +} + +// For testing only, get all tx attempts in the DB +func (o *evmTxStore) GetAllTxAttempts(ctx context.Context) (attempts []TxAttempt, err error) { + var cancel context.CancelFunc + ctx, cancel = o.mergeContexts(ctx) + defer cancel() + qq := o.q.WithOpts(pg.WithParentCtx(ctx)) + var dbAttempts []DbEthTxAttempt + sql := "SELECT * FROM evm.tx_attempts" + err = qq.Select(&dbAttempts, sql) + attempts = dbEthTxAttemptsToEthTxAttempts(dbAttempts) + return attempts, err +} + +func (o *evmTxStore) CountTxesByStateAndSubject(ctx context.Context, state txmgrtypes.TxState, subject uuid.UUID) (count int, err error) { + var cancel context.CancelFunc + ctx, cancel = o.mergeContexts(ctx) + defer cancel() + qq := o.q.WithOpts(pg.WithParentCtx(ctx)) + sql := "SELECT COUNT(*) FROM evm.txes WHERE state = $1 AND subject = $2" + err = qq.Get(&count, sql, state, subject) + return count, err +} + +func (o *evmTxStore) FindTxesByFromAddressAndState(ctx context.Context, fromAddress common.Address, state string) (txes []*Tx, err error) { + var cancel context.CancelFunc + ctx, cancel = o.mergeContexts(ctx) + defer cancel() + qq := o.q.WithOpts(pg.WithParentCtx(ctx)) + sql := "SELECT * FROM evm.txes WHERE from_address = $1 AND state = $2" + var dbEtxs []DbEthTx + err = qq.Select(&dbEtxs, sql, fromAddress, state) + txes = make([]*Tx, len(dbEtxs)) + dbEthTxsToEvmEthTxPtrs(dbEtxs, txes) + return txes, err +} + +func (o *evmTxStore) UpdateTxAttemptBroadcastBeforeBlockNum(ctx context.Context, id int64, blockNum uint) error { + var cancel context.CancelFunc + ctx, cancel = o.mergeContexts(ctx) + defer cancel() + qq := o.q.WithOpts(pg.WithParentCtx(ctx)) + sql := "UPDATE evm.tx_attempts SET broadcast_before_block_num = $1 WHERE eth_tx_id = $2" + _, err := qq.Exec(sql, blockNum, id) + return err +} + // Returns a context that contains the values of the provided context, // and which is canceled when either the provided contextg or TxStore parent context is canceled. func (o *evmTxStore) mergeContexts(ctx context.Context) (context.Context, context.CancelFunc) { diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 0b4287b6f6c..1a1ee1bcd3a 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "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" @@ -23,7 +24,6 @@ import ( "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" "github.com/google/uuid" "github.com/stretchr/testify/assert" @@ -1811,7 +1811,7 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := newTxStore(t, db, cfg.Database()) + txStore := txmgr.NewTxStore(db, logger.Test(t), cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1822,7 +1822,7 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { for i := 0; i < 5; i++ { mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, txRequestWithStrategy(strategy1)) } - testutils.AssertCountPerSubject(t, db, int64(5), subject1) + AssertCountPerSubject(t, txStore, int64(5), subject1) }) t.Run("prunes if queue has exceeded capacity", func(t *testing.T) { @@ -1831,6 +1831,13 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { for i := 0; i < 5; i++ { mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, txRequestWithStrategy(strategy2)) } - testutils.AssertCountPerSubject(t, db, int64(3), subject2) + AssertCountPerSubject(t, txStore, int64(3), subject2) }) } + +func AssertCountPerSubject(t *testing.T, txStore txmgr.TestEvmTxStore, expected int64, subject uuid.UUID) { + t.Helper() + count, err := txStore.CountTxesByStateAndSubject(testutils.Context(t), "unstarted", subject) + require.NoError(t, err) + require.Equal(t, int(expected), count) +} diff --git a/core/chains/evm/txmgr/reaper_test.go b/core/chains/evm/txmgr/reaper_test.go index 2da8e7a93c8..a539f0ac8cb 100644 --- a/core/chains/evm/txmgr/reaper_test.go +++ b/core/chains/evm/txmgr/reaper_test.go @@ -9,13 +9,14 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" txmgrmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func newReaperWithChainID(t *testing.T, db txmgrtypes.TxHistoryReaper[*big.Int], cfg txmgrtypes.ReaperChainConfig, txConfig txmgrtypes.ReaperTransactionsConfig, cid *big.Int) *txmgr.Reaper { diff --git a/core/chains/evm/txmgr/transmitchecker.go b/core/chains/evm/txmgr/transmitchecker.go index 919fb509fee..5a5cc3dbcd4 100644 --- a/core/chains/evm/txmgr/transmitchecker.go +++ b/core/chains/evm/txmgr/transmitchecker.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" + "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes" "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" @@ -23,7 +24,6 @@ import ( v1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" v2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ( @@ -252,7 +252,7 @@ func (v *VRFV1Checker) Check( "meta", tx.Meta, "reqID", reqID) return nil - } else if utils.IsEmpty(callback.SeedAndBlockNum[:]) { + } else if bytes.IsEmpty(callback.SeedAndBlockNum[:]) { // Request already fulfilled l.Infow("Request already fulfilled", "err", err, @@ -344,7 +344,7 @@ func (v *VRFV2Checker) Check( "blockNumber", h.Number, ) return nil - } else if utils.IsEmpty(callback[:]) { + } else if bytes.IsEmpty(callback[:]) { // If seedAndBlockNumber is zero then the response has been fulfilled and we should skip it. l.Infow("Request already fulfilled.", "ethTxID", tx.ID, diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index df913a41905..6fafff1a5c1 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -22,6 +22,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" @@ -33,6 +35,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -42,7 +45,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func makeTestEvmTxm( @@ -419,7 +421,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { require.Equal(t, payload, etx.EncodedPayload) }) - require.NoError(t, utils.JustError(db.Exec(`DELETE FROM evm.txes WHERE from_address = $1`, thisKey.Address))) + require.NoError(t, commonutils.JustError(db.Exec(`DELETE FROM evm.txes WHERE from_address = $1`, thisKey.Address))) t.Run("if this key has any transactions with insufficient eth errors, inserts it anyway", func(t *testing.T) { payload := cltest.MustRandomBytes(t, 100) @@ -442,7 +444,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { require.Equal(t, payload, etx.EncodedPayload) }) - require.NoError(t, utils.JustError(db.Exec(`DELETE FROM evm.txes WHERE from_address = $1`, thisKey.Address))) + require.NoError(t, commonutils.JustError(db.Exec(`DELETE FROM evm.txes WHERE from_address = $1`, thisKey.Address))) t.Run("if this key has transactions but no insufficient eth errors, transmits as normal", func(t *testing.T) { payload := cltest.MustRandomBytes(t, 100) @@ -652,14 +654,15 @@ func mustInsertUnconfirmedEthTxWithAttemptState(t *testing.T, txStore txmgr.Test etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - tx := types.NewTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := cltest.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) rlp := new(bytes.Buffer) require.NoError(t, tx.EncodeRLP(rlp)) attempt.SignedRawTx = rlp.Bytes() attempt.State = txAttemptState require.NoError(t, txStore.InsertTxAttempt(&attempt)) - etx, err := txStore.FindTxWithAttempts(etx.ID) + var err error + etx, err = txStore.FindTxWithAttempts(etx.ID) require.NoError(t, err) return etx } @@ -686,7 +689,8 @@ func mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t *testing.T, txSt attempt.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(&attempt)) - etx, err := txStore.FindTxWithAttempts(etx.ID) + var err error + etx, err = txStore.FindTxWithAttempts(etx.ID) require.NoError(t, err) return etx } @@ -703,14 +707,15 @@ func mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t *testing.T, txStore require.NoError(t, txStore.InsertTx(&etx)) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - tx := types.NewTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := cltest.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) rlp := new(bytes.Buffer) require.NoError(t, tx.EncodeRLP(rlp)) attempt.SignedRawTx = rlp.Bytes() attempt.State = txmgrtypes.TxAttemptInsufficientFunds require.NoError(t, txStore.InsertTxAttempt(&attempt)) - etx, err := txStore.FindTxWithAttempts(etx.ID) + var err error + etx, err = txStore.FindTxWithAttempts(etx.ID) require.NoError(t, err) return etx } @@ -741,13 +746,14 @@ func mustInsertInProgressEthTxWithAttempt(t *testing.T, txStore txmgr.TestEvmTxS etx.State = txmgrcommon.TxInProgress require.NoError(t, txStore.InsertTx(&etx)) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - tx := types.NewTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := cltest.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) rlp := new(bytes.Buffer) require.NoError(t, tx.EncodeRLP(rlp)) attempt.SignedRawTx = rlp.Bytes() attempt.State = txmgrtypes.TxAttemptInProgress require.NoError(t, txStore.InsertTxAttempt(&attempt)) - etx, err := txStore.FindTxWithAttempts(etx.ID) + var err error + etx, err = txStore.FindTxWithAttempts(etx.ID) require.NoError(t, err) return etx } diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index b7c1e5b56d5..93b300aa532 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -16,13 +16,14 @@ import ( "github.com/pkg/errors" "github.com/ugorji/go/codec" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" commontypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types/internal/blocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/null" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Head represents a BlockNumber, BlockHash. @@ -500,7 +501,7 @@ func (f *FunctionSelector) SetBytes(b []byte) { copy(f[:], b[:FunctionSelectorLe var hexRegexp = regexp.MustCompile("^[0-9a-fA-F]*$") func unmarshalFromString(s string, f *FunctionSelector) error { - if utils.HasHexPrefix(s) { + if hex.HasPrefix(s) { if !hexRegexp.Match([]byte(s)[2:]) { return fmt.Errorf("function selector %s must be 0x-hex encoded", s) } diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go index 3507b6a1318..a32deba697d 100644 --- a/core/chains/evm/types/models_test.go +++ b/core/chains/evm/types/models_test.go @@ -12,20 +12,20 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "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" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "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/null" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestHead_NewHead(t *testing.T) { @@ -95,13 +95,12 @@ func TestEthTxAttempt_GetSignedTx(t *testing.T) { cfg := configtest.NewGeneralConfig(t, nil) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - tx := gethTypes.NewTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := cltest.NewLegacyTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) chainID := big.NewInt(3) signedTx, err := ethKeyStore.SignTx(fromAddress, tx, chainID) require.NoError(t, err) - signedTx.Size() // Needed to write the size for equality checking rlp := new(bytes.Buffer) require.NoError(t, signedTx.EncodeRLP(rlp)) @@ -721,10 +720,10 @@ func TestTransaction_UnmarshalJSON(t *testing.T) { ), }, want: &evmtypes.Transaction{ - GasPrice: assets.NewWei(utils.HexToBig("978a846d2")), + GasPrice: assets.NewWei(mustHexToBig(t, "978a846d2")), GasLimit: mustHextoUint32(t, "0xdbba0"), - MaxFeePerGas: assets.NewWei(utils.HexToBig("d0892241d")), - MaxPriorityFeePerGas: assets.NewWei(utils.HexToBig("3b9aca01")), + MaxFeePerGas: assets.NewWei(mustHexToBig(t, "d0892241d")), + MaxPriorityFeePerGas: assets.NewWei(mustHexToBig(t, "3b9aca01")), Type: 0x2, Hash: common.HexToHash("0x754f49f0a2ca7680806d261dd36ee95ac88a81da59fef0b5d8d691478f075d46"), }, @@ -756,7 +755,7 @@ func TestTransaction_UnmarshalJSON(t *testing.T) { }`, )}, want: &evmtypes.Transaction{ - GasPrice: assets.NewWei(utils.HexToBig("4f7915f5")), + GasPrice: assets.NewWei(mustHexToBig(t, "4f7915f5")), GasLimit: mustHextoUint32(t, "0x2dc6c0"), MaxFeePerGas: nil, MaxPriorityFeePerGas: nil, @@ -779,10 +778,10 @@ func TestTransaction_UnmarshalJSON(t *testing.T) { func TestTransaction_JSONRoundtrip(t *testing.T) { t.Parallel() want := &evmtypes.Transaction{ - GasPrice: assets.NewWei(utils.HexToBig("978a846d2")), + GasPrice: assets.NewWei(mustHexToBig(t, "978a846d2")), GasLimit: mustHextoUint32(t, "0xdbba0"), - MaxFeePerGas: assets.NewWei(utils.HexToBig("d0892241d")), - MaxPriorityFeePerGas: assets.NewWei(utils.HexToBig("3b9aca01")), + MaxFeePerGas: assets.NewWei(mustHexToBig(t, "d0892241d")), + MaxPriorityFeePerGas: assets.NewWei(mustHexToBig(t, "3b9aca01")), Type: evmtypes.TxType(2), Hash: common.HexToHash("0x754f49f0a2ca7680806d261dd36ee95ac88a81da59fef0b5d8d691478f075d46"), } @@ -856,3 +855,9 @@ func mustHextoUint32(t *testing.T, hx string) uint32 { require.NoError(t, err) return uint32(*temp) } + +func mustHexToBig(t *testing.T, hx string) *big.Int { + n, err := hex.ParseBig(hx) + require.NoError(t, err) + return n +} diff --git a/core/chains/evm/types/types.go b/core/chains/evm/types/types.go index aa43806da1f..987fd987d3f 100644 --- a/core/chains/evm/types/types.go +++ b/core/chains/evm/types/types.go @@ -13,15 +13,14 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type Configs interface { - Chains(ids ...relay.ChainID) ([]types.ChainStatus, int, error) + Chains(ids ...string) ([]types.ChainStatus, int, error) Node(name string) (Node, error) - Nodes(chainID relay.ChainID) (nodes []Node, err error) + Nodes(chainID string) (nodes []Node, err error) NodeStatus(name string) (types.NodeStatus, error) } diff --git a/core/chains/evm/utils/big/big.go b/core/chains/evm/utils/big/big.go index f0ff475a7e7..4bb51e27323 100644 --- a/core/chains/evm/utils/big/big.go +++ b/core/chains/evm/utils/big/big.go @@ -9,8 +9,9 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" + "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const base10 = 10 @@ -84,7 +85,7 @@ func (b Big) MarshalJSON() ([]byte, error) { func (b *Big) UnmarshalText(input []byte) error { input = bytes.TrimQuotes(input) str := string(input) - if utils.HasHexPrefix(str) { + if hex.HasPrefix(str) { decoded, err := hexutil.DecodeBig(str) if err != nil { return err diff --git a/core/utils/ethabi.go b/core/chains/evm/utils/ethabi.go similarity index 97% rename from core/utils/ethabi.go rename to core/chains/evm/utils/ethabi.go index 76c2f186e83..61d365933d2 100644 --- a/core/utils/ethabi.go +++ b/core/chains/evm/utils/ethabi.go @@ -12,6 +12,8 @@ import ( "github.com/pkg/errors" "github.com/shopspring/decimal" "github.com/tidwall/gjson" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" ) const ( @@ -115,8 +117,8 @@ func parseDecimalString(input string) (*big.Int, error) { } func parseNumericString(input string) (*big.Int, error) { - if HasHexPrefix(input) { - output, ok := big.NewInt(0).SetString(RemoveHexPrefix(input), 16) + if hex.HasPrefix(input) { + output, ok := big.NewInt(0).SetString(hex.TrimPrefix(input), 16) if !ok { return nil, fmt.Errorf("error parsing hex %s", input) } diff --git a/core/utils/ethabi_test.go b/core/chains/evm/utils/ethabi_test.go similarity index 99% rename from core/utils/ethabi_test.go rename to core/chains/evm/utils/ethabi_test.go index 4cecab48e4c..b99d906eae7 100644 --- a/core/utils/ethabi_test.go +++ b/core/chains/evm/utils/ethabi_test.go @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + + commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" ) func pow2(arg int64) *big.Int { @@ -590,7 +592,7 @@ func EVMTranscodeJSONWithFormat(value gjson.Result, format string) ([]byte, erro case FormatBytes: return EVMTranscodeBytes(value) case FormatPreformatted: - return hex.DecodeString(RemoveHexPrefix(value.Str)) + return hex.DecodeString(commonhex.TrimPrefix(value.Str)) case FormatUint256: data, err := EVMTranscodeUint256(value) if err != nil { diff --git a/core/chains/evm/utils/utils.go b/core/chains/evm/utils/utils.go index abcea77124a..97aaf3b2bd4 100644 --- a/core/chains/evm/utils/utils.go +++ b/core/chains/evm/utils/utils.go @@ -1,13 +1,97 @@ package utils import ( + "context" + "crypto/rand" + "fmt" + "math/big" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/jpillora/backoff" "golang.org/x/crypto/sha3" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" ) +// EVMWordByteLen the length of an EVM Word Byte +const EVMWordByteLen = 32 + +// ZeroAddress is an address of all zeroes, otherwise in Ethereum as +// 0x0000000000000000000000000000000000000000 +var ZeroAddress = common.Address{} + +// EmptyHash is a hash of all zeroes, otherwise in Ethereum as +// 0x0000000000000000000000000000000000000000000000000000000000000000 +var EmptyHash = common.Hash{} + +func RandomAddress() common.Address { + b := make([]byte, 20) + _, _ = rand.Read(b) // Assignment for errcheck. Only used in tests so we can ignore. + return common.BytesToAddress(b) +} + +// IsEmptyAddress checks that the address is empty, synonymous with the zero +// account/address. No logs can come from this address, as there is no contract +// present there. +// +// See https://stackoverflow.com/questions/48219716/what-is-address0-in-solidity +// for the more info on the zero address. +func IsEmptyAddress(addr common.Address) bool { + return addr == ZeroAddress +} + +func RandomBytes32() (r [32]byte) { + b := make([]byte, 32) + _, _ = rand.Read(b[:]) // Assignment for errcheck. Only used in tests so we can ignore. + copy(r[:], b) + return +} + +func Bytes32ToSlice(a [32]byte) (r []byte) { + r = append(r, a[:]...) + return +} + +// Uint256ToBytes is x represented as the bytes of a uint256 +func Uint256ToBytes(x *big.Int) (uint256 []byte, err error) { + if x.Cmp(MaxUint256) > 0 { + return nil, fmt.Errorf("too large to convert to uint256") + } + uint256 = common.LeftPadBytes(x.Bytes(), EVMWordByteLen) + if x.Cmp(big.NewInt(0).SetBytes(uint256)) != 0 { + panic("failed to round-trip uint256 back to source big.Int") + } + return uint256, err +} + +// NewHash return random Keccak256 +func NewHash() common.Hash { + b := make([]byte, 32) + _, err := rand.Read(b) + if err != nil { + panic(err) + } + return common.BytesToHash(b) +} + +// PadByteToHash returns a hash with zeros padded on the left of the given byte. +func PadByteToHash(b byte) common.Hash { + var h [32]byte + h[31] = b + return h +} + +// Uint256ToBytes32 returns the bytes32 encoding of the big int provided +func Uint256ToBytes32(n *big.Int) []byte { + if n.BitLen() > 256 { + panic("vrf.uint256ToBytes32: too big to marshal to uint256") + } + return common.LeftPadBytes(n.Bytes(), 32) +} + // MustHash returns the keccak256 hash, or panics on failure. func MustHash(in string) common.Hash { out, err := Keccak256([]byte(in)) @@ -17,6 +101,30 @@ func MustHash(in string) common.Hash { return common.BytesToHash(out) } +// HexToUint256 returns the uint256 represented by s, or an error if it doesn't +// represent one. +func HexToUint256(s string) (*big.Int, error) { + rawNum, err := hexutil.Decode(s) + if err != nil { + return nil, fmt.Errorf("error while parsing %s as hex: %w", s, err) + } + rv := big.NewInt(0).SetBytes(rawNum) // can't be negative number + if err := CheckUint256(rv); err != nil { + return nil, err + } + return rv, nil +} + +var zero = big.NewInt(0) + +// CheckUint256 returns an error if n is out of bounds for a uint256 +func CheckUint256(n *big.Int) error { + if n.Cmp(zero) < 0 || n.Cmp(MaxUint256) >= 0 { + return fmt.Errorf("number out of range for uint256") + } + return nil +} + // Keccak256 is a simplified interface for the legacy SHA3 implementation that // Ethereum uses. func Keccak256(in []byte) ([]byte, error) { @@ -25,6 +133,42 @@ func Keccak256(in []byte) ([]byte, error) { return hash.Sum(nil), err } +func Keccak256Fixed(in []byte) [32]byte { + hash := sha3.NewLegacyKeccak256() + // Note this Keccak256 cannot error https://github.com/golang/crypto/blob/master/sha3/sha3.go#L126 + // if we start supporting hashing algos which do, we can change this API to include an error. + hash.Write(in) + var h [32]byte + copy(h[:], hash.Sum(nil)) + return h +} + +// EIP55CapitalizedAddress returns true iff possibleAddressString has the correct +// capitalization for an Ethereum address, per EIP 55 +func EIP55CapitalizedAddress(possibleAddressString string) bool { + possibleAddressString = hex.EnsurePrefix(possibleAddressString) + EIP55Capitalized := common.HexToAddress(possibleAddressString).Hex() + return possibleAddressString == EIP55Capitalized +} + +// ParseEthereumAddress returns addressString as a go-ethereum Address, or an +// error if it's invalid, e.g. if EIP 55 capitalization check fails +func ParseEthereumAddress(addressString string) (common.Address, error) { + if !common.IsHexAddress(addressString) { + return common.Address{}, fmt.Errorf( + "not a valid Ethereum address: %s", addressString) + } + address := common.HexToAddress(addressString) + if !EIP55CapitalizedAddress(addressString) { + return common.Address{}, fmt.Errorf( + "%s treated as Ethereum address, but it has an invalid capitalization! "+ + "The correctly-capitalized address would be %s, but "+ + "check carefully before copying and pasting! ", + addressString, address.Hex()) + } + return address, nil +} + // NewRedialBackoff is a standard backoff to use for redialling or reconnecting to // unreachable network endpoints func NewRedialBackoff() backoff.Backoff { @@ -35,3 +179,79 @@ func NewRedialBackoff() backoff.Backoff { } } + +// RetryWithBackoff retries the sleeper and backs off if not Done +func RetryWithBackoff(ctx context.Context, fn func() (retry bool)) { + sleeper := NewBackoffSleeper() + sleeper.Reset() + for { + retry := fn() + if !retry { + return + } + + select { + case <-ctx.Done(): + return + case <-time.After(sleeper.After()): + continue + } + } +} + +// NewBackoffSleeper returns a BackoffSleeper that is configured to +// sleep for 0 seconds initially, then backs off from 1 second minimum +// to 10 seconds maximum. +func NewBackoffSleeper() *BackoffSleeper { + return &BackoffSleeper{ + Backoff: backoff.Backoff{ + Min: 1 * time.Second, + Max: 10 * time.Second, + }, + } +} + +// BackoffSleeper is a sleeper that backs off on subsequent attempts. +type BackoffSleeper struct { + backoff.Backoff + beenRun atomic.Bool +} + +// Sleep waits for the given duration, incrementing the back off. +func (bs *BackoffSleeper) Sleep() { + if bs.beenRun.CompareAndSwap(false, true) { + return + } + time.Sleep(bs.Backoff.Duration()) +} + +// After returns the duration for the next stop, and increments the backoff. +func (bs *BackoffSleeper) After() time.Duration { + if bs.beenRun.CompareAndSwap(false, true) { + return 0 + } + return bs.Backoff.Duration() +} + +// Duration returns the current duration value. +func (bs *BackoffSleeper) Duration() time.Duration { + if !bs.beenRun.Load() { + return 0 + } + return bs.ForAttempt(bs.Attempt()) +} + +// Reset resets the backoff intervals. +func (bs *BackoffSleeper) Reset() { + bs.beenRun.Store(false) + bs.Backoff.Reset() +} + +// RandUint256 generates a random bigNum up to 2 ** 256 - 1 +func RandUint256() *big.Int { + n, err := rand.Int(rand.Reader, MaxUint256) + if err != nil { + panic(err) + } + return n +} diff --git a/core/chains/evm/utils/utils_test.go b/core/chains/evm/utils/utils_test.go new file mode 100644 index 00000000000..9e8b44864ad --- /dev/null +++ b/core/chains/evm/utils/utils_test.go @@ -0,0 +1,231 @@ +package utils_test + +import ( + "context" + "math/big" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/assert" + "go.uber.org/multierr" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +func TestKeccak256(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + input string + want string + }{ + {"basic", "0xf00b", "0x2433bb36d5f9b14e4fea87c2d32d79abfe34e56808b891e471f4400fca2a336c"}, + {"long input", "0xf00b2433bb36d5f9b14e4fea87c2d32d79abfe34e56808b891e471f4400fca2a336c", "0x6b917c56ad7bea7d09132b9e1e29bb5d9aa7d32d067c638dfa886bbbf6874cdf"}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + input, err := hexutil.Decode(test.input) + assert.NoError(t, err) + result, err := utils.Keccak256(input) + assert.NoError(t, err) + + assert.Equal(t, test.want, hexutil.Encode(result)) + }) + } +} + +func TestUtils_IsEmptyAddress(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + addr common.Address + want bool + }{ + {"zero address", common.Address{}, true}, + {"non-zero address", testutils.NewAddress(), false}, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + actual := utils.IsEmptyAddress(test.addr) + assert.Equal(t, test.want, actual) + }) + } +} + +// From https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md#test-cases +var testAddresses = []string{ + "0x52908400098527886E0F7030069857D2E4169EE7", + "0x8617E340B3D01FA5F11F306F4090FD50E238070D", + "0xde709f2102306220921060314715629080e2fb77", + "0x27b1fdb04752bbc536007a920d24acb045561c26", + "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", + "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", + "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", +} + +func TestClient_EIP55CapitalizedAddress(t *testing.T) { + t.Parallel() + + valid := utils.EIP55CapitalizedAddress + for _, address := range testAddresses { + assert.True(t, valid(address)) + assert.False(t, valid(strings.ToLower(address)) && + valid(strings.ToUpper(address))) + } +} + +func TestClient_ParseEthereumAddress(t *testing.T) { + t.Parallel() + + parse := utils.ParseEthereumAddress + for _, address := range testAddresses { + a1, err := parse(address) + assert.NoError(t, err) + no0xPrefix := address[2:] + a2, err := parse(no0xPrefix) + assert.NoError(t, err) + assert.True(t, a1 == a2) + _, lowerErr := parse(strings.ToLower(address)) + _, upperErr := parse(strings.ToUpper(address)) + shouldBeError := multierr.Combine(lowerErr, upperErr) + assert.Error(t, shouldBeError) + assert.True(t, strings.Contains(shouldBeError.Error(), no0xPrefix)) + } + _, notHexErr := parse("0xCeci n'est pas une chaîne hexadécimale") + assert.Error(t, notHexErr) + _, tooLongErr := parse("0x0123456789abcdef0123456789abcdef0123456789abcdef") + assert.Error(t, tooLongErr) +} + +func TestUint256ToBytes(t *testing.T) { + t.Parallel() + + v := big.NewInt(0).Sub(utils.MaxUint256, big.NewInt(1)) + uint256, err := utils.Uint256ToBytes(v) + assert.NoError(t, err) + + b32 := utils.Uint256ToBytes32(v) + assert.Equal(t, uint256, b32) + + large := big.NewInt(0).Add(utils.MaxUint256, big.NewInt(1)) + _, err = utils.Uint256ToBytes(large) + assert.Error(t, err, "too large to convert to uint256") + + negative := big.NewInt(-1) + assert.Panics(t, func() { + _, _ = utils.Uint256ToBytes(negative) + }, "failed to round-trip uint256 back to source big.Int") +} + +func TestCheckUint256(t *testing.T) { + t.Parallel() + + large := big.NewInt(0).Add(utils.MaxUint256, big.NewInt(1)) + err := utils.CheckUint256(large) + assert.Error(t, err, "number out of range for uint256") + + negative := big.NewInt(-123) + err = utils.CheckUint256(negative) + assert.Error(t, err, "number out of range for uint256") + + err = utils.CheckUint256(big.NewInt(123)) + assert.NoError(t, err) +} + +func TestRandUint256(t *testing.T) { + t.Parallel() + + for i := 0; i < 1000; i++ { + uint256 := utils.RandUint256() + assert.NoError(t, utils.CheckUint256(uint256)) + } +} + +func TestHexToUint256(t *testing.T) { + t.Parallel() + + b, err := utils.HexToUint256("0x00") + assert.NoError(t, err) + assert.Zero(t, b.Cmp(big.NewInt(0))) + + b, err = utils.HexToUint256("0xFFFFFFFF") + assert.NoError(t, err) + assert.Zero(t, b.Cmp(big.NewInt(4294967295))) +} + +func TestNewHash(t *testing.T) { + t.Parallel() + + h1 := utils.NewHash() + h2 := utils.NewHash() + assert.NotEqual(t, h1, h2) + assert.NotEqual(t, h1, common.HexToHash("0x0")) + assert.NotEqual(t, h2, common.HexToHash("0x0")) +} + +func TestPadByteToHash(t *testing.T) { + t.Parallel() + + h := utils.PadByteToHash(1) + assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000001", h.String()) +} + +func TestUtils_BackoffSleeper(t *testing.T) { + t.Parallel() + + bs := utils.NewBackoffSleeper() + assert.Equal(t, time.Duration(0), bs.Duration(), "should initially return immediately") + bs.Sleep() + + d := 1 * time.Nanosecond + bs.Min = d + bs.Factor = 2 + assert.Equal(t, d, bs.Duration()) + bs.Sleep() + + d2 := 2 * time.Nanosecond + assert.Equal(t, d2, bs.Duration()) + + bs.Reset() + assert.Equal(t, time.Duration(0), bs.Duration(), "should initially return immediately") +} + +func TestRetryWithBackoff(t *testing.T) { + t.Parallel() + + var counter atomic.Int32 + ctx, cancel := context.WithCancel(testutils.Context(t)) + + utils.RetryWithBackoff(ctx, func() bool { + return false + }) + + retry := func() bool { + return counter.Add(1) < 3 + } + + go utils.RetryWithBackoff(ctx, retry) + + assert.Eventually(t, func() bool { + return counter.Load() == 3 + }, testutils.WaitTimeout(t), testutils.TestInterval) + + cancel() + + utils.RetryWithBackoff(ctx, retry) + assert.Equal(t, int32(4), counter.Load()) +} diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index ef84573cd09..0e0e1e65aca 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -37,7 +37,6 @@ import ( "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/pg" ) //go:generate mockery --quiet --name Chain --output ./mocks/ --case=underscore @@ -164,9 +163,8 @@ func (c ChainRelayExtenderConfig) Validate() error { type ChainOpts struct { AppConfig AppConfig - EventBroadcaster pg.EventBroadcaster - MailMon *mailbox.Monitor - GasEstimator gas.EvmFeeEstimator + MailMon *mailbox.Monitor + GasEstimator gas.EvmFeeEstimator *sqlx.DB @@ -185,9 +183,7 @@ func (o ChainOpts) Validate() error { if o.AppConfig == nil { err = errors.Join(err, errors.New("nil AppConfig")) } - if o.EventBroadcaster == nil { - err = errors.Join(err, errors.New("nil EventBroadcaster")) - } + if o.MailMon == nil { err = errors.Join(err, errors.New("nil MailMon")) } diff --git a/core/chains/legacyevm/chain_test.go b/core/chains/legacyevm/chain_test.go index 93332348aa0..e639db6e7cc 100644 --- a/core/chains/legacyevm/chain_test.go +++ b/core/chains/legacyevm/chain_test.go @@ -14,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) func TestLegacyChains(t *testing.T) { @@ -34,10 +33,9 @@ func TestLegacyChains(t *testing.T) { func TestChainOpts_Validate(t *testing.T) { type fields struct { - AppConfig legacyevm.AppConfig - EventBroadcaster pg.EventBroadcaster - MailMon *mailbox.Monitor - DB *sqlx.DB + AppConfig legacyevm.AppConfig + MailMon *mailbox.Monitor + DB *sqlx.DB } tests := []struct { name string @@ -47,19 +45,17 @@ func TestChainOpts_Validate(t *testing.T) { { name: "valid", fields: fields{ - AppConfig: configtest.NewTestGeneralConfig(t), - EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &mailbox.Monitor{}, - DB: pgtest.NewSqlxDB(t), + AppConfig: configtest.NewTestGeneralConfig(t), + MailMon: &mailbox.Monitor{}, + DB: pgtest.NewSqlxDB(t), }, }, { name: "invalid", fields: fields{ - AppConfig: nil, - EventBroadcaster: nil, - MailMon: nil, - DB: nil, + AppConfig: nil, + MailMon: nil, + DB: nil, }, wantErr: true, }, @@ -67,10 +63,9 @@ func TestChainOpts_Validate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { o := legacyevm.ChainOpts{ - AppConfig: tt.fields.AppConfig, - EventBroadcaster: tt.fields.EventBroadcaster, - MailMon: tt.fields.MailMon, - DB: tt.fields.DB, + AppConfig: tt.fields.AppConfig, + MailMon: tt.fields.MailMon, + DB: 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/cmd/admin_commands.go b/core/cmd/admin_commands.go index 24e78e5e2bb..a0e69867e71 100644 --- a/core/cmd/admin_commands.go +++ b/core/cmd/admin_commands.go @@ -17,6 +17,8 @@ import ( "github.com/urfave/cli" "go.uber.org/multierr" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -155,7 +157,7 @@ func (p *AdminUsersPresenter) RenderTable(rt RendererTable) error { renderList(adminUsersTableHeaders, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } type AdminUsersPresenters []AdminUsersPresenter @@ -173,7 +175,7 @@ func (ps AdminUsersPresenters) RenderTable(rt RendererTable) error { } renderList(adminUsersTableHeaders, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } // ListUsers renders all API users and their roles diff --git a/core/cmd/app.go b/core/cmd/app.go index 17a4da85002..8e61380156c 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -162,6 +162,17 @@ func NewApp(s *Shell) *cli.App { Usage: "Commands for the node's configuration", Subcommands: initRemoteConfigSubCmds(s), }, + { + Name: "health", + Usage: "Prints a health report", + Action: s.Health, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "json, j", + Usage: "json output", + }, + }, + }, { Name: "jobs", Usage: "Commands for managing Jobs", diff --git a/core/cmd/cosmos_keys_commands.go b/core/cmd/cosmos_keys_commands.go index e951ff37a18..11974198fd6 100644 --- a/core/cmd/cosmos_keys_commands.go +++ b/core/cmd/cosmos_keys_commands.go @@ -1,8 +1,8 @@ package cmd import ( + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/cosmos_keys_commands_test.go b/core/cmd/cosmos_keys_commands_test.go index 2cab11379d0..16609daadc6 100644 --- a/core/cmd/cosmos_keys_commands_test.go +++ b/core/cmd/cosmos_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/csa_keys_commands.go b/core/cmd/csa_keys_commands.go index 4874176d335..c2ab3697b18 100644 --- a/core/cmd/csa_keys_commands.go +++ b/core/cmd/csa_keys_commands.go @@ -12,6 +12,7 @@ import ( "github.com/urfave/cli" "go.uber.org/multierr" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -102,7 +103,7 @@ func (ps CSAKeyPresenters) RenderTable(rt RendererTable) error { return err } renderList(headers, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } // ListCSAKeys retrieves a list of all CSA keys diff --git a/core/cmd/csa_keys_commands_test.go b/core/cmd/csa_keys_commands_test.go index 869608fa72b..a181922979a 100644 --- a/core/cmd/csa_keys_commands_test.go +++ b/core/cmd/csa_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/dkgencrypt_keys_commands.go b/core/cmd/dkgencrypt_keys_commands.go index 6a8334454b8..ddcc80a33be 100644 --- a/core/cmd/dkgencrypt_keys_commands.go +++ b/core/cmd/dkgencrypt_keys_commands.go @@ -1,8 +1,8 @@ package cmd import ( + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgsignkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/dkgencrypt_keys_commands_test.go b/core/cmd/dkgencrypt_keys_commands_test.go index a7505ce46dc..b4c6d6f6e91 100644 --- a/core/cmd/dkgencrypt_keys_commands_test.go +++ b/core/cmd/dkgencrypt_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/dkgsign_keys_commands.go b/core/cmd/dkgsign_keys_commands.go index 6c345ce42a2..b0435450e32 100644 --- a/core/cmd/dkgsign_keys_commands.go +++ b/core/cmd/dkgsign_keys_commands.go @@ -1,8 +1,8 @@ package cmd import ( + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgsignkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/dkgsign_keys_commands_test.go b/core/cmd/dkgsign_keys_commands_test.go index 1948800d677..717f988b328 100644 --- a/core/cmd/dkgsign_keys_commands_test.go +++ b/core/cmd/dkgsign_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgsignkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/eth_keys_commands.go b/core/cmd/eth_keys_commands.go index c13bea80f2f..4fb3044ecb6 100644 --- a/core/cmd/eth_keys_commands.go +++ b/core/cmd/eth_keys_commands.go @@ -14,6 +14,7 @@ import ( "github.com/urfave/cli" "go.uber.org/multierr" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -123,15 +124,27 @@ type EthKeyPresenter struct { } func (p *EthKeyPresenter) ToRow() []string { + eth := "Unknown" + if p.EthBalance != nil { + eth = p.EthBalance.String() + } + link := "Unknown" + if p.LinkBalance != nil { + link = p.LinkBalance.String() + } + gas := "None" + if p.MaxGasPriceWei != nil { + gas = p.MaxGasPriceWei.String() + } return []string{ p.Address, p.EVMChainID.String(), - p.EthBalance.String(), - p.LinkBalance.String(), + eth, + link, fmt.Sprintf("%v", p.Disabled), p.CreatedAt.String(), p.UpdatedAt.String(), - p.MaxGasPriceWei.String(), + gas, } } @@ -143,7 +156,7 @@ func (p *EthKeyPresenter) RenderTable(rt RendererTable) error { renderList(ethKeysTableHeaders, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } type EthKeyPresenters []EthKeyPresenter diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go index 7c85b779ecc..de40a5bf873 100644 --- a/core/cmd/eth_keys_commands_test.go +++ b/core/cmd/eth_keys_commands_test.go @@ -13,13 +13,14 @@ import ( "github.com/pkg/errors" commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "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/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" "github.com/stretchr/testify/assert" @@ -160,8 +161,8 @@ func TestShell_ListETHKeys_Disabled(t *testing.T) { assert.Nil(t, balances[0].LinkBalance) assert.Nil(t, balances[0].MaxGasPriceWei) assert.Equal(t, []string{ - k.Address.String(), "0", "", "0", "false", - balances[0].UpdatedAt.String(), balances[0].CreatedAt.String(), "", + k.Address.String(), "0", "Unknown", "Unknown", "false", + balances[0].UpdatedAt.String(), balances[0].CreatedAt.String(), "None", }, balances[0].ToRow()) } diff --git a/core/cmd/evm_transaction_commands.go b/core/cmd/evm_transaction_commands.go index a1a11ab9b37..76628944a6c 100644 --- a/core/cmd/evm_transaction_commands.go +++ b/core/cmd/evm_transaction_commands.go @@ -11,9 +11,9 @@ import ( "go.uber.org/multierr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/stringutils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index 6c079a12495..5c80a7d74a0 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -19,6 +19,8 @@ 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/evmtest" + "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/store/models" ) @@ -156,7 +158,8 @@ func TestShell_SendEther_From_Txm(t *testing.T) { ) client, r := app.NewShellAndRenderer() db := app.GetSqlxDB() - + cfg := pgtest.NewQConfig(false) + txStore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg) set := flag.NewFlagSet("sendether", 0) flagSetApplyFromAction(client.SendEther, set, "") @@ -170,21 +173,26 @@ func TestShell_SendEther_From_Txm(t *testing.T) { assert.NoError(t, client.SendEther(c)) - dbEvmTx := txmgr.DbEthTx{} - require.NoError(t, db.Get(&dbEvmTx, `SELECT * FROM evm.txes`)) - require.Equal(t, "100.500000000000000000", dbEvmTx.Value.String()) - require.Equal(t, fromAddress, dbEvmTx.FromAddress) - require.Equal(t, to, dbEvmTx.ToAddress.String()) + evmTxes, err := txStore.GetAllTxes(testutils.Context(t)) + require.NoError(t, err) + require.Len(t, evmTxes, 1) + evmTx := evmTxes[0] + value := assets.Eth(evmTx.Value) + require.Equal(t, "100.500000000000000000", value.String()) + require.Equal(t, fromAddress, evmTx.FromAddress) + require.Equal(t, to, evmTx.ToAddress.String()) output := *r.Renders[0].(*cmd.EthTxPresenter) - assert.Equal(t, &dbEvmTx.FromAddress, output.From) - assert.Equal(t, &dbEvmTx.ToAddress, output.To) - assert.Equal(t, dbEvmTx.Value.String(), output.Value) - assert.Equal(t, fmt.Sprintf("%d", *dbEvmTx.Nonce), output.Nonce) - - var dbEvmTxAttempt txmgr.DbEthTxAttempt - require.NoError(t, db.Get(&dbEvmTxAttempt, `SELECT * FROM evm.tx_attempts`)) - assert.Equal(t, dbEvmTxAttempt.Hash, output.Hash) + assert.Equal(t, &evmTx.FromAddress, output.From) + assert.Equal(t, &evmTx.ToAddress, output.To) + assert.Equal(t, value.String(), output.Value) + assert.Equal(t, fmt.Sprintf("%d", *evmTx.Sequence), output.Nonce) + + attempts, err := txStore.GetAllTxAttempts(testutils.Context(t)) + require.NoError(t, err) + require.Len(t, attempts, 1) + assert.Equal(t, attempts[0].Hash, output.Hash) + } func TestShell_SendEther_From_Txm_WEI(t *testing.T) { @@ -216,6 +224,8 @@ func TestShell_SendEther_From_Txm_WEI(t *testing.T) { ) client, r := app.NewShellAndRenderer() db := app.GetSqlxDB() + cfg := pgtest.NewQConfig(false) + txStore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg) set := flag.NewFlagSet("sendether", 0) flagSetApplyFromAction(client.SendEther, set, "") @@ -236,19 +246,23 @@ func TestShell_SendEther_From_Txm_WEI(t *testing.T) { assert.NoError(t, client.SendEther(c)) - dbEvmTx := txmgr.DbEthTx{} - require.NoError(t, db.Get(&dbEvmTx, `SELECT * FROM evm.txes`)) - require.Equal(t, "1.000000000000000000", dbEvmTx.Value.String()) - require.Equal(t, fromAddress, dbEvmTx.FromAddress) - require.Equal(t, to, dbEvmTx.ToAddress.String()) + evmTxes, err := txStore.GetAllTxes(testutils.Context(t)) + require.NoError(t, err) + require.Len(t, evmTxes, 1) + evmTx := evmTxes[0] + value := assets.Eth(evmTx.Value) + require.Equal(t, "1.000000000000000000", value.String()) + require.Equal(t, fromAddress, evmTx.FromAddress) + require.Equal(t, to, evmTx.ToAddress.String()) output := *r.Renders[0].(*cmd.EthTxPresenter) - assert.Equal(t, &dbEvmTx.FromAddress, output.From) - assert.Equal(t, &dbEvmTx.ToAddress, output.To) - assert.Equal(t, dbEvmTx.Value.String(), output.Value) - assert.Equal(t, fmt.Sprintf("%d", *dbEvmTx.Nonce), output.Nonce) - - var dbEvmTxAttempt txmgr.DbEthTxAttempt - require.NoError(t, db.Get(&dbEvmTxAttempt, `SELECT * FROM evm.tx_attempts`)) - assert.Equal(t, dbEvmTxAttempt.Hash, output.Hash) + assert.Equal(t, &evmTx.FromAddress, output.From) + assert.Equal(t, &evmTx.ToAddress, output.To) + assert.Equal(t, value.String(), output.Value) + assert.Equal(t, fmt.Sprintf("%d", *evmTx.Sequence), output.Nonce) + + attempts, err := txStore.GetAllTxAttempts(testutils.Context(t)) + require.NoError(t, err) + require.Len(t, attempts, 1) + assert.Equal(t, attempts[0].Hash, output.Hash) } diff --git a/core/cmd/forwarders_commands_test.go b/core/cmd/forwarders_commands_test.go index 5946d31dc3d..b5a96a73aa8 100644 --- a/core/cmd/forwarders_commands_test.go +++ b/core/cmd/forwarders_commands_test.go @@ -10,11 +10,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/ocr2_keys_commands.go b/core/cmd/ocr2_keys_commands.go index f1df2626fbc..ad4b30df4c2 100644 --- a/core/cmd/ocr2_keys_commands.go +++ b/core/cmd/ocr2_keys_commands.go @@ -11,6 +11,7 @@ import ( "github.com/urfave/cli" "go.uber.org/multierr" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -92,7 +93,7 @@ func (p *OCR2KeyBundlePresenter) RenderTable(rt RendererTable) error { } renderList(headers, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } func (p *OCR2KeyBundlePresenter) ToRow() []string { @@ -121,7 +122,7 @@ func (ps OCR2KeyBundlePresenters) RenderTable(rt RendererTable) error { } renderList(headers, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } // ListOCR2KeyBundles lists the available OCR2 Key Bundles diff --git a/core/cmd/ocr2_keys_commands_test.go b/core/cmd/ocr2_keys_commands_test.go index dd2ac2544da..5a861fafa7c 100644 --- a/core/cmd/ocr2_keys_commands_test.go +++ b/core/cmd/ocr2_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/ocr_keys_commands.go b/core/cmd/ocr_keys_commands.go index b9343a4a3f3..2628cd9b270 100644 --- a/core/cmd/ocr_keys_commands.go +++ b/core/cmd/ocr_keys_commands.go @@ -11,6 +11,7 @@ import ( "github.com/urfave/cli" "go.uber.org/multierr" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -91,7 +92,7 @@ func (p *OCRKeyBundlePresenter) RenderTable(rt RendererTable) error { } renderList(headers, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } func (p *OCRKeyBundlePresenter) ToRow() []string { @@ -135,7 +136,7 @@ func (ps OCRKeyBundlePresenters) RenderTable(rt RendererTable) error { } renderList(headers, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } // CreateOCR2KeyBundle creates an OCR key bundle and saves it to the keystore diff --git a/core/cmd/ocr_keys_commands_test.go b/core/cmd/ocr_keys_commands_test.go index aeda9006610..f5da3294903 100644 --- a/core/cmd/ocr_keys_commands_test.go +++ b/core/cmd/ocr_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/p2p_keys_commands.go b/core/cmd/p2p_keys_commands.go index 4ef3c349faf..4ec03da96ca 100644 --- a/core/cmd/p2p_keys_commands.go +++ b/core/cmd/p2p_keys_commands.go @@ -11,6 +11,7 @@ import ( "github.com/urfave/cli" "go.uber.org/multierr" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -90,7 +91,7 @@ func (p *P2PKeyPresenter) RenderTable(rt RendererTable) error { } renderList(headers, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } func (p *P2PKeyPresenter) ToRow() []string { @@ -119,7 +120,7 @@ func (ps P2PKeyPresenters) RenderTable(rt RendererTable) error { } renderList(headers, rows, rt.Writer) - return utils.JustError(rt.Write([]byte("\n"))) + return cutils.JustError(rt.Write([]byte("\n"))) } // ListP2PKeys retrieves a list of all P2P keys diff --git a/core/cmd/p2p_keys_commands_test.go b/core/cmd/p2p_keys_commands_test.go index 683129fafa7..87269e02711 100644 --- a/core/cmd/p2p_keys_commands_test.go +++ b/core/cmd/p2p_keys_commands_test.go @@ -11,12 +11,12 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 3810559cf34..547de67210f 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -43,7 +43,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/periodicbackup" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" @@ -154,10 +153,8 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } keyStore := keystore.New(db, utils.GetScryptParams(cfg), appLggr, cfg.Database()) - mailMon := mailbox.NewMonitor(cfg.AppID().String()) + mailMon := mailbox.NewMonitor(cfg.AppID().String(), appLggr.Named("Mailbox")) - dbListener := cfg.Database().Listener() - eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), dbListener.MinReconnectInterval(), dbListener.MaxReconnectDuration(), appLggr, cfg.AppID()) loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing()) mercuryPool := wsrpc.NewPool(appLggr, cache.Config{ @@ -176,7 +173,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G evmFactoryCfg := chainlink.EVMFactoryConfig{ CSAETHKeystore: keyStore, - ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, EventBroadcaster: eventBroadcaster, MailMon: mailMon, DB: db}, + ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, DB: db}, } // evm always enabled for backward compatibility // TODO BCF-2510 this needs to change in order to clear the path for EVM extraction @@ -226,7 +223,6 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G SqlxDB: db, KeyStore: keyStore, RelayerChainInteroperators: relayChainInterops, - EventBroadcaster: eventBroadcaster, MailMon: mailMon, Logger: appLggr, AuditLogger: auditLogger, diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index e4c29a0e5c2..69b7373ed70 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -33,6 +33,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" @@ -50,6 +51,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" webPresenters "github.com/smartcontractkit/chainlink/v2/core/web/presenters" + "github.com/smartcontractkit/chainlink/v2/internal/testdb" ) var ErrProfileTooLong = errors.New("requested profile duration too large") @@ -257,13 +259,6 @@ func initLocalSubCmds(s *Shell, safe bool) []cli.Command { // ownerPermsMask are the file permission bits reserved for owner. const ownerPermsMask = os.FileMode(0o700) -// PristineDBName is a clean copy of test DB with migrations. -// Used by heavyweight.FullTestDB* functions. -const ( - PristineDBName = "chainlink_test_pristine" - TestDBNamePrefix = "chainlink_test_" -) - // RunNode starts the Chainlink core. func (s *Shell) RunNode(c *cli.Context) error { if err := s.runNode(c); err != nil { @@ -808,13 +803,13 @@ func dropDanglingTestDBs(lggr logger.Logger, db *sqlx.DB) (err error) { defer wg.Done() for dbname := range ch { lggr.Infof("Dropping old, dangling test database: %q", dbname) - gerr := utils.JustError(db.Exec(fmt.Sprintf(`DROP DATABASE IF EXISTS %s`, dbname))) + gerr := cutils.JustError(db.Exec(fmt.Sprintf(`DROP DATABASE IF EXISTS %s`, dbname))) errCh <- gerr } }() } for _, dbname := range dbs { - if strings.HasPrefix(dbname, TestDBNamePrefix) && !strings.HasSuffix(dbname, "_pristine") { + if strings.HasPrefix(dbname, testdb.TestDBNamePrefix) && !strings.HasSuffix(dbname, "_pristine") { ch <- dbname } } @@ -1084,11 +1079,11 @@ func dropAndCreateDB(parsed url.URL) (err error) { } func dropAndCreatePristineDB(db *sqlx.DB, template string) (err error) { - _, err = db.Exec(fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, PristineDBName)) + _, err = db.Exec(fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, testdb.PristineDBName)) if err != nil { return fmt.Errorf("unable to drop postgres database: %v", err) } - _, err = db.Exec(fmt.Sprintf(`CREATE DATABASE "%s" WITH TEMPLATE "%s"`, PristineDBName, template)) + _, err = db.Exec(fmt.Sprintf(`CREATE DATABASE "%s" WITH TEMPLATE "%s"`, testdb.PristineDBName, template)) if err != nil { return fmt.Errorf("unable to create postgres database: %v", err) } diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 56da90d811c..5bdcbb180ef 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -25,7 +25,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" chainlinkmocks "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" evmrelayer "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth" "github.com/smartcontractkit/chainlink/v2/core/store/dialects" @@ -89,10 +88,9 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { Logger: lggr, KeyStore: keyStore.Eth(), ChainOpts: legacyevm.ChainOpts{ - AppConfig: cfg, - EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &mailbox.Monitor{}, - DB: db, + AppConfig: cfg, + MailMon: &mailbox.Monitor{}, + DB: db, }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -194,10 +192,9 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { Logger: lggr, KeyStore: keyStore.Eth(), ChainOpts: legacyevm.ChainOpts{ - AppConfig: cfg, - EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &mailbox.Monitor{}, - DB: db, + AppConfig: cfg, + MailMon: &mailbox.Monitor{}, + DB: db, }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -420,7 +417,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { assert.NoError(t, c.RebroadcastTransactions(ctx)) - cltest.AssertEthTxAttemptCountStays(t, app.GetSqlxDB(), 1) + cltest.AssertEthTxAttemptCountStays(t, txStore, 1) }) } } diff --git a/core/cmd/shell_remote.go b/core/cmd/shell_remote.go index fa72d21ee6f..bc4620d0732 100644 --- a/core/cmd/shell_remote.go +++ b/core/cmd/shell_remote.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" + "github.com/gin-gonic/gin" "github.com/manyminds/api2go/jsonapi" "github.com/mitchellh/go-homedir" "github.com/pelletier/go-toml" @@ -511,6 +512,23 @@ func (s *Shell) checkRemoteBuildCompatibility(lggr logger.Logger, onlyWarn bool, return nil } +func (s *Shell) Health(c *cli.Context) error { + mime := gin.MIMEPlain + if c.Bool("json") { + mime = gin.MIMEJSON + } + resp, err := s.HTTP.Get("/health", map[string]string{"Accept": mime}) + if err != nil { + return s.errorOut(err) + } + b, err := parseResponse(resp) + if err != nil { + return s.errorOut(err) + } + fmt.Println(string(b)) + return nil +} + // ErrIncompatible is returned when the cli and remote versions are not compatible. type ErrIncompatible struct { CLIVersion, CLISha string diff --git a/core/cmd/solana_keys_commands.go b/core/cmd/solana_keys_commands.go index 4dac505af51..636f8a7014a 100644 --- a/core/cmd/solana_keys_commands.go +++ b/core/cmd/solana_keys_commands.go @@ -1,8 +1,8 @@ package cmd import ( + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/solana_keys_commands_test.go b/core/cmd/solana_keys_commands_test.go index e72343be45c..d58c3657019 100644 --- a/core/cmd/solana_keys_commands_test.go +++ b/core/cmd/solana_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/starknet_keys_commands.go b/core/cmd/starknet_keys_commands.go index 3b98a1d11e8..5722e5bd946 100644 --- a/core/cmd/starknet_keys_commands.go +++ b/core/cmd/starknet_keys_commands.go @@ -1,8 +1,8 @@ package cmd import ( + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/starknet_keys_commands_test.go b/core/cmd/starknet_keys_commands_test.go index b1fa4d88f05..0cf0065129d 100644 --- a/core/cmd/starknet_keys_commands_test.go +++ b/core/cmd/starknet_keys_commands_test.go @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/cmd/vrf_keys_commands_test.go b/core/cmd/vrf_keys_commands_test.go index a061067771d..f912e861a64 100644 --- a/core/cmd/vrf_keys_commands_test.go +++ b/core/cmd/vrf_keys_commands_test.go @@ -8,14 +8,14 @@ import ( "github.com/urfave/cli" - "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/smartcontractkit/chainlink/v2/core/web/presenters" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) func TestVRFKeyPresenter_RenderTable(t *testing.T) { diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 953f1feabd8..3cb6bb0aaa7 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -574,3 +574,8 @@ MaxStaleAge = "1h" # Default # LatestReportDeadline controls how long to wait for a response from the # mercury server before retrying. Setting this to zero will wait indefinitely. LatestReportDeadline = "5s" # Default + +# Mercury.TLS controls client settings for when the node talks to traditional web servers or load balancers. +[Mercury.TLS] +# CertFile is the path to a PEM file of trusted root certificate authority certificates +CertFile = "/path/to/client/certs.pem" # Example diff --git a/core/config/docs/defaults.go b/core/config/docs/defaults.go index 8946d75cc65..53e6433a8ef 100644 --- a/core/config/docs/defaults.go +++ b/core/config/docs/defaults.go @@ -4,10 +4,10 @@ import ( "log" "strings" + "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/config/toml" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/cfgtest" "github.com/smartcontractkit/chainlink/v2/core/store/dialects" - "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) var ( diff --git a/core/config/docs/docs_test.go b/core/config/docs/docs_test.go index 74fa6682c96..30688c38879 100644 --- a/core/config/docs/docs_test.go +++ b/core/config/docs/docs_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-solana/pkg/solana" stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" + "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/config/docs" @@ -21,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/cfgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) func TestDoc(t *testing.T) { diff --git a/core/config/env/env.go b/core/config/env/env.go index ea84a50b754..37ae131ddf1 100644 --- a/core/config/env/env.go +++ b/core/config/env/env.go @@ -27,6 +27,8 @@ var ( LOOPPHostName = Var("CL_LOOPP_HOSTNAME") // Work around for Solana LOOPPs configured with zero values. MinOCR2MaxDurationQuery = Var("CL_MIN_OCR2_MAX_DURATION_QUERY") + // PipelineOvertime is an undocumented escape hatch for overriding the default padding in pipeline executions. + PipelineOvertime = Var("CL_PIPELINE_OVERTIME") DatabaseAllowSimplePasswords = Var("CL_DATABASE_ALLOW_SIMPLE_PASSWORDS") DatabaseURL = Secret("CL_DATABASE_URL") diff --git a/core/config/mercury_config.go b/core/config/mercury_config.go index e530af6338f..6a483c593e3 100644 --- a/core/config/mercury_config.go +++ b/core/config/mercury_config.go @@ -12,7 +12,12 @@ type MercuryCache interface { LatestReportDeadline() time.Duration } +type MercuryTLS interface { + CertFile() string +} + type Mercury interface { Credentials(credName string) *ocr2models.MercuryCredentials Cache() MercuryCache + TLS() MercuryTLS } diff --git a/core/config/toml/types.go b/core/config/toml/types.go index e944b44853b..93fcef32611 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -1304,12 +1304,37 @@ func (mc *MercuryCache) setFrom(f *MercuryCache) { } } +type MercuryTLS struct { + CertFile *string +} + +func (m *MercuryTLS) setFrom(f *MercuryTLS) { + if v := f.CertFile; v != nil { + m.CertFile = v + } +} + +func (m *MercuryTLS) ValidateConfig() (err error) { + if *m.CertFile != "" { + if !isValidFilePath(*m.CertFile) { + err = multierr.Append(err, configutils.ErrInvalid{Name: "CertFile", Value: *m.CertFile, Msg: "must be a valid file path"}) + } + } + return +} + type Mercury struct { Cache MercuryCache `toml:",omitempty"` + TLS MercuryTLS `toml:",omitempty"` } func (m *Mercury) setFrom(f *Mercury) { m.Cache.setFrom(&f.Cache) + m.TLS.setFrom(&f.TLS) +} + +func (m *Mercury) ValidateConfig() (err error) { + return m.TLS.ValidateConfig() } type MercuryCredentials struct { diff --git a/core/config/toml/types_test.go b/core/config/toml/types_test.go index e16d3a864da..d29da688e33 100644 --- a/core/config/toml/types_test.go +++ b/core/config/toml/types_test.go @@ -531,5 +531,50 @@ func TestTracing_ValidateMode(t *testing.T) { } } +func TestMercuryTLS_ValidateTLSCertPath(t *testing.T) { + tests := []struct { + name string + tlsCertPath *string + wantErr bool + errMsg string + }{ + { + name: "valid file path", + tlsCertPath: ptr("/etc/ssl/certs/cert.pem"), + wantErr: false, + }, + { + name: "relative file path", + tlsCertPath: ptr("certs/cert.pem"), + wantErr: false, + }, + { + name: "excessively long file path", + tlsCertPath: ptr(strings.Repeat("z", 4097)), + wantErr: true, + errMsg: "CertFile: invalid value (" + strings.Repeat("z", 4097) + "): must be a valid file path", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mercury := &Mercury{ + TLS: MercuryTLS{ + CertFile: tt.tlsCertPath, + }, + } + + err := mercury.ValidateConfig() + + if tt.wantErr { + assert.Error(t, err) + assert.Equal(t, tt.errMsg, err.Error()) + } else { + assert.NoError(t, err) + } + }) + } +} + // ptr is a utility function for converting a value to a pointer to the value. func ptr[T any](t T) *T { return &t } diff --git a/core/gethwrappers/abigen.go b/core/gethwrappers/abigen.go index d96d9f8c306..ed2558f4173 100644 --- a/core/gethwrappers/abigen.go +++ b/core/gethwrappers/abigen.go @@ -17,7 +17,7 @@ import ( gethParams "github.com/ethereum/go-ethereum/params" "golang.org/x/tools/go/ast/astutil" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) const headerComment = `// Code generated - DO NOT EDIT. diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 3cdd44cbc5c..0a77e57c88f 100644 --- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ -GETH_VERSION: 1.12.0 +GETH_VERSION: 1.12.2 functions: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRequest.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRequest.bin 3c972870b0afeb6d73a29ebb182f24956a2cebb127b21c4f867d1ecf19a762db functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServiceAllowList.abi ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServiceAllowList.bin 6beec092fbb3b619dfe69f1ad23392b0bbaf00327b335e4080f921c7122a57e4 functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77 diff --git a/core/gethwrappers/generated/log_emitter/log_emitter.go b/core/gethwrappers/generated/log_emitter/log_emitter.go index 3cb11da5125..24fef257af3 100644 --- a/core/gethwrappers/generated/log_emitter/log_emitter.go +++ b/core/gethwrappers/generated/log_emitter/log_emitter.go @@ -31,8 +31,8 @@ var ( ) var LogEmitterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"Log3\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"v\",\"type\":\"uint256[]\"}],\"name\":\"EmitLog1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"v\",\"type\":\"uint256[]\"}],\"name\":\"EmitLog2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"v\",\"type\":\"string[]\"}],\"name\":\"EmitLog3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061052b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063696933c914610046578063bc253bc01461005b578063d9c21f461461006e575b600080fd5b610059610054366004610269565b610081565b005b610059610069366004610269565b6100f5565b61005961007c3660046102ff565b610159565b60005b81518110156100f1577f46692c0e59ca9cd1ad8f984a9d11715ec83424398b7eed4e05c8ce84662415a88282815181106100c0576100c0610424565b60200260200101516040516100d791815260200190565b60405180910390a1806100e981610453565b915050610084565b5050565b60005b81518110156100f15781818151811061011357610113610424565b60200260200101517f624fb00c2ce79f34cb543884c3af64816dce0f4cec3d32661959e49d488a7a9360405160405180910390a28061015181610453565b9150506100f8565b60005b81518110156100f1577fb94ec34dfe32a8a7170992a093976368d1e63decf8f0bc0b38a8eb89cc9f95cf82828151811061019857610198610424565b60200260200101516040516101ad91906104b2565b60405180910390a1806101bf81610453565b91505061015c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561023d5761023d6101c7565b604052919050565b600067ffffffffffffffff82111561025f5761025f6101c7565b5060051b60200190565b6000602080838503121561027c57600080fd5b823567ffffffffffffffff81111561029357600080fd5b8301601f810185136102a457600080fd5b80356102b76102b282610245565b6101f6565b81815260059190911b820183019083810190878311156102d657600080fd5b928401925b828410156102f4578335825292840192908401906102db565b979650505050505050565b6000602080838503121561031257600080fd5b823567ffffffffffffffff8082111561032a57600080fd5b8185019150601f868184011261033f57600080fd5b823561034d6102b282610245565b81815260059190911b8401850190858101908983111561036c57600080fd5b8686015b83811015610416578035868111156103885760008081fd5b8701603f81018c1361039a5760008081fd5b888101356040888211156103b0576103b06101c7565b6103df8b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a850116016101f6565b8281528e828486010111156103f45760008081fd5b828285018d83013760009281018c019290925250845250918701918701610370565b509998505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036104ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600060208083528351808285015260005b818110156104df578581018301518582016040015282016104c3565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea164736f6c6343000813000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"Log3\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log4\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"v\",\"type\":\"uint256[]\"}],\"name\":\"EmitLog1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"v\",\"type\":\"uint256[]\"}],\"name\":\"EmitLog2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"v\",\"type\":\"string[]\"}],\"name\":\"EmitLog3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"w\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"}],\"name\":\"EmitLog4\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506105c5806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063696933c914610051578063b4b12d9814610066578063bc253bc014610079578063d9c21f461461008c575b600080fd5b61006461005f3660046102d7565b61009f565b005b61006461007436600461036d565b610113565b6100646100873660046102d7565b610163565b61006461009a366004610399565b6101c7565b60005b815181101561010f577f46692c0e59ca9cd1ad8f984a9d11715ec83424398b7eed4e05c8ce84662415a88282815181106100de576100de6104be565b60200260200101516040516100f591815260200190565b60405180910390a180610107816104ed565b9150506100a2565b5050565b60005b8181101561015d57604051839085907fba21d5b63d64546cb4ab29e370a8972bf26f78cb0c395391b4f451699fdfdc5d90600090a380610155816104ed565b915050610116565b50505050565b60005b815181101561010f57818181518110610181576101816104be565b60200260200101517f624fb00c2ce79f34cb543884c3af64816dce0f4cec3d32661959e49d488a7a9360405160405180910390a2806101bf816104ed565b915050610166565b60005b815181101561010f577fb94ec34dfe32a8a7170992a093976368d1e63decf8f0bc0b38a8eb89cc9f95cf828281518110610206576102066104be565b602002602001015160405161021b919061054c565b60405180910390a18061022d816104ed565b9150506101ca565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156102ab576102ab610235565b604052919050565b600067ffffffffffffffff8211156102cd576102cd610235565b5060051b60200190565b600060208083850312156102ea57600080fd5b823567ffffffffffffffff81111561030157600080fd5b8301601f8101851361031257600080fd5b8035610325610320826102b3565b610264565b81815260059190911b8201830190838101908783111561034457600080fd5b928401925b8284101561036257833582529284019290840190610349565b979650505050505050565b60008060006060848603121561038257600080fd5b505081359360208301359350604090920135919050565b600060208083850312156103ac57600080fd5b823567ffffffffffffffff808211156103c457600080fd5b8185019150601f86818401126103d957600080fd5b82356103e7610320826102b3565b81815260059190911b8401850190858101908983111561040657600080fd5b8686015b838110156104b0578035868111156104225760008081fd5b8701603f81018c136104345760008081fd5b8881013560408882111561044a5761044a610235565b6104798b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601610264565b8281528e8284860101111561048e5760008081fd5b828285018d83013760009281018c01929092525084525091870191870161040a565b509998505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610545577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600060208083528351808285015260005b818110156105795785810183015185820160400152820161055d565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea164736f6c6343000813000a", } var LogEmitterABI = LogEmitterMetaData.ABI @@ -207,6 +207,18 @@ func (_LogEmitter *LogEmitterTransactorSession) EmitLog3(v []string) (*types.Tra return _LogEmitter.Contract.EmitLog3(&_LogEmitter.TransactOpts, v) } +func (_LogEmitter *LogEmitterTransactor) EmitLog4(opts *bind.TransactOpts, v *big.Int, w *big.Int, c *big.Int) (*types.Transaction, error) { + return _LogEmitter.contract.Transact(opts, "EmitLog4", v, w, c) +} + +func (_LogEmitter *LogEmitterSession) EmitLog4(v *big.Int, w *big.Int, c *big.Int) (*types.Transaction, error) { + return _LogEmitter.Contract.EmitLog4(&_LogEmitter.TransactOpts, v, w, c) +} + +func (_LogEmitter *LogEmitterTransactorSession) EmitLog4(v *big.Int, w *big.Int, c *big.Int) (*types.Transaction, error) { + return _LogEmitter.Contract.EmitLog4(&_LogEmitter.TransactOpts, v, w, c) +} + type LogEmitterLog1Iterator struct { Event *LogEmitterLog1 @@ -568,6 +580,142 @@ func (_LogEmitter *LogEmitterFilterer) ParseLog3(log types.Log) (*LogEmitterLog3 return event, nil } +type LogEmitterLog4Iterator struct { + Event *LogEmitterLog4 + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LogEmitterLog4Iterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LogEmitterLog4) + 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(LogEmitterLog4) + 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 *LogEmitterLog4Iterator) Error() error { + return it.fail +} + +func (it *LogEmitterLog4Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LogEmitterLog4 struct { + Arg0 *big.Int + Arg1 *big.Int + Raw types.Log +} + +func (_LogEmitter *LogEmitterFilterer) FilterLog4(opts *bind.FilterOpts, arg0 []*big.Int, arg1 []*big.Int) (*LogEmitterLog4Iterator, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + var arg1Rule []interface{} + for _, arg1Item := range arg1 { + arg1Rule = append(arg1Rule, arg1Item) + } + + logs, sub, err := _LogEmitter.contract.FilterLogs(opts, "Log4", arg0Rule, arg1Rule) + if err != nil { + return nil, err + } + return &LogEmitterLog4Iterator{contract: _LogEmitter.contract, event: "Log4", logs: logs, sub: sub}, nil +} + +func (_LogEmitter *LogEmitterFilterer) WatchLog4(opts *bind.WatchOpts, sink chan<- *LogEmitterLog4, arg0 []*big.Int, arg1 []*big.Int) (event.Subscription, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + var arg1Rule []interface{} + for _, arg1Item := range arg1 { + arg1Rule = append(arg1Rule, arg1Item) + } + + logs, sub, err := _LogEmitter.contract.WatchLogs(opts, "Log4", arg0Rule, arg1Rule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LogEmitterLog4) + if err := _LogEmitter.contract.UnpackLog(event, "Log4", 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 (_LogEmitter *LogEmitterFilterer) ParseLog4(log types.Log) (*LogEmitterLog4, error) { + event := new(LogEmitterLog4) + if err := _LogEmitter.contract.UnpackLog(event, "Log4", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + func (_LogEmitter *LogEmitter) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { case _LogEmitter.abi.Events["Log1"].ID: @@ -576,6 +724,8 @@ func (_LogEmitter *LogEmitter) ParseLog(log types.Log) (generated.AbigenLog, err return _LogEmitter.ParseLog2(log) case _LogEmitter.abi.Events["Log3"].ID: return _LogEmitter.ParseLog3(log) + case _LogEmitter.abi.Events["Log4"].ID: + return _LogEmitter.ParseLog4(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) @@ -594,6 +744,10 @@ func (LogEmitterLog3) Topic() common.Hash { return common.HexToHash("0xb94ec34dfe32a8a7170992a093976368d1e63decf8f0bc0b38a8eb89cc9f95cf") } +func (LogEmitterLog4) Topic() common.Hash { + return common.HexToHash("0xba21d5b63d64546cb4ab29e370a8972bf26f78cb0c395391b4f451699fdfdc5d") +} + func (_LogEmitter *LogEmitter) Address() common.Address { return _LogEmitter.address } @@ -605,6 +759,8 @@ type LogEmitterInterface interface { EmitLog3(opts *bind.TransactOpts, v []string) (*types.Transaction, error) + EmitLog4(opts *bind.TransactOpts, v *big.Int, w *big.Int, c *big.Int) (*types.Transaction, error) + FilterLog1(opts *bind.FilterOpts) (*LogEmitterLog1Iterator, error) WatchLog1(opts *bind.WatchOpts, sink chan<- *LogEmitterLog1) (event.Subscription, error) @@ -623,6 +779,12 @@ type LogEmitterInterface interface { ParseLog3(log types.Log) (*LogEmitterLog3, error) + FilterLog4(opts *bind.FilterOpts, arg0 []*big.Int, arg1 []*big.Int) (*LogEmitterLog4Iterator, error) + + WatchLog4(opts *bind.WatchOpts, sink chan<- *LogEmitterLog4, arg0 []*big.Int, arg1 []*big.Int) (event.Subscription, error) + + ParseLog4(log types.Log) (*LogEmitterLog4, error) + ParseLog(log types.Log) (generated.AbigenLog, error) Address() common.Address diff --git a/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go b/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go index bb28c8bd6c4..1409bcb1548 100644 --- a/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go +++ b/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go @@ -30,6 +30,12 @@ var ( _ = abi.ConvertType ) +type CheckData struct { + CheckBurnAmount *big.Int + PerformBurnAmount *big.Int + EventSig [32]byte +} + type Log struct { Index *big.Int Timestamp *big.Int @@ -42,8 +48,8 @@ type Log struct { } var SimpleLogUpkeepCounterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lastBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"counter\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timeToPerform\",\"type\":\"uint256\"}],\"name\":\"PerformingUpkeep\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"source\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"topics\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structLog\",\"name\":\"log\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"checkLog\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousPerformBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeToPerform\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5060006001819055438155600281905560035561088a806100326000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806361bc221a1161005b57806361bc221a146100d4578063806b984f146100dd578063917d895f146100e6578063c6066f0d146100ef57600080fd5b80632cb158641461008257806340691db41461009e5780634585e33b146100bf575b600080fd5b61008b60025481565b6040519081526020015b60405180910390f35b6100b16100ac366004610384565b6100f8565b60405161009592919061055e565b6100d26100cd366004610312565b61012a565b005b61008b60035481565b61008b60005481565b61008b60015481565b61008b60045481565b6000606060018460405160200161010f91906105db565b604051602081830303815290604052915091505b9250929050565b60025461013657436002555b436000556003546101489060016107f0565b6003556000805460015561015e828401846103f1565b90508060200151426101709190610808565b6004819055600254600054600154600354604080519485526020850193909352918301526060820152608081019190915232907f4874b8dd61a40fe23599b4360a9a824d7081742fca9f555bcee3d389c4f4bd659060a00160405180910390a2505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146101f957600080fd5b919050565b600082601f83011261020f57600080fd5b8135602067ffffffffffffffff82111561022b5761022b61084e565b8160051b61023a8282016106d6565b83815282810190868401838801850189101561025557600080fd5b600093505b8584101561027857803583526001939093019291840191840161025a565b50979650505050505050565b600082601f83011261029557600080fd5b813567ffffffffffffffff8111156102af576102af61084e565b6102e060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016106d6565b8181528460208386010111156102f557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806020838503121561032557600080fd5b823567ffffffffffffffff8082111561033d57600080fd5b818501915085601f83011261035157600080fd5b81358181111561036057600080fd5b86602082850101111561037257600080fd5b60209290920196919550909350505050565b6000806040838503121561039757600080fd5b823567ffffffffffffffff808211156103af57600080fd5b9084019061010082870312156103c457600080fd5b909250602084013590808211156103da57600080fd5b506103e785828601610284565b9150509250929050565b60006020828403121561040357600080fd5b813567ffffffffffffffff8082111561041b57600080fd5b90830190610100828603121561043057600080fd5b6104386106ac565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015261047060a084016101d5565b60a082015260c08301358281111561048757600080fd5b610493878286016101fe565b60c08301525060e0830135828111156104ab57600080fd5b6104b787828601610284565b60e08301525095945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156104f857600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b821515815260006020604081840152835180604085015260005b8181101561059457858101830151858201606001528201610578565b818111156105a6576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152608082013560a082015273ffffffffffffffffffffffffffffffffffffffff61062f60a084016101d5565b1660c0820152600061064460c0840184610725565b6101008060e086015261065c610120860183856104c6565b925061066b60e087018761078c565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086850301828701526106a1848483610515565b979650505050505050565b604051610100810167ffffffffffffffff811182821017156106d0576106d061084e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561071d5761071d61084e565b604052919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261075a57600080fd5b830160208101925035905067ffffffffffffffff81111561077a57600080fd5b8060051b360383131561012357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107c157600080fd5b830160208101925035905067ffffffffffffffff8111156107e157600080fd5b80360383131561012357600080fd5b600082198211156108035761080361081f565b500190565b60008282101561081a5761081a61081f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lastBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"counter\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timeToPerform\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isRecovered\",\"type\":\"bool\"}],\"name\":\"PerformingUpkeep\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"checkBurnAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"performBurnAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"eventSig\",\"type\":\"bytes32\"}],\"internalType\":\"structCheckData\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"_checkDataConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"source\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"topics\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structLog\",\"name\":\"log\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"}],\"name\":\"checkLog\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"dummyMap\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRecovered\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousPerformBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeToPerform\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5060006002819055436001556003819055600455610d12806100336000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637145f11b11610076578063917d895f1161005b578063917d895f1461016b578063c6066f0d14610174578063eb950ce71461017d57600080fd5b80637145f11b1461012f578063806b984f1461016257600080fd5b80634585e33b116100a75780634585e33b1461010057806361bc221a14610115578063697794731461011e57600080fd5b80632cb15864146100c357806340691db4146100df575b600080fd5b6100cc60035481565b6040519081526020015b60405180910390f35b6100f26100ed3660046106c6565b61018a565b6040516100d692919061092d565b61011361010e366004610628565b6102c2565b005b6100cc60045481565b61011361012c36600461066a565b50565b61015261013d36600461060f565b60006020819052908152604090205460ff1681565b60405190151581526020016100d6565b6100cc60015481565b6100cc60025481565b6100cc60055481565b6006546101529060ff1681565b6000606081808061019d8688018861083b565b92509250925060005a905060006101b5600143610c61565b40905060008515610224575b855a6101cd9085610c61565b1015610224578080156101ee575060008281526020819052604090205460ff165b604080516020810185905230918101919091529091506060016040516020818303038152906040528051906020012091506101c1565b8361023260c08d018d610a9d565b600281811061024357610243610ca7565b9050602002013514156102875760018b438c8c60405160200161026994939291906109aa565b604051602081830303815290604052975097505050505050506102ba565b60008b438c8c6040516020016102a094939291906109aa565b604051602081830303815290604052975097505050505050505b935093915050565b6003546102ce57436003555b4360019081556004546102e091610c49565b600455600154600255600080806102f984860186610738565b92509250925082602001514261030f9190610c61565b600555600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556060830151821461037157600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b60008060008380602001905181019061038a9190610867565b92509250925060005a905060006103a2600143610c61565b40905060008415610411575b845a6103ba9085610c61565b1015610411578080156103db575060008281526020819052604090205460ff165b604080516020810185905230918101919091529091506060016040516020818303038152906040528051906020012091506103ae565b600354600154600254600454600554600654604080519687526020870195909552938501929092526060840152608083015260ff16151560a082015232907f29eff4cb37911c3ea85db4630638cc5474fdd0631ec42215aef1d7ec96c8e63d9060c00160405180910390a25050505050505050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104ad57600080fd5b919050565b600082601f8301126104c357600080fd5b8135602067ffffffffffffffff8211156104df576104df610cd6565b8160051b6104ee828201610b2f565b83815282810190868401838801850189101561050957600080fd5b600093505b8584101561052c57803583526001939093019291840191840161050e565b50979650505050505050565b60008083601f84011261054a57600080fd5b50813567ffffffffffffffff81111561056257600080fd5b60208301915083602082850101111561057a57600080fd5b9250929050565b600082601f83011261059257600080fd5b813567ffffffffffffffff8111156105ac576105ac610cd6565b6105dd60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610b2f565b8181528460208386010111156105f257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561062157600080fd5b5035919050565b6000806020838503121561063b57600080fd5b823567ffffffffffffffff81111561065257600080fd5b61065e85828601610538565b90969095509350505050565b60006060828403121561067c57600080fd5b6040516060810181811067ffffffffffffffff8211171561069f5761069f610cd6565b80604052508235815260208301356020820152604083013560408201528091505092915050565b6000806000604084860312156106db57600080fd5b833567ffffffffffffffff808211156106f357600080fd5b90850190610100828803121561070857600080fd5b9093506020850135908082111561071e57600080fd5b5061072b86828701610538565b9497909650939450505050565b60008060006060848603121561074d57600080fd5b833567ffffffffffffffff8082111561076557600080fd5b90850190610100828803121561077a57600080fd5b610782610b05565b82358152602083013560208201526040830135604082015260608301356060820152608083013560808201526107ba60a08401610489565b60a082015260c0830135828111156107d157600080fd5b6107dd898286016104b2565b60c08301525060e0830135828111156107f557600080fd5b61080189828601610581565b60e083015250945060208601359350604086013591508082111561082457600080fd5b5061083186828701610581565b9150509250925092565b60008060006060848603121561085057600080fd5b505081359360208301359350604090920135919050565b60008060006060848603121561087c57600080fd5b8351925060208401519150604084015190509250925092565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156108c757600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b821515815260006020604081840152835180604085015260005b8181101561096357858101830151858201606001528201610947565b81811115610975576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b606081528435606082015260208501356080820152604085013560a0820152606085013560c0820152608085013560e082015260006109eb60a08701610489565b61010073ffffffffffffffffffffffffffffffffffffffff821681850152610a1660c0890189610b7e565b925081610120860152610a2e61016086018483610895565b92505050610a3f60e0880188610be5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa085840301610140860152610a758382846108e4565b925050508560208401528281036040840152610a928185876108e4565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610ad257600080fd5b83018035915067ffffffffffffffff821115610aed57600080fd5b6020019150600581901b360382131561057a57600080fd5b604051610100810167ffffffffffffffff81118282101715610b2957610b29610cd6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610b7657610b76610cd6565b604052919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610bb357600080fd5b830160208101925035905067ffffffffffffffff811115610bd357600080fd5b8060051b360383131561057a57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610c1a57600080fd5b830160208101925035905067ffffffffffffffff811115610c3a57600080fd5b80360383131561057a57600080fd5b60008219821115610c5c57610c5c610c78565b500190565b600082821015610c7357610c73610c78565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a", } var SimpleLogUpkeepCounterABI = SimpleLogUpkeepCounterMetaData.ABI @@ -182,9 +188,9 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorRaw) Transact(opt return _SimpleLogUpkeepCounter.Contract.contract.Transact(opts, method, params...) } -func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) CheckLog(opts *bind.CallOpts, log Log, arg1 []byte) (bool, []byte, error) { +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) CheckLog(opts *bind.CallOpts, log Log, checkData []byte) (bool, []byte, error) { var out []interface{} - err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "checkLog", log, arg1) + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "checkLog", log, checkData) if err != nil { return *new(bool), *new([]byte), err @@ -197,12 +203,12 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) CheckLog(opts *bind } -func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) CheckLog(log Log, arg1 []byte) (bool, []byte, error) { - return _SimpleLogUpkeepCounter.Contract.CheckLog(&_SimpleLogUpkeepCounter.CallOpts, log, arg1) +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) CheckLog(log Log, checkData []byte) (bool, []byte, error) { + return _SimpleLogUpkeepCounter.Contract.CheckLog(&_SimpleLogUpkeepCounter.CallOpts, log, checkData) } -func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) CheckLog(log Log, arg1 []byte) (bool, []byte, error) { - return _SimpleLogUpkeepCounter.Contract.CheckLog(&_SimpleLogUpkeepCounter.CallOpts, log, arg1) +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) CheckLog(log Log, checkData []byte) (bool, []byte, error) { + return _SimpleLogUpkeepCounter.Contract.CheckLog(&_SimpleLogUpkeepCounter.CallOpts, log, checkData) } func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) Counter(opts *bind.CallOpts) (*big.Int, error) { @@ -227,6 +233,28 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) Counter() (* return _SimpleLogUpkeepCounter.Contract.Counter(&_SimpleLogUpkeepCounter.CallOpts) } +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) DummyMap(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "dummyMap", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) DummyMap(arg0 [32]byte) (bool, error) { + return _SimpleLogUpkeepCounter.Contract.DummyMap(&_SimpleLogUpkeepCounter.CallOpts, arg0) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) DummyMap(arg0 [32]byte) (bool, error) { + return _SimpleLogUpkeepCounter.Contract.DummyMap(&_SimpleLogUpkeepCounter.CallOpts, arg0) +} + func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) InitialBlock(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "initialBlock") @@ -249,6 +277,28 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) InitialBlock return _SimpleLogUpkeepCounter.Contract.InitialBlock(&_SimpleLogUpkeepCounter.CallOpts) } +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) IsRecovered(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "isRecovered") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) IsRecovered() (bool, error) { + return _SimpleLogUpkeepCounter.Contract.IsRecovered(&_SimpleLogUpkeepCounter.CallOpts) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) IsRecovered() (bool, error) { + return _SimpleLogUpkeepCounter.Contract.IsRecovered(&_SimpleLogUpkeepCounter.CallOpts) +} + func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) LastBlock(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "lastBlock") @@ -315,6 +365,18 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) TimeToPerfor return _SimpleLogUpkeepCounter.Contract.TimeToPerform(&_SimpleLogUpkeepCounter.CallOpts) } +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactor) CheckDataConfig(opts *bind.TransactOpts, arg0 CheckData) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.contract.Transact(opts, "_checkDataConfig", arg0) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) CheckDataConfig(arg0 CheckData) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.CheckDataConfig(&_SimpleLogUpkeepCounter.TransactOpts, arg0) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorSession) CheckDataConfig(arg0 CheckData) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.CheckDataConfig(&_SimpleLogUpkeepCounter.TransactOpts, arg0) +} + func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactor) PerformUpkeep(opts *bind.TransactOpts, performData []byte) (*types.Transaction, error) { return _SimpleLogUpkeepCounter.contract.Transact(opts, "performUpkeep", performData) } @@ -394,6 +456,7 @@ type SimpleLogUpkeepCounterPerformingUpkeep struct { PreviousBlock *big.Int Counter *big.Int TimeToPerform *big.Int + IsRecovered bool Raw types.Log } @@ -470,7 +533,7 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounter) ParseLog(log types.Log) ( } func (SimpleLogUpkeepCounterPerformingUpkeep) Topic() common.Hash { - return common.HexToHash("0x4874b8dd61a40fe23599b4360a9a824d7081742fca9f555bcee3d389c4f4bd65") + return common.HexToHash("0x29eff4cb37911c3ea85db4630638cc5474fdd0631ec42215aef1d7ec96c8e63d") } func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounter) Address() common.Address { @@ -478,18 +541,24 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounter) Address() common.Address } type SimpleLogUpkeepCounterInterface interface { - CheckLog(opts *bind.CallOpts, log Log, arg1 []byte) (bool, []byte, error) + CheckLog(opts *bind.CallOpts, log Log, checkData []byte) (bool, []byte, error) Counter(opts *bind.CallOpts) (*big.Int, error) + DummyMap(opts *bind.CallOpts, arg0 [32]byte) (bool, error) + InitialBlock(opts *bind.CallOpts) (*big.Int, error) + IsRecovered(opts *bind.CallOpts) (bool, error) + LastBlock(opts *bind.CallOpts) (*big.Int, error) PreviousPerformBlock(opts *bind.CallOpts) (*big.Int, error) TimeToPerform(opts *bind.CallOpts) (*big.Int, error) + CheckDataConfig(opts *bind.TransactOpts, arg0 CheckData) (*types.Transaction, error) + PerformUpkeep(opts *bind.TransactOpts, performData []byte) (*types.Transaction, error) FilterPerformingUpkeep(opts *bind.FilterOpts, from []common.Address) (*SimpleLogUpkeepCounterPerformingUpkeepIterator, error) diff --git a/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go b/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go index 62e8b9f0de3..1475c56499f 100644 --- a/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go +++ b/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go @@ -66,8 +66,8 @@ type VRFV2PlusClientRandomWordsRequest struct { } var VRFCoordinatorV25MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"blockhashStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"internalBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalBalance\",\"type\":\"uint256\"}],\"name\":\"BalanceInvariantViolated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"}],\"name\":\"BlockhashNotInStore\",\"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\":[],\"name\":\"FailedToSendNative\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"GasLimitTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"have\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"want\",\"type\":\"uint256\"}],\"name\":\"InsufficientGasForConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"have\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"min\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"max\",\"type\":\"uint16\"}],\"name\":\"InvalidRequestConfirmations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkAlreadySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkNotSet\",\"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\":[],\"name\":\"NoCorrespondingRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"NoSuchProvingKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"NumWordsTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structVRFCoordinatorV2_5.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"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\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeFundsRecovered\",\"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\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"ProvingKeyDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"ProvingKeyRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"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\":\"amountLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountNative\",\"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\":false,\"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\":\"uint256\",\"name\":\"oldNativeBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNativeBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFundedWithNative\",\"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\":\"BLOCKHASH_STORE\",\"outputs\":[{\"internalType\":\"contractBlockhashStoreInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK_NATIVE_FEED\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_REQUEST_CONFIRMATIONS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"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\":\"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[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"deregisterProvingKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"pk\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"gamma\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"uWitness\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"cGammaWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"sHashWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"zInv\",\"type\":\"uint256\"}],\"internalType\":\"structVRF.Proof\",\"name\":\"proof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockNum\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFCoordinatorV2_5.RequestCommitment\",\"name\":\"rc\",\"type\":\"tuple\"}],\"name\":\"fulfillRandomWords\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"fundSubscriptionWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveSubscriptionIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequestConfig\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"reqCount\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicKey\",\"type\":\"uint256[2]\"}],\"name\":\"hashOfKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrationVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"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\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"ownerCancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"pendingRequestExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverNativeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"registerProvingKey\",\"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\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFV2PlusClient.RandomWordsRequest\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"requestRandomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"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_config\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_currentSubNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fallbackWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_feeConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_provingKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"s_provingKeys\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestCommitments\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalNativeBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"internalType\":\"structVRFCoordinatorV2_5.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLINKAndLINKNativeFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200615d3803806200615d833981016040819052620000349162000183565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d7565b50505060601b6001600160601b031916608052620001b5565b6001600160a01b038116331415620001325760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019657600080fd5b81516001600160a01b0381168114620001ae57600080fd5b9392505050565b60805160601c615f82620001db60003960008181610566015261384f0152615f826000f3fe60806040526004361061023c5760003560e01c806379ba50971161012f578063b08c8795116100b1578063b08c87951461076d578063b2a7cac51461078d578063bec4c08c146107ad578063caf70c4a146107cd578063cb631797146107ed578063d98e620e1461080d578063da2f26101461082d578063dac83d2914610863578063dc311dd314610883578063e72f6e30146108b4578063ee9d2d38146108d4578063f2fde38b1461090157600080fd5b806379ba50971461060d5780638402595e1461062257806386fe91c7146106425780638da5cb5b1461066257806395b55cfc146106805780639b1c385e146106935780639d40a6fd146106b3578063a21a23e4146106eb578063a4c0ed3614610700578063aa433aff14610720578063aefb212f1461074057600080fd5b8063330987b3116101c3578063330987b314610444578063405b84fa1461046457806340d6bb821461048457806341af6c87146104af5780635d06b4ab146104df57806364d51a2a146104ff578063659827441461051457806366316d8d14610534578063689c4517146105545780636b6feccc146105885780636f64f03f146105cd57806372e9d565146105ed57600080fd5b80620122911461024157806304104edb1461026e578063043bd6ae14610290578063088070f5146102b457806308821d58146103345780630ae095401461035457806315c48b841461037457806318e3dd271461039c5780631b6b6d23146103db5780632949265714610408578063294daa4914610428575b600080fd5b34801561024d57600080fd5b50610256610921565b60405161026593929190615a61565b60405180910390f35b34801561027a57600080fd5b5061028e61028936600461533c565b61099d565b005b34801561029c57600080fd5b506102a660115481565b604051908152602001610265565b3480156102c057600080fd5b50600d546102fc9061ffff81169063ffffffff62010000820481169160ff600160301b82041691600160381b8204811691600160581b90041685565b6040805161ffff909616865263ffffffff9485166020870152921515928501929092528216606084015216608082015260a001610265565b34801561034057600080fd5b5061028e61034f36600461547c565b610b53565b34801561036057600080fd5b5061028e61036f36600461571e565b610ce7565b34801561038057600080fd5b5061038960c881565b60405161ffff9091168152602001610265565b3480156103a857600080fd5b50600a546103c390600160601b90046001600160601b031681565b6040516001600160601b039091168152602001610265565b3480156103e757600080fd5b506002546103fb906001600160a01b031681565b604051610265919061594f565b34801561041457600080fd5b5061028e610423366004615359565b610dac565b34801561043457600080fd5b5060405160018152602001610265565b34801561045057600080fd5b506103c361045f36600461554e565b610f29565b34801561047057600080fd5b5061028e61047f36600461571e565b61140d565b34801561049057600080fd5b5061049a6101f481565b60405163ffffffff9091168152602001610265565b3480156104bb57600080fd5b506104cf6104ca3660046154d1565b6117f8565b6040519015158152602001610265565b3480156104eb57600080fd5b5061028e6104fa36600461533c565b611999565b34801561050b57600080fd5b50610389606481565b34801561052057600080fd5b5061028e61052f36600461538e565b611a50565b34801561054057600080fd5b5061028e61054f366004615359565b611ab0565b34801561056057600080fd5b506103fb7f000000000000000000000000000000000000000000000000000000000000000081565b34801561059457600080fd5b506012546105b09063ffffffff80821691600160201b90041682565b6040805163ffffffff938416815292909116602083015201610265565b3480156105d957600080fd5b5061028e6105e83660046153c7565b611c78565b3480156105f957600080fd5b506003546103fb906001600160a01b031681565b34801561061957600080fd5b5061028e611d77565b34801561062e57600080fd5b5061028e61063d36600461533c565b611e21565b34801561064e57600080fd5b50600a546103c3906001600160601b031681565b34801561066e57600080fd5b506000546001600160a01b03166103fb565b61028e61068e3660046154d1565b611f33565b34801561069f57600080fd5b506102a66106ae36600461562b565b61207a565b3480156106bf57600080fd5b506007546106d3906001600160401b031681565b6040516001600160401b039091168152602001610265565b3480156106f757600080fd5b506102a661240c565b34801561070c57600080fd5b5061028e61071b3660046153f4565b61265a565b34801561072c57600080fd5b5061028e61073b3660046154d1565b6127fa565b34801561074c57600080fd5b5061076061075b366004615743565b61285a565b60405161026591906159c6565b34801561077957600080fd5b5061028e610788366004615680565b61295b565b34801561079957600080fd5b5061028e6107a83660046154d1565b612ade565b3480156107b957600080fd5b5061028e6107c836600461571e565b612c02565b3480156107d957600080fd5b506102a66107e8366004615498565b612d99565b3480156107f957600080fd5b5061028e61080836600461571e565b612dc9565b34801561081957600080fd5b506102a66108283660046154d1565b6130b6565b34801561083957600080fd5b506103fb6108483660046154d1565b600e602052600090815260409020546001600160a01b031681565b34801561086f57600080fd5b5061028e61087e36600461571e565b6130d7565b34801561088f57600080fd5b506108a361089e3660046154d1565b6131e7565b604051610265959493929190615be3565b3480156108c057600080fd5b5061028e6108cf36600461533c565b6132e2565b3480156108e057600080fd5b506102a66108ef3660046154d1565b60106020526000908152604090205481565b34801561090d57600080fd5b5061028e61091c36600461533c565b6134c3565b600d54600f805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff1693919283919083018282801561098b57602002820191906000526020600020905b815481526020019060010190808311610977575b50505050509050925092509250909192565b6109a56134d4565b60135460005b81811015610b2b57826001600160a01b0316601382815481106109d0576109d0615ede565b6000918252602090912001546001600160a01b03161415610b195760136109f8600184615dab565b81548110610a0857610a08615ede565b600091825260209091200154601380546001600160a01b039092169183908110610a3457610a34615ede565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055826013610a6b600185615dab565b81548110610a7b57610a7b615ede565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506013805480610aba57610aba615ec8565b600082815260209020810160001990810180546001600160a01b03191690550190556040517ff80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af3790610b0c90859061594f565b60405180910390a1505050565b80610b2381615e46565b9150506109ab565b5081604051635428d44960e01b8152600401610b47919061594f565b60405180910390fd5b50565b610b5b6134d4565b604080518082018252600091610b8a919084906002908390839080828437600092019190915250612d99915050565b6000818152600e60205260409020549091506001600160a01b031680610bc657604051631dfd6e1360e21b815260048101839052602401610b47565b6000828152600e6020526040812080546001600160a01b03191690555b600f54811015610c9e5782600f8281548110610c0157610c01615ede565b90600052602060002001541415610c8c57600f805460009190610c2690600190615dab565b81548110610c3657610c36615ede565b9060005260206000200154905080600f8381548110610c5757610c57615ede565b600091825260209091200155600f805480610c7457610c74615ec8565b60019003818190600052602060002001600090559055505b80610c9681615e46565b915050610be3565b50806001600160a01b03167f72be339577868f868798bac2c93e52d6f034fef4689a9848996c14ebb7416c0d83604051610cda91815260200190565b60405180910390a2505050565b60008281526005602052604090205482906001600160a01b031680610d1f57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614610d4a5780604051636c51fda960e11b8152600401610b47919061594f565b600d54600160301b900460ff1615610d755760405163769dd35360e11b815260040160405180910390fd5b610d7e846117f8565b15610d9c57604051631685ecdd60e31b815260040160405180910390fd5b610da68484613529565b50505050565b600d54600160301b900460ff1615610dd75760405163769dd35360e11b815260040160405180910390fd5b336000908152600c60205260409020546001600160601b0380831691161015610e1357604051631e9acf1760e31b815260040160405180910390fd5b336000908152600c602052604081208054839290610e3b9084906001600160601b0316615dc2565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a600c8282829054906101000a90046001600160601b0316610e839190615dc2565b92506101000a8154816001600160601b0302191690836001600160601b031602179055506000826001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114610efd576040519150601f19603f3d011682016040523d82523d6000602084013e610f02565b606091505b5050905080610f245760405163950b247960e01b815260040160405180910390fd5b505050565b600d54600090600160301b900460ff1615610f575760405163769dd35360e11b815260040160405180910390fd5b60005a90506000610f6885856136e4565b90506000846060015163ffffffff166001600160401b03811115610f8e57610f8e615ef4565b604051908082528060200260200182016040528015610fb7578160200160208202803683370190505b50905060005b856060015163ffffffff1681101561103757826040015181604051602001610fef929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c82828151811061101a5761101a615ede565b60209081029190910101528061102f81615e46565b915050610fbd565b5060208083018051600090815260109092526040808320839055905190518291631fe543e360e01b9161106f91908690602401615aeb565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600d805460ff60301b1916600160301b1790559088015160808901519192506000916110d49163ffffffff169084613971565b600d805460ff60301b19169055602089810151600090815260069091526040902054909150600160c01b90046001600160401b0316611114816001615d34565b6020808b0151600090815260069091526040812080546001600160401b0393909316600160c01b026001600160c01b039093169290921790915560a08a0151805161116190600190615dab565b8151811061117157611171615ede565b602091010151600d5460f89190911c60011491506000906111a2908a90600160581b900463ffffffff163a856139bf565b905081156112ab576020808c01516000908152600690915260409020546001600160601b03808316600160601b9092041610156111f257604051631e9acf1760e31b815260040160405180910390fd5b60208b81015160009081526006909152604090208054829190600c90611229908490600160601b90046001600160601b0316615dc2565b82546101009290920a6001600160601b0381810219909316918316021790915589516000908152600e60209081526040808320546001600160a01b03168352600c90915281208054859450909261128291859116615d56565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550611397565b6020808c01516000908152600690915260409020546001600160601b03808316911610156112ec57604051631e9acf1760e31b815260040160405180910390fd5b6020808c0151600090815260069091526040812080548392906113199084906001600160601b0316615dc2565b82546101009290920a6001600160601b0381810219909316918316021790915589516000908152600e60209081526040808320546001600160a01b03168352600b90915281208054859450909261137291859116615d56565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b8a6020015188602001517f49580fdfd9497e1ed5c1b1cec0495087ae8e3f1267470ec2fb015db32e3d6aa78a6040015184886040516113f4939291909283526001600160601b039190911660208301521515604082015260600190565b60405180910390a3985050505050505050505b92915050565b600d54600160301b900460ff16156114385760405163769dd35360e11b815260040160405180910390fd5b61144181613a0e565b6114605780604051635428d44960e01b8152600401610b47919061594f565b60008060008061146f866131e7565b945094505093509350336001600160a01b0316826001600160a01b0316146114d25760405162461bcd60e51b81526020600482015260166024820152752737ba1039bab139b1b934b83a34b7b71037bbb732b960511b6044820152606401610b47565b6114db866117f8565b156115215760405162461bcd60e51b815260206004820152601660248201527550656e64696e6720726571756573742065786973747360501b6044820152606401610b47565b60006040518060c00160405280611536600190565b60ff168152602001888152602001846001600160a01b03168152602001838152602001866001600160601b03168152602001856001600160601b0316815250905060008160405160200161158a91906159ec565b60405160208183030381529060405290506115a488613a78565b505060405163ce3f471960e01b81526001600160a01b0388169063ce3f4719906001600160601b038816906115dd9085906004016159d9565b6000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50506002546001600160a01b031615801593509150611633905057506001600160601b03861615155b156116fd5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061166a908a908a90600401615996565b602060405180830381600087803b15801561168457600080fd5b505af1158015611698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bc91906154b4565b6116fd5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b6044820152606401610b47565b600d805460ff60301b1916600160301b17905560005b83518110156117a65783818151811061172e5761172e615ede565b60200260200101516001600160a01b0316638ea98117896040518263ffffffff1660e01b8152600401611761919061594f565b600060405180830381600087803b15801561177b57600080fd5b505af115801561178f573d6000803e3d6000fd5b50505050808061179e90615e46565b915050611713565b50600d805460ff60301b191690556040517fd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be4187906117e69089908b90615963565b60405180910390a15050505050505050565b6000818152600560209081526040808320815160608101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561188257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611864575b505050505081525050905060005b81604001515181101561198f5760005b600f5481101561197c576000611945600f83815481106118c2576118c2615ede565b9060005260206000200154856040015185815181106118e3576118e3615ede565b602002602001015188600460008960400151898151811061190657611906615ede565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208d82529092529020546001600160401b0316613cc6565b50600081815260106020526040902054909150156119695750600195945050505050565b508061197481615e46565b9150506118a0565b508061198781615e46565b915050611890565b5060009392505050565b6119a16134d4565b6119aa81613a0e565b156119ca578060405163ac8a27ef60e01b8152600401610b47919061594f565b601380546001810182556000919091527f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0900180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af0162590611a4590839061594f565b60405180910390a150565b611a586134d4565b6002546001600160a01b031615611a8257604051631688c53760e11b815260040160405180910390fd5b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055565b600d54600160301b900460ff1615611adb5760405163769dd35360e11b815260040160405180910390fd5b6002546001600160a01b0316611b045760405163c1f0c0a160e01b815260040160405180910390fd5b336000908152600b60205260409020546001600160601b0380831691161015611b4057604051631e9acf1760e31b815260040160405180910390fd5b336000908152600b602052604081208054839290611b689084906001600160601b0316615dc2565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a60008282829054906101000a90046001600160601b0316611bb09190615dc2565b82546001600160601b039182166101009390930a92830291909202199091161790555060025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611c059085908590600401615996565b602060405180830381600087803b158015611c1f57600080fd5b505af1158015611c33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5791906154b4565b611c7457604051631e9acf1760e31b815260040160405180910390fd5b5050565b611c806134d4565b604080518082018252600091611caf919084906002908390839080828437600092019190915250612d99915050565b6000818152600e60205260409020549091506001600160a01b031615611ceb57604051634a0b8fa760e01b815260048101829052602401610b47565b6000818152600e6020908152604080832080546001600160a01b0319166001600160a01b038816908117909155600f805460018101825594527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802909301849055518381527fe729ae16526293f74ade739043022254f1489f616295a25bf72dfb4511ed73b89101610cda565b6001546001600160a01b03163314611dca5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610b47565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611e296134d4565b600a544790600160601b90046001600160601b031681811115611e69576040516354ced18160e11b81526004810182905260248101839052604401610b47565b81811015610f24576000611e7d8284615dab565b90506000846001600160a01b03168260405160006040518083038185875af1925050503d8060008114611ecc576040519150601f19603f3d011682016040523d82523d6000602084013e611ed1565b606091505b5050905080611ef35760405163950b247960e01b815260040160405180910390fd5b7f4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c8583604051611f24929190615963565b60405180910390a15050505050565b600d54600160301b900460ff1615611f5e5760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b0316611f9357604051630fb532db60e11b815260040160405180910390fd5b60008181526006602052604090208054600160601b90046001600160601b0316903490600c611fc28385615d56565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555034600a600c8282829054906101000a90046001600160601b031661200a9190615d56565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e90282348461205d9190615d1c565b604080519283526020830191909152015b60405180910390a25050565b600d54600090600160301b900460ff16156120a85760405163769dd35360e11b815260040160405180910390fd5b6020808301356000908152600590915260409020546001600160a01b03166120e357604051630fb532db60e11b815260040160405180910390fd5b3360009081526004602090815260408083208583013584529091529020546001600160401b031680612130578260200135336040516379bfd40160e01b8152600401610b47929190615ac0565b600d5461ffff166121476060850160408601615665565b61ffff16108061216a575060c86121646060850160408601615665565b61ffff16115b156121b05761217f6060840160408501615665565b600d5460405163539c34bb60e11b815261ffff92831660048201529116602482015260c86044820152606401610b47565b600d5462010000900463ffffffff166121cf6080850160608601615765565b63ffffffff16111561221f576121eb6080840160608501615765565b600d54604051637aebf00f60e11b815263ffffffff9283166004820152620100009091049091166024820152604401610b47565b6101f461223260a0850160808601615765565b63ffffffff1611156122785761224e60a0840160808501615765565b6040516311ce1afb60e21b815263ffffffff90911660048201526101f46024820152604401610b47565b6000612285826001615d34565b905060008061229b863533602089013586613cc6565b909250905060006122b76122b260a0890189615c38565b613d3f565b905060006122c482613dbc565b9050836122cf613e2d565b60208a01356122e460808c0160608d01615765565b6122f460a08d0160808e01615765565b338660405160200161230c9796959493929190615b43565b604051602081830303815290604052805190602001206010600086815260200190815260200160002081905550336001600160a01b0316886020013589600001357feb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e87878d60400160208101906123839190615665565b8e60600160208101906123969190615765565b8f60800160208101906123a99190615765565b896040516123bc96959493929190615b04565b60405180910390a45050336000908152600460209081526040808320898301358452909152902080546001600160401b0319166001600160401b039490941693909317909255925050505b919050565b600d54600090600160301b900460ff161561243a5760405163769dd35360e11b815260040160405180910390fd5b600033612448600143615dab565b600754604051606093841b6001600160601b03199081166020830152924060348201523090931b909116605483015260c01b6001600160c01b031916606882015260700160408051601f198184030181529190528051602090910120600780549192506001600160401b039091169060006124c283615e61565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550506000806001600160401b0381111561250157612501615ef4565b60405190808252806020026020018201604052801561252a578160200160208202803683370190505b506040805160608082018352600080835260208084018281528486018381528984526006835286842095518654925191516001600160601b039182166001600160c01b031990941693909317600160601b9190921602176001600160c01b0316600160c01b6001600160401b039092169190910217909355835191820184523382528183018181528285018681528883526005855294909120825181546001600160a01b03199081166001600160a01b03928316178355925160018301805490941691161790915592518051949550909361260b9260028501920190615052565b5061261b91506008905083613ebd565b50817f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d3360405161264c919061594f565b60405180910390a250905090565b600d54600160301b900460ff16156126855760405163769dd35360e11b815260040160405180910390fd5b6002546001600160a01b031633146126b0576040516344b0e3c360e01b815260040160405180910390fd5b602081146126d157604051638129bbcd60e01b815260040160405180910390fd5b60006126df828401846154d1565b6000818152600560205260409020549091506001600160a01b031661271757604051630fb532db60e11b815260040160405180910390fd5b600081815260066020526040812080546001600160601b03169186919061273e8385615d56565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600a60008282829054906101000a90046001600160601b03166127869190615d56565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a8287846127d99190615d1c565b604080519283526020830191909152015b60405180910390a2505050505050565b6128026134d4565b6000818152600560205260409020546001600160a01b031661283757604051630fb532db60e11b815260040160405180910390fd5b600081815260056020526040902054610b509082906001600160a01b0316613529565b606060006128686008613ec9565b905080841061288a57604051631390f2a160e01b815260040160405180910390fd5b60006128968486615d1c565b9050818111806128a4575083155b6128ae57806128b0565b815b905060006128be8683615dab565b6001600160401b038111156128d5576128d5615ef4565b6040519080825280602002602001820160405280156128fe578160200160208202803683370190505b50905060005b81518110156129515761292261291a8883615d1c565b600890613ed3565b82828151811061293457612934615ede565b60209081029190910101528061294981615e46565b915050612904565b5095945050505050565b6129636134d4565b60c861ffff8716111561299d5760405163539c34bb60e11b815261ffff871660048201819052602482015260c86044820152606401610b47565b600082136129c1576040516321ea67b360e11b815260048101839052602401610b47565b6040805160a0808201835261ffff891680835263ffffffff89811660208086018290526000868801528a831660608088018290528b85166080988901819052600d805465ffffffffffff191688176201000087021768ffffffffffffffffff60301b1916600160381b850263ffffffff60581b191617600160581b83021790558a51601280548d8701519289166001600160401b031990911617600160201b92891692909202919091179081905560118d90558a519788528785019590955298860191909152840196909652938201879052838116928201929092529190921c90911660c08201527f777357bb93f63d088f18112d3dba38457aec633eb8f1341e1d418380ad328e789060e00160405180910390a1505050505050565b600d54600160301b900460ff1615612b095760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b0316612b3e57604051630fb532db60e11b815260040160405180910390fd5b6000818152600560205260409020600101546001600160a01b03163314612b95576000818152600560205260409081902060010154905163d084e97560e01b8152610b47916001600160a01b03169060040161594f565b6000818152600560205260409081902080546001600160a01b031980821633908117845560019093018054909116905591516001600160a01b039092169183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c93869161206e91859161597c565b60008281526005602052604090205482906001600160a01b031680612c3a57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614612c655780604051636c51fda960e11b8152600401610b47919061594f565b600d54600160301b900460ff1615612c905760405163769dd35360e11b815260040160405180910390fd5b60008481526005602052604090206002015460641415612cc3576040516305a48e0f60e01b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b031615612cfa57610da6565b6001600160a01b0383166000818152600460209081526040808320888452825280832080546001600160401b031916600190811790915560058352818420600201805491820181558452919092200180546001600160a01b0319169092179091555184907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e190612d8b90869061594f565b60405180910390a250505050565b600081604051602001612dac91906159b8565b604051602081830303815290604052805190602001209050919050565b60008281526005602052604090205482906001600160a01b031680612e0157604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614612e2c5780604051636c51fda960e11b8152600401610b47919061594f565b600d54600160301b900460ff1615612e575760405163769dd35360e11b815260040160405180910390fd5b612e60846117f8565b15612e7e57604051631685ecdd60e31b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b0316612ecc5783836040516379bfd40160e01b8152600401610b47929190615ac0565b600084815260056020908152604080832060020180548251818502810185019093528083529192909190830182828015612f2f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612f11575b50505050509050600060018251612f469190615dab565b905060005b825181101561305257856001600160a01b0316838281518110612f7057612f70615ede565b60200260200101516001600160a01b03161415613040576000838381518110612f9b57612f9b615ede565b6020026020010151905080600560008a81526020019081526020016000206002018381548110612fcd57612fcd615ede565b600091825260208083209190910180546001600160a01b0319166001600160a01b03949094169390931790925589815260059091526040902060020180548061301857613018615ec8565b600082815260209020810160001990810180546001600160a01b031916905501905550613052565b8061304a81615e46565b915050612f4b565b506001600160a01b03851660009081526004602090815260408083208984529091529081902080546001600160401b03191690555186907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a7906127ea90889061594f565b600f81815481106130c657600080fd5b600091825260209091200154905081565b60008281526005602052604090205482906001600160a01b03168061310f57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b0382161461313a5780604051636c51fda960e11b8152600401610b47919061594f565b600d54600160301b900460ff16156131655760405163769dd35360e11b815260040160405180910390fd5b6000848152600560205260409020600101546001600160a01b03848116911614610da6576000848152600560205260409081902060010180546001600160a01b0319166001600160a01b0386161790555184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a190612d8b903390879061597c565b6000818152600560205260408120548190819081906060906001600160a01b031661322557604051630fb532db60e11b815260040160405180910390fd5b60008681526006602090815260408083205460058352928190208054600290910180548351818602810186019094528084526001600160601b0380871696600160601b810490911695600160c01b9091046001600160401b0316946001600160a01b03909416939183918301828280156132c857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116132aa575b505050505090509450945094509450945091939590929450565b6132ea6134d4565b6002546001600160a01b03166133135760405163c1f0c0a160e01b815260040160405180910390fd5b6002546040516370a0823160e01b81526000916001600160a01b0316906370a082319061334490309060040161594f565b60206040518083038186803b15801561335c57600080fd5b505afa158015613370573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061339491906154ea565b600a549091506001600160601b0316818111156133ce576040516354ced18160e11b81526004810182905260248101839052604401610b47565b81811015610f245760006133e28284615dab565b60025460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb906134159087908590600401615963565b602060405180830381600087803b15801561342f57600080fd5b505af1158015613443573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061346791906154b4565b61348457604051631f01ff1360e21b815260040160405180910390fd5b7f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b43660084826040516134b5929190615963565b60405180910390a150505050565b6134cb6134d4565b610b5081613edf565b6000546001600160a01b031633146135275760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610b47565b565b60008061353584613a78565b60025491935091506001600160a01b03161580159061355c57506001600160601b03821615155b1561360b5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061359c9086906001600160601b03871690600401615963565b602060405180830381600087803b1580156135b657600080fd5b505af11580156135ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ee91906154b4565b61360b57604051631e9acf1760e31b815260040160405180910390fd5b6000836001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114613661576040519150601f19603f3d011682016040523d82523d6000602084013e613666565b606091505b50509050806136885760405163950b247960e01b815260040160405180910390fd5b604080516001600160a01b03861681526001600160601b038581166020830152841681830152905186917f8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c4919081900360600190a25050505050565b604080516060810182526000808252602082018190529181019190915260006137108460000151612d99565b6000818152600e60205260409020549091506001600160a01b03168061374c57604051631dfd6e1360e21b815260048101839052602401610b47565b600082866080015160405160200161376e929190918252602082015260400190565b60408051601f19818403018152918152815160209283012060008181526010909352912054909150806137b457604051631b44092560e11b815260040160405180910390fd5b85516020808801516040808a015160608b015160808c015160a08d015193516137e3978a979096959101615b8f565b6040516020818303038152906040528051906020012081146138185760405163354a450b60e21b815260040160405180910390fd5b60006138278760000151613f83565b9050806138ff578651604051631d2827a760e31b81526001600160401b0390911660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e9413d389060240160206040518083038186803b15801561389957600080fd5b505afa1580156138ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d191906154ea565b9050806138ff57865160405163175dadad60e01b81526001600160401b039091166004820152602401610b47565b6000886080015182604051602001613921929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c905060006139488a83614065565b604080516060810182529889526020890196909652948701949094525093979650505050505050565b60005a61138881101561398357600080fd5b61138881039050846040820482031161399b57600080fd5b50823b6139a757600080fd5b60008083516020850160008789f190505b9392505050565b600081156139ec576012546139e59086908690600160201b900463ffffffff16866140d0565b9050613a06565b601254613a03908690869063ffffffff1686614172565b90505b949350505050565b6000805b601354811015613a6f57826001600160a01b031660138281548110613a3957613a39615ede565b6000918252602090912001546001600160a01b03161415613a5d5750600192915050565b80613a6781615e46565b915050613a12565b50600092915050565b6000818152600560209081526040808320815160608101835281546001600160a01b03908116825260018301541681850152600282018054845181870281018701865281815287968796949594860193919290830182828015613b0457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613ae6575b505050919092525050506000858152600660209081526040808320815160608101835290546001600160601b03808216808452600160601b8304909116948301859052600160c01b9091046001600160401b0316928201929092529096509094509192505b826040015151811015613be0576004600084604001518381518110613b9057613b90615ede565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120898252909252902080546001600160401b031916905580613bd881615e46565b915050613b69565b50600085815260056020526040812080546001600160a01b03199081168255600182018054909116905590613c1860028301826150b7565b5050600085815260066020526040812055613c34600886614298565b50600a8054859190600090613c539084906001600160601b0316615dc2565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555082600a600c8282829054906101000a90046001600160601b0316613c9b9190615dc2565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050915091565b6040805160208082018790526001600160a01b03959095168183015260608101939093526001600160401b03919091166080808401919091528151808403909101815260a08301825280519084012060c083019490945260e0808301859052815180840390910181526101009092019052805191012091565b60408051602081019091526000815281613d685750604080516020810190915260008152611407565b63125fa26760e31b613d7a8385615dea565b6001600160e01b03191614613da257604051632923fee760e11b815260040160405180910390fd5b613daf8260048186615cf2565b8101906139b89190615503565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa82604051602401613df591511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b600046613e39816142a4565b15613eb65760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015613e7857600080fd5b505afa158015613e8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613eb091906154ea565b91505090565b4391505090565b60006139b883836142c7565b6000611407825490565b60006139b88383614316565b6001600160a01b038116331415613f325760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610b47565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600046613f8f816142a4565b1561405657610100836001600160401b0316613fa9613e2d565b613fb39190615dab565b1180613fcf5750613fc2613e2d565b836001600160401b031610155b15613fdd5750600092915050565b6040516315a03d4160e11b81526001600160401b0384166004820152606490632b407a82906024015b60206040518083038186803b15801561401e57600080fd5b505afa158015614032573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139b891906154ea565b50506001600160401b03164090565b60006140998360000151846020015185604001518660600151868860a001518960c001518a60e001518b6101000151614340565b600383602001516040516020016140b1929190615ad7565b60408051601f1981840301815291905280516020909101209392505050565b6000806141136000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061455c92505050565b905060005a6141228888615d1c565b61412c9190615dab565b6141369085615d8c565b9050600061414f63ffffffff871664e8d4a51000615d8c565b90508261415c8284615d1c565b6141669190615d1c565b98975050505050505050565b60008061417d614621565b9050600081136141a3576040516321ea67b360e11b815260048101829052602401610b47565b60006141e56000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061455c92505050565b9050600082825a6141f68b8b615d1c565b6142009190615dab565b61420a9088615d8c565b6142149190615d1c565b61422690670de0b6b3a7640000615d8c565b6142309190615d78565b9050600061424963ffffffff881664e8d4a51000615d8c565b9050614261816b033b2e3c9fd0803ce8000000615dab565b8211156142815760405163e80fa38160e01b815260040160405180910390fd5b61428b8183615d1c565b9998505050505050505050565b60006139b883836146ec565b600061a4b18214806142b8575062066eed82145b8061140757505062066eee1490565b600081815260018301602052604081205461430e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611407565b506000611407565b600082600001828154811061432d5761432d615ede565b9060005260206000200154905092915050565b614349896147df565b6143925760405162461bcd60e51b815260206004820152601a6024820152797075626c6963206b6579206973206e6f74206f6e20637572766560301b6044820152606401610b47565b61439b886147df565b6143df5760405162461bcd60e51b815260206004820152601560248201527467616d6d61206973206e6f74206f6e20637572766560581b6044820152606401610b47565b6143e8836147df565b6144345760405162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e2063757276650000006044820152606401610b47565b61443d826147df565b6144895760405162461bcd60e51b815260206004820152601c60248201527f73486173685769746e657373206973206e6f74206f6e206375727665000000006044820152606401610b47565b614495878a88876148a2565b6144dd5760405162461bcd60e51b81526020600482015260196024820152786164647228632a706b2b732a6729213d5f755769746e65737360381b6044820152606401610b47565b60006144e98a876149c5565b905060006144fc898b878b868989614a29565b9050600061450d838d8d8a86614b3c565b9050808a1461454e5760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606401610b47565b505050505050505050505050565b600046614568816142a4565b156145a757606c6001600160a01b031663c6f7de0e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561401e57600080fd5b6145b081614b7c565b15613a6f57600f602160991b016001600160a01b03166349948e0e84604051806080016040528060488152602001615f2e604891396040516020016145f69291906158a5565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161400691906159d9565b600d5460035460408051633fabe5a360e21b81529051600093600160381b900463ffffffff169283151592859283926001600160a01b03169163feaf968c9160048083019260a0929190829003018186803b15801561467f57600080fd5b505afa158015614693573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b79190615780565b5094509092508491505080156146db57506146d28242615dab565b8463ffffffff16105b15613a065750601154949350505050565b600081815260018301602052604081205480156147d5576000614710600183615dab565b855490915060009061472490600190615dab565b905081811461478957600086600001828154811061474457614744615ede565b906000526020600020015490508087600001848154811061476757614767615ede565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061479a5761479a615ec8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611407565b6000915050611407565b80516000906401000003d0191161482d5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420782d6f7264696e61746560701b6044820152606401610b47565b60208201516401000003d0191161487b5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420792d6f7264696e61746560701b6044820152606401610b47565b60208201516401000003d01990800961489b8360005b6020020151614bb6565b1492915050565b60006001600160a01b0382166148e85760405162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b6044820152606401610b47565b6020840151600090600116156148ff57601c614902565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe19918203925060009190890987516040805160008082526020820180845287905260ff88169282019290925260608101929092526080820183905291925060019060a0016020604051602081039080840390855afa15801561499d573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b6149cd6150d5565b6149fa600184846040516020016149e69392919061592e565b604051602081830303815290604052614bda565b90505b614a06816147df565b611407578051604080516020810192909252614a2291016149e6565b90506149fd565b614a316150d5565b825186516401000003d0199081900691061415614a905760405162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e637400006044820152606401610b47565b614a9b878988614c28565b614ae05760405162461bcd60e51b8152602060048201526016602482015275119a5c9cdd081b5d5b0818da1958dac819985a5b195960521b6044820152606401610b47565b614aeb848685614c28565b614b315760405162461bcd60e51b815260206004820152601760248201527614d958dbdb99081b5d5b0818da1958dac819985a5b1959604a1b6044820152606401610b47565b614166868484614d50565b600060028686868587604051602001614b5a969594939291906158d4565b60408051601f1981840301815291905280516020909101209695505050505050565b6000600a821480614b8e57506101a482145b80614b9b575062aa37dc82145b80614ba7575061210582145b8061140757505062014a331490565b6000806401000003d01980848509840990506401000003d019600782089392505050565b614be26150d5565b614beb82614e13565b8152614c00614bfb826000614891565b614e4e565b602082018190526002900660011415612407576020810180516401000003d019039052919050565b600082614c655760405162461bcd60e51b815260206004820152600b60248201526a3d32b9379039b1b0b630b960a91b6044820152606401610b47565b83516020850151600090614c7b90600290615e88565b15614c8757601c614c8a565b601b5b9050600070014551231950b75fc4402da1732fc9bebe198387096040805160008082526020820180845281905260ff86169282019290925260608101869052608081018390529192509060019060a0016020604051602081039080840390855afa158015614cfc573d6000803e3d6000fd5b505050602060405103519050600086604051602001614d1b9190615893565b60408051601f1981840301815291905280516020909101206001600160a01b0392831692169190911498975050505050505050565b614d586150d5565b835160208086015185519186015160009384938493614d7993909190614e6e565b919450925090506401000003d019858209600114614dd55760405162461bcd60e51b815260206004820152601960248201527834b73b2d1036bab9ba1031329034b73b32b939b29037b3103d60391b6044820152606401610b47565b60405180604001604052806401000003d01980614df457614df4615eb2565b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d019811061240757604080516020808201939093528151808203840181529082019091528051910120614e1b565b6000611407826002614e676401000003d0196001615d1c565b901c614f4e565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a0890506000614eae83838585614fe5565b9098509050614ebf88828e88615009565b9098509050614ed088828c87615009565b90985090506000614ee38d878b85615009565b9098509050614ef488828686614fe5565b9098509050614f0588828e89615009565b9098509050818114614f3a576401000003d019818a0998506401000003d01982890997506401000003d0198183099650614f3e565b8196505b5050505050509450945094915050565b600080614f596150f3565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152614f8b615111565b60208160c0846005600019fa925082614fdb5760405162461bcd60e51b81526020600482015260126024820152716269674d6f64457870206661696c7572652160701b6044820152606401610b47565b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b8280548282559060005260206000209081019282156150a7579160200282015b828111156150a757825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615072565b506150b392915061512f565b5090565b5080546000825590600052602060002090810190610b50919061512f565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b808211156150b35760008155600101615130565b803561240781615f0a565b806040810183101561140757600080fd5b600082601f83011261517157600080fd5b615179615c85565b80838560408601111561518b57600080fd5b60005b60028110156151ad57813584526020938401939091019060010161518e565b509095945050505050565b600082601f8301126151c957600080fd5b81356001600160401b03808211156151e3576151e3615ef4565b604051601f8301601f19908116603f0116810190828211818310171561520b5761520b615ef4565b8160405283815286602085880101111561522457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060c0828403121561525657600080fd5b61525e615cad565b905081356001600160401b03808216821461527857600080fd5b81835260208401356020840152615291604085016152f7565b60408401526152a2606085016152f7565b60608401526152b360808501615144565b608084015260a08401359150808211156152cc57600080fd5b506152d9848285016151b8565b60a08301525092915050565b803561ffff8116811461240757600080fd5b803563ffffffff8116811461240757600080fd5b805169ffffffffffffffffffff8116811461240757600080fd5b80356001600160601b038116811461240757600080fd5b60006020828403121561534e57600080fd5b81356139b881615f0a565b6000806040838503121561536c57600080fd5b823561537781615f0a565b915061538560208401615325565b90509250929050565b600080604083850312156153a157600080fd5b82356153ac81615f0a565b915060208301356153bc81615f0a565b809150509250929050565b600080606083850312156153da57600080fd5b82356153e581615f0a565b9150615385846020850161514f565b6000806000806060858703121561540a57600080fd5b843561541581615f0a565b93506020850135925060408501356001600160401b038082111561543857600080fd5b818701915087601f83011261544c57600080fd5b81358181111561545b57600080fd5b88602082850101111561546d57600080fd5b95989497505060200194505050565b60006040828403121561548e57600080fd5b6139b8838361514f565b6000604082840312156154aa57600080fd5b6139b88383615160565b6000602082840312156154c657600080fd5b81516139b881615f1f565b6000602082840312156154e357600080fd5b5035919050565b6000602082840312156154fc57600080fd5b5051919050565b60006020828403121561551557600080fd5b604051602081018181106001600160401b038211171561553757615537615ef4565b604052823561554581615f1f565b81529392505050565b6000808284036101c081121561556357600080fd5b6101a08082121561557357600080fd5b61557b615ccf565b91506155878686615160565b82526155968660408701615160565b60208301526080850135604083015260a0850135606083015260c085013560808301526155c560e08601615144565b60a08301526101006155d987828801615160565b60c08401526155ec876101408801615160565b60e0840152610180860135908301529092508301356001600160401b0381111561561557600080fd5b61562185828601615244565b9150509250929050565b60006020828403121561563d57600080fd5b81356001600160401b0381111561565357600080fd5b820160c081850312156139b857600080fd5b60006020828403121561567757600080fd5b6139b8826152e5565b60008060008060008086880360e081121561569a57600080fd5b6156a3886152e5565b96506156b1602089016152f7565b95506156bf604089016152f7565b94506156cd606089016152f7565b9350608088013592506040609f19820112156156e857600080fd5b506156f1615c85565b6156fd60a089016152f7565b815261570b60c089016152f7565b6020820152809150509295509295509295565b6000806040838503121561573157600080fd5b8235915060208301356153bc81615f0a565b6000806040838503121561575657600080fd5b50508035926020909101359150565b60006020828403121561577757600080fd5b6139b8826152f7565b600080600080600060a0868803121561579857600080fd5b6157a18661530b565b94506020860151935060408601519250606086015191506157c46080870161530b565b90509295509295909350565b600081518084526020808501945080840160005b838110156158095781516001600160a01b0316875295820195908201906001016157e4565b509495945050505050565b8060005b6002811015610da6578151845260209384019390910190600101615818565b600081518084526020808501945080840160005b838110156158095781518752958201959082019060010161584b565b6000815180845261587f816020860160208601615e1a565b601f01601f19169290920160200192915050565b61589d8183615814565b604001919050565b600083516158b7818460208801615e1a565b8351908301906158cb818360208801615e1a565b01949350505050565b8681526158e46020820187615814565b6158f16060820186615814565b6158fe60a0820185615814565b61590b60e0820184615814565b60609190911b6001600160601b0319166101208201526101340195945050505050565b83815261593e6020820184615814565b606081019190915260800192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682526001600160601b0316602082015260400190565b604081016114078284615814565b6020815260006139b86020830184615837565b6020815260006139b86020830184615867565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160c06080840152615a3160e08401826157d0565b60808501516001600160601b0390811660a0868101919091529095015190941660c0909301929092525090919050565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b81811015615ab257845183529383019391830191600101615a96565b509098975050505050505050565b9182526001600160a01b0316602082015260400190565b828152606081016139b86020830184615814565b828152604060208201526000613a066040830184615837565b86815285602082015261ffff85166040820152600063ffffffff808616606084015280851660808401525060c060a083015261416660c0830184615867565b878152602081018790526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c0820181905260009061428b90830184615867565b8781526001600160401b03871660208201526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c0820181905260009061428b90830184615867565b6001600160601b038681168252851660208201526001600160401b03841660408201526001600160a01b038316606082015260a060808201819052600090615c2d908301846157d0565b979650505050505050565b6000808335601e19843603018112615c4f57600080fd5b8301803591506001600160401b03821115615c6957600080fd5b602001915036819003821315615c7e57600080fd5b9250929050565b604080519081016001600160401b0381118282101715615ca757615ca7615ef4565b60405290565b60405160c081016001600160401b0381118282101715615ca757615ca7615ef4565b60405161012081016001600160401b0381118282101715615ca757615ca7615ef4565b60008085851115615d0257600080fd5b83861115615d0f57600080fd5b5050820193919092039150565b60008219821115615d2f57615d2f615e9c565b500190565b60006001600160401b038083168185168083038211156158cb576158cb615e9c565b60006001600160601b038281168482168083038211156158cb576158cb615e9c565b600082615d8757615d87615eb2565b500490565b6000816000190483118215151615615da657615da6615e9c565b500290565b600082821015615dbd57615dbd615e9c565b500390565b60006001600160601b0383811690831681811015615de257615de2615e9c565b039392505050565b6001600160e01b03198135818116916004851015615e125780818660040360031b1b83161692505b505092915050565b60005b83811015615e35578181015183820152602001615e1d565b83811115610da65750506000910152565b6000600019821415615e5a57615e5a615e9c565b5060010190565b60006001600160401b0380831681811415615e7e57615e7e615e9c565b6001019392505050565b600082615e9757615e97615eb2565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610b5057600080fd5b8015158114610b5057600080fdfe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000806000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"blockhashStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"internalBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalBalance\",\"type\":\"uint256\"}],\"name\":\"BalanceInvariantViolated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"}],\"name\":\"BlockhashNotInStore\",\"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\":[],\"name\":\"FailedToSendNative\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"GasLimitTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"have\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"want\",\"type\":\"uint256\"}],\"name\":\"InsufficientGasForConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"have\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"min\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"max\",\"type\":\"uint16\"}],\"name\":\"InvalidRequestConfirmations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkAlreadySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkNotSet\",\"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\":[],\"name\":\"NoCorrespondingRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"NoSuchProvingKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"NumWordsTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structVRFCoordinatorV2_5.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"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\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeFundsRecovered\",\"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\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"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\":\"amountLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountNative\",\"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\":false,\"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\":\"uint256\",\"name\":\"oldNativeBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNativeBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFundedWithNative\",\"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\":\"BLOCKHASH_STORE\",\"outputs\":[{\"internalType\":\"contractBlockhashStoreInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK_NATIVE_FEED\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_REQUEST_CONFIRMATIONS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"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\":\"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[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"deregisterProvingKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"pk\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"gamma\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"uWitness\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"cGammaWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"sHashWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"zInv\",\"type\":\"uint256\"}],\"internalType\":\"structVRF.Proof\",\"name\":\"proof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockNum\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFCoordinatorV2_5.RequestCommitment\",\"name\":\"rc\",\"type\":\"tuple\"}],\"name\":\"fulfillRandomWords\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"fundSubscriptionWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveSubscriptionIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequestConfig\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"reqCount\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicKey\",\"type\":\"uint256[2]\"}],\"name\":\"hashOfKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrationVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"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\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"ownerCancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"pendingRequestExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverNativeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"registerProvingKey\",\"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\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFV2PlusClient.RandomWordsRequest\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"requestRandomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"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_config\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_currentSubNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fallbackWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_feeConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_provingKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"s_provingKeys\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestCommitments\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalNativeBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"internalType\":\"structVRFCoordinatorV2_5.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLINKAndLINKNativeFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200606038038062006060833981016040819052620000349162000183565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d7565b50505060601b6001600160601b031916608052620001b5565b6001600160a01b038116331415620001325760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019657600080fd5b81516001600160a01b0381168114620001ae57600080fd5b9392505050565b60805160601c615e85620001db6000396000818161056601526137d10152615e856000f3fe60806040526004361061023c5760003560e01c80637bce14d11161012f578063b08c8795116100b1578063b08c87951461076d578063b2a7cac51461078d578063bec4c08c146107ad578063caf70c4a146107cd578063cb631797146107ed578063d98e620e1461080d578063da2f26101461082d578063dac83d291461085d578063dc311dd31461087d578063e72f6e30146108ae578063ee9d2d38146108ce578063f2fde38b146108fb57600080fd5b80637bce14d1146106025780638402595e1461062257806386fe91c7146106425780638da5cb5b1461066257806395b55cfc146106805780639b1c385e146106935780639d40a6fd146106b3578063a21a23e4146106eb578063a4c0ed3614610700578063aa433aff14610720578063aefb212f1461074057600080fd5b8063330987b3116101c3578063330987b314610444578063405b84fa1461046457806340d6bb821461048457806341af6c87146104af57806351cff8d9146104df5780635d06b4ab146104ff57806364d51a2a1461051f5780636598274414610534578063689c4517146105545780636b6feccc1461058857806372e9d565146105cd57806379ba5097146105ed57600080fd5b80620122911461024157806304104edb1461026e578063043bd6ae14610290578063088070f5146102b457806308821d58146103345780630ae095401461035457806315c48b841461037457806318e3dd271461039c5780631b6b6d23146103db578063294daa49146104085780632f622e6b14610424575b600080fd5b34801561024d57600080fd5b5061025661091b565b60405161026593929190615964565b60405180910390f35b34801561027a57600080fd5b5061028e610289366004615295565b610997565b005b34801561029c57600080fd5b506102a660105481565b604051908152602001610265565b3480156102c057600080fd5b50600c546102fc9061ffff81169063ffffffff62010000820481169160ff600160301b82041691600160381b8204811691600160581b90041685565b6040805161ffff909616865263ffffffff9485166020870152921515928501929092528216606084015216608082015260a001610265565b34801561034057600080fd5b5061028e61034f366004615373565b610b4d565b34801561036057600080fd5b5061028e61036f366004615621565b610cc4565b34801561038057600080fd5b5061038960c881565b60405161ffff9091168152602001610265565b3480156103a857600080fd5b50600a546103c390600160601b90046001600160601b031681565b6040516001600160601b039091168152602001610265565b3480156103e757600080fd5b506002546103fb906001600160a01b031681565b6040516102659190615852565b34801561041457600080fd5b5060405160018152602001610265565b34801561043057600080fd5b5061028e61043f366004615295565b610d89565b34801561045057600080fd5b506103c361045f366004615451565b610efd565b34801561047057600080fd5b5061028e61047f366004615621565b6113bf565b34801561049057600080fd5b5061049a6101f481565b60405163ffffffff9091168152602001610265565b3480156104bb57600080fd5b506104cf6104ca3660046153d4565b6117aa565b6040519015158152602001610265565b3480156104eb57600080fd5b5061028e6104fa366004615295565b61194b565b34801561050b57600080fd5b5061028e61051a366004615295565b611afc565b34801561052b57600080fd5b50610389606481565b34801561054057600080fd5b5061028e61054f3660046152b2565b611bb3565b34801561056057600080fd5b506103fb7f000000000000000000000000000000000000000000000000000000000000000081565b34801561059457600080fd5b506011546105b09063ffffffff80821691600160201b90041682565b6040805163ffffffff938416815292909116602083015201610265565b3480156105d957600080fd5b506003546103fb906001600160a01b031681565b3480156105f957600080fd5b5061028e611c13565b34801561060e57600080fd5b5061028e61061d366004615373565b611cbd565b34801561062e57600080fd5b5061028e61063d366004615295565b611daa565b34801561064e57600080fd5b50600a546103c3906001600160601b031681565b34801561066e57600080fd5b506000546001600160a01b03166103fb565b61028e61068e3660046153d4565b611ebc565b34801561069f57600080fd5b506102a66106ae36600461552e565b612003565b3480156106bf57600080fd5b506007546106d3906001600160401b031681565b6040516001600160401b039091168152602001610265565b3480156106f757600080fd5b506102a6612395565b34801561070c57600080fd5b5061028e61071b3660046152eb565b6125e3565b34801561072c57600080fd5b5061028e61073b3660046153d4565b612783565b34801561074c57600080fd5b5061076061075b366004615646565b6127e3565b60405161026591906158c9565b34801561077957600080fd5b5061028e610788366004615583565b6128e4565b34801561079957600080fd5b5061028e6107a83660046153d4565b612a67565b3480156107b957600080fd5b5061028e6107c8366004615621565b612b8b565b3480156107d957600080fd5b506102a66107e836600461539b565b612d22565b3480156107f957600080fd5b5061028e610808366004615621565b612d52565b34801561081957600080fd5b506102a66108283660046153d4565b61303f565b34801561083957600080fd5b506104cf6108483660046153d4565b600d6020526000908152604090205460ff1681565b34801561086957600080fd5b5061028e610878366004615621565b613060565b34801561088957600080fd5b5061089d6108983660046153d4565b613170565b604051610265959493929190615ae6565b3480156108ba57600080fd5b5061028e6108c9366004615295565b61326b565b3480156108da57600080fd5b506102a66108e93660046153d4565b600f6020526000908152604090205481565b34801561090757600080fd5b5061028e610916366004615295565b61344c565b600c54600e805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff1693919283919083018282801561098557602002820191906000526020600020905b815481526020019060010190808311610971575b50505050509050925092509250909192565b61099f61345d565b60125460005b81811015610b2557826001600160a01b0316601282815481106109ca576109ca615de1565b6000918252602090912001546001600160a01b03161415610b135760126109f2600184615cae565b81548110610a0257610a02615de1565b600091825260209091200154601280546001600160a01b039092169183908110610a2e57610a2e615de1565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055826012610a65600185615cae565b81548110610a7557610a75615de1565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506012805480610ab457610ab4615dcb565b600082815260209020810160001990810180546001600160a01b03191690550190556040517ff80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af3790610b06908590615852565b60405180910390a1505050565b80610b1d81615d49565b9150506109a5565b5081604051635428d44960e01b8152600401610b419190615852565b60405180910390fd5b50565b610b5561345d565b604080518082018252600091610b84919084906002908390839080828437600092019190915250612d22915050565b6000818152600d602052604090205490915060ff16610bb957604051631dfd6e1360e21b815260048101829052602401610b41565b6000818152600d60205260408120805460ff191690555b600e54811015610c8b5781600e8281548110610bee57610bee615de1565b90600052602060002001541415610c7957600e805460009190610c1390600190615cae565b81548110610c2357610c23615de1565b9060005260206000200154905080600e8381548110610c4457610c44615de1565b600091825260209091200155600e805480610c6157610c61615dcb565b60019003818190600052602060002001600090559055505b80610c8381615d49565b915050610bd0565b506040518181527fbd242ec01625c15ecbc02cf700ac8b02c86f7346fa91a08e186810221ae509d0906020015b60405180910390a15050565b60008281526005602052604090205482906001600160a01b031680610cfc57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614610d275780604051636c51fda960e11b8152600401610b419190615852565b600c54600160301b900460ff1615610d525760405163769dd35360e11b815260040160405180910390fd5b610d5b846117aa565b15610d7957604051631685ecdd60e31b815260040160405180910390fd5b610d8384846134b2565b50505050565b600c54600160301b900460ff1615610db45760405163769dd35360e11b815260040160405180910390fd5b610dbc61345d565b600b54600160601b90046001600160601b0316610dec57604051631e9acf1760e31b815260040160405180910390fd5b600b8054600160601b90046001600160601b0316908190600c610e0f8380615cc5565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a600c8282829054906101000a90046001600160601b0316610e579190615cc5565b92506101000a8154816001600160601b0302191690836001600160601b031602179055506000826001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114610ed1576040519150601f19603f3d011682016040523d82523d6000602084013e610ed6565b606091505b5050905080610ef85760405163950b247960e01b815260040160405180910390fd5b505050565b600c54600090600160301b900460ff1615610f2b5760405163769dd35360e11b815260040160405180910390fd5b60005a90506000610f3c858561366d565b90506000846060015163ffffffff166001600160401b03811115610f6257610f62615df7565b604051908082528060200260200182016040528015610f8b578160200160208202803683370190505b50905060005b856060015163ffffffff1681101561100b57826040015181604051602001610fc3929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c828281518110610fee57610fee615de1565b60209081029190910101528061100381615d49565b915050610f91565b50602080830180516000908152600f9092526040808320839055905190518291631fe543e360e01b91611043919086906024016159ee565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600c805460ff60301b1916600160301b1790559088015160808901519192506000916110a89163ffffffff1690846138f2565b600c805460ff60301b19169055602089810151600090815260069091526040902054909150600160c01b90046001600160401b03166110e8816001615c37565b6020808b0151600090815260069091526040812080546001600160401b0393909316600160c01b026001600160c01b039093169290921790915560a08a0151805161113590600190615cae565b8151811061114557611145615de1565b602091010151600c5460f89190911c6001149150600090611176908a90600160581b900463ffffffff163a85613940565b9050811561126e576020808c01516000908152600690915260409020546001600160601b03808316600160601b9092041610156111c657604051631e9acf1760e31b815260040160405180910390fd5b60208b81015160009081526006909152604090208054829190600c906111fd908490600160601b90046001600160601b0316615cc5565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600b600c8282829054906101000a90046001600160601b03166112459190615c59565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550611349565b6020808c01516000908152600690915260409020546001600160601b03808316911610156112af57604051631e9acf1760e31b815260040160405180910390fd5b6020808c0151600090815260069091526040812080548392906112dc9084906001600160601b0316615cc5565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600b60008282829054906101000a90046001600160601b03166113249190615c59565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b8a6020015188602001517f49580fdfd9497e1ed5c1b1cec0495087ae8e3f1267470ec2fb015db32e3d6aa78a6040015184886040516113a6939291909283526001600160601b039190911660208301521515604082015260600190565b60405180910390a3985050505050505050505b92915050565b600c54600160301b900460ff16156113ea5760405163769dd35360e11b815260040160405180910390fd5b6113f38161398f565b6114125780604051635428d44960e01b8152600401610b419190615852565b60008060008061142186613170565b945094505093509350336001600160a01b0316826001600160a01b0316146114845760405162461bcd60e51b81526020600482015260166024820152752737ba1039bab139b1b934b83a34b7b71037bbb732b960511b6044820152606401610b41565b61148d866117aa565b156114d35760405162461bcd60e51b815260206004820152601660248201527550656e64696e6720726571756573742065786973747360501b6044820152606401610b41565b60006040518060c001604052806114e8600190565b60ff168152602001888152602001846001600160a01b03168152602001838152602001866001600160601b03168152602001856001600160601b0316815250905060008160405160200161153c91906158ef565b6040516020818303038152906040529050611556886139f9565b505060405163ce3f471960e01b81526001600160a01b0388169063ce3f4719906001600160601b0388169061158f9085906004016158dc565b6000604051808303818588803b1580156115a857600080fd5b505af11580156115bc573d6000803e3d6000fd5b50506002546001600160a01b0316158015935091506115e5905057506001600160601b03861615155b156116af5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061161c908a908a90600401615899565b602060405180830381600087803b15801561163657600080fd5b505af115801561164a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166e91906153b7565b6116af5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b6044820152606401610b41565b600c805460ff60301b1916600160301b17905560005b8351811015611758578381815181106116e0576116e0615de1565b60200260200101516001600160a01b0316638ea98117896040518263ffffffff1660e01b81526004016117139190615852565b600060405180830381600087803b15801561172d57600080fd5b505af1158015611741573d6000803e3d6000fd5b50505050808061175090615d49565b9150506116c5565b50600c805460ff60301b191690556040517fd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be4187906117989089908b90615866565b60405180910390a15050505050505050565b6000818152600560209081526040808320815160608101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561183457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611816575b505050505081525050905060005b8160400151518110156119415760005b600e5481101561192e5760006118f7600e838154811061187457611874615de1565b90600052602060002001548560400151858151811061189557611895615de1565b60200260200101518860046000896040015189815181106118b8576118b8615de1565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208d82529092529020546001600160401b0316613c47565b506000818152600f60205260409020549091501561191b5750600195945050505050565b508061192681615d49565b915050611852565b508061193981615d49565b915050611842565b5060009392505050565b600c54600160301b900460ff16156119765760405163769dd35360e11b815260040160405180910390fd5b61197e61345d565b6002546001600160a01b03166119a75760405163c1f0c0a160e01b815260040160405180910390fd5b600b546001600160601b03166119d057604051631e9acf1760e31b815260040160405180910390fd5b600b80546001600160601b031690819060006119ec8380615cc5565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a60008282829054906101000a90046001600160601b0316611a349190615cc5565b82546001600160601b039182166101009390930a92830291909202199091161790555060025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611a899085908590600401615899565b602060405180830381600087803b158015611aa357600080fd5b505af1158015611ab7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adb91906153b7565b611af857604051631e9acf1760e31b815260040160405180910390fd5b5050565b611b0461345d565b611b0d8161398f565b15611b2d578060405163ac8a27ef60e01b8152600401610b419190615852565b601280546001810182556000919091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af0162590611ba8908390615852565b60405180910390a150565b611bbb61345d565b6002546001600160a01b031615611be557604051631688c53760e11b815260040160405180910390fd5b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055565b6001546001600160a01b03163314611c665760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610b41565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611cc561345d565b604080518082018252600091611cf4919084906002908390839080828437600092019190915250612d22915050565b6000818152600d602052604090205490915060ff1615611d2a57604051634a0b8fa760e01b815260048101829052602401610b41565b6000818152600d6020526040808220805460ff19166001908117909155600e805491820181559092527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd909101829055517fc9583fd3afa3d7f16eb0b88d0268e7d05c09bafa4b21e092cbd1320e1bc8089d90610cb89083815260200190565b611db261345d565b600a544790600160601b90046001600160601b031681811115611df2576040516354ced18160e11b81526004810182905260248101839052604401610b41565b81811015610ef8576000611e068284615cae565b90506000846001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e55576040519150601f19603f3d011682016040523d82523d6000602084013e611e5a565b606091505b5050905080611e7c5760405163950b247960e01b815260040160405180910390fd5b7f4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c8583604051611ead929190615866565b60405180910390a15050505050565b600c54600160301b900460ff1615611ee75760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b0316611f1c57604051630fb532db60e11b815260040160405180910390fd5b60008181526006602052604090208054600160601b90046001600160601b0316903490600c611f4b8385615c59565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555034600a600c8282829054906101000a90046001600160601b0316611f939190615c59565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e902823484611fe69190615c1f565b604080519283526020830191909152015b60405180910390a25050565b600c54600090600160301b900460ff16156120315760405163769dd35360e11b815260040160405180910390fd5b6020808301356000908152600590915260409020546001600160a01b031661206c57604051630fb532db60e11b815260040160405180910390fd5b3360009081526004602090815260408083208583013584529091529020546001600160401b0316806120b9578260200135336040516379bfd40160e01b8152600401610b419291906159c3565b600c5461ffff166120d06060850160408601615568565b61ffff1610806120f3575060c86120ed6060850160408601615568565b61ffff16115b15612139576121086060840160408501615568565b600c5460405163539c34bb60e11b815261ffff92831660048201529116602482015260c86044820152606401610b41565b600c5462010000900463ffffffff166121586080850160608601615668565b63ffffffff1611156121a8576121746080840160608501615668565b600c54604051637aebf00f60e11b815263ffffffff9283166004820152620100009091049091166024820152604401610b41565b6101f46121bb60a0850160808601615668565b63ffffffff161115612201576121d760a0840160808501615668565b6040516311ce1afb60e21b815263ffffffff90911660048201526101f46024820152604401610b41565b600061220e826001615c37565b9050600080612224863533602089013586613c47565b9092509050600061224061223b60a0890189615b3b565b613cc0565b9050600061224d82613d3d565b905083612258613dae565b60208a013561226d60808c0160608d01615668565b61227d60a08d0160808e01615668565b33866040516020016122959796959493929190615a46565b60405160208183030381529060405280519060200120600f600086815260200190815260200160002081905550336001600160a01b0316886020013589600001357feb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e87878d604001602081019061230c9190615568565b8e606001602081019061231f9190615668565b8f60800160208101906123329190615668565b8960405161234596959493929190615a07565b60405180910390a45050336000908152600460209081526040808320898301358452909152902080546001600160401b0319166001600160401b039490941693909317909255925050505b919050565b600c54600090600160301b900460ff16156123c35760405163769dd35360e11b815260040160405180910390fd5b6000336123d1600143615cae565b600754604051606093841b6001600160601b03199081166020830152924060348201523090931b909116605483015260c01b6001600160c01b031916606882015260700160408051601f198184030181529190528051602090910120600780549192506001600160401b0390911690600061244b83615d64565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550506000806001600160401b0381111561248a5761248a615df7565b6040519080825280602002602001820160405280156124b3578160200160208202803683370190505b506040805160608082018352600080835260208084018281528486018381528984526006835286842095518654925191516001600160601b039182166001600160c01b031990941693909317600160601b9190921602176001600160c01b0316600160c01b6001600160401b039092169190910217909355835191820184523382528183018181528285018681528883526005855294909120825181546001600160a01b03199081166001600160a01b0392831617835592516001830180549094169116179091559251805194955090936125949260028501920190614fd3565b506125a491506008905083613e3e565b50817f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d336040516125d59190615852565b60405180910390a250905090565b600c54600160301b900460ff161561260e5760405163769dd35360e11b815260040160405180910390fd5b6002546001600160a01b03163314612639576040516344b0e3c360e01b815260040160405180910390fd5b6020811461265a57604051638129bbcd60e01b815260040160405180910390fd5b6000612668828401846153d4565b6000818152600560205260409020549091506001600160a01b03166126a057604051630fb532db60e11b815260040160405180910390fd5b600081815260066020526040812080546001600160601b0316918691906126c78385615c59565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600a60008282829054906101000a90046001600160601b031661270f9190615c59565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a8287846127629190615c1f565b604080519283526020830191909152015b60405180910390a2505050505050565b61278b61345d565b6000818152600560205260409020546001600160a01b03166127c057604051630fb532db60e11b815260040160405180910390fd5b600081815260056020526040902054610b4a9082906001600160a01b03166134b2565b606060006127f16008613e4a565b905080841061281357604051631390f2a160e01b815260040160405180910390fd5b600061281f8486615c1f565b90508181118061282d575083155b6128375780612839565b815b905060006128478683615cae565b6001600160401b0381111561285e5761285e615df7565b604051908082528060200260200182016040528015612887578160200160208202803683370190505b50905060005b81518110156128da576128ab6128a38883615c1f565b600890613e54565b8282815181106128bd576128bd615de1565b6020908102919091010152806128d281615d49565b91505061288d565b5095945050505050565b6128ec61345d565b60c861ffff871611156129265760405163539c34bb60e11b815261ffff871660048201819052602482015260c86044820152606401610b41565b6000821361294a576040516321ea67b360e11b815260048101839052602401610b41565b6040805160a0808201835261ffff891680835263ffffffff89811660208086018290526000868801528a831660608088018290528b85166080988901819052600c805465ffffffffffff191688176201000087021768ffffffffffffffffff60301b1916600160381b850263ffffffff60581b191617600160581b83021790558a51601180548d8701519289166001600160401b031990911617600160201b92891692909202919091179081905560108d90558a519788528785019590955298860191909152840196909652938201879052838116928201929092529190921c90911660c08201527f777357bb93f63d088f18112d3dba38457aec633eb8f1341e1d418380ad328e789060e00160405180910390a1505050505050565b600c54600160301b900460ff1615612a925760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b0316612ac757604051630fb532db60e11b815260040160405180910390fd5b6000818152600560205260409020600101546001600160a01b03163314612b1e576000818152600560205260409081902060010154905163d084e97560e01b8152610b41916001600160a01b031690600401615852565b6000818152600560205260409081902080546001600160a01b031980821633908117845560019093018054909116905591516001600160a01b039092169183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c938691611ff791859161587f565b60008281526005602052604090205482906001600160a01b031680612bc357604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614612bee5780604051636c51fda960e11b8152600401610b419190615852565b600c54600160301b900460ff1615612c195760405163769dd35360e11b815260040160405180910390fd5b60008481526005602052604090206002015460641415612c4c576040516305a48e0f60e01b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b031615612c8357610d83565b6001600160a01b0383166000818152600460209081526040808320888452825280832080546001600160401b031916600190811790915560058352818420600201805491820181558452919092200180546001600160a01b0319169092179091555184907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e190612d14908690615852565b60405180910390a250505050565b600081604051602001612d3591906158bb565b604051602081830303815290604052805190602001209050919050565b60008281526005602052604090205482906001600160a01b031680612d8a57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614612db55780604051636c51fda960e11b8152600401610b419190615852565b600c54600160301b900460ff1615612de05760405163769dd35360e11b815260040160405180910390fd5b612de9846117aa565b15612e0757604051631685ecdd60e31b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b0316612e555783836040516379bfd40160e01b8152600401610b419291906159c3565b600084815260056020908152604080832060020180548251818502810185019093528083529192909190830182828015612eb857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612e9a575b50505050509050600060018251612ecf9190615cae565b905060005b8251811015612fdb57856001600160a01b0316838281518110612ef957612ef9615de1565b60200260200101516001600160a01b03161415612fc9576000838381518110612f2457612f24615de1565b6020026020010151905080600560008a81526020019081526020016000206002018381548110612f5657612f56615de1565b600091825260208083209190910180546001600160a01b0319166001600160a01b039490941693909317909255898152600590915260409020600201805480612fa157612fa1615dcb565b600082815260209020810160001990810180546001600160a01b031916905501905550612fdb565b80612fd381615d49565b915050612ed4565b506001600160a01b03851660009081526004602090815260408083208984529091529081902080546001600160401b03191690555186907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a790612773908890615852565b600e818154811061304f57600080fd5b600091825260209091200154905081565b60008281526005602052604090205482906001600160a01b03168061309857604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146130c35780604051636c51fda960e11b8152600401610b419190615852565b600c54600160301b900460ff16156130ee5760405163769dd35360e11b815260040160405180910390fd5b6000848152600560205260409020600101546001600160a01b03848116911614610d83576000848152600560205260409081902060010180546001600160a01b0319166001600160a01b0386161790555184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a190612d14903390879061587f565b6000818152600560205260408120548190819081906060906001600160a01b03166131ae57604051630fb532db60e11b815260040160405180910390fd5b60008681526006602090815260408083205460058352928190208054600290910180548351818602810186019094528084526001600160601b0380871696600160601b810490911695600160c01b9091046001600160401b0316946001600160a01b039094169391839183018282801561325157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613233575b505050505090509450945094509450945091939590929450565b61327361345d565b6002546001600160a01b031661329c5760405163c1f0c0a160e01b815260040160405180910390fd5b6002546040516370a0823160e01b81526000916001600160a01b0316906370a08231906132cd903090600401615852565b60206040518083038186803b1580156132e557600080fd5b505afa1580156132f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061331d91906153ed565b600a549091506001600160601b031681811115613357576040516354ced18160e11b81526004810182905260248101839052604401610b41565b81811015610ef857600061336b8284615cae565b60025460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb9061339e9087908590600401615866565b602060405180830381600087803b1580156133b857600080fd5b505af11580156133cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f091906153b7565b61340d57604051631f01ff1360e21b815260040160405180910390fd5b7f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b436600848260405161343e929190615866565b60405180910390a150505050565b61345461345d565b610b4a81613e60565b6000546001600160a01b031633146134b05760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610b41565b565b6000806134be846139f9565b60025491935091506001600160a01b0316158015906134e557506001600160601b03821615155b156135945760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906135259086906001600160601b03871690600401615866565b602060405180830381600087803b15801561353f57600080fd5b505af1158015613553573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357791906153b7565b61359457604051631e9acf1760e31b815260040160405180910390fd5b6000836001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d80600081146135ea576040519150601f19603f3d011682016040523d82523d6000602084013e6135ef565b606091505b50509050806136115760405163950b247960e01b815260040160405180910390fd5b604080516001600160a01b03861681526001600160601b038581166020830152841681830152905186917f8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c4919081900360600190a25050505050565b604080516060810182526000808252602082018190529181019190915260006136998460000151612d22565b6000818152600d602052604090205490915060ff166136ce57604051631dfd6e1360e21b815260048101829052602401610b41565b60008185608001516040516020016136f0929190918252602082015260400190565b60408051601f1981840301815291815281516020928301206000818152600f9093529120549091508061373657604051631b44092560e11b815260040160405180910390fd5b845160208087015160408089015160608a015160808b015160a08c01519351613765978a979096959101615a92565b60405160208183030381529060405280519060200120811461379a5760405163354a450b60e21b815260040160405180910390fd5b60006137a98660000151613f04565b905080613881578551604051631d2827a760e31b81526001600160401b0390911660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e9413d389060240160206040518083038186803b15801561381b57600080fd5b505afa15801561382f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385391906153ed565b90508061388157855160405163175dadad60e01b81526001600160401b039091166004820152602401610b41565b60008760800151826040516020016138a3929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c905060006138ca8983613fe6565b6040805160608101825297885260208801969096529486019490945250929695505050505050565b60005a61138881101561390457600080fd5b61138881039050846040820482031161391c57600080fd5b50823b61392857600080fd5b60008083516020850160008789f190505b9392505050565b6000811561396d576011546139669086908690600160201b900463ffffffff1686614051565b9050613987565b601154613984908690869063ffffffff16866140f3565b90505b949350505050565b6000805b6012548110156139f057826001600160a01b0316601282815481106139ba576139ba615de1565b6000918252602090912001546001600160a01b031614156139de5750600192915050565b806139e881615d49565b915050613993565b50600092915050565b6000818152600560209081526040808320815160608101835281546001600160a01b03908116825260018301541681850152600282018054845181870281018701865281815287968796949594860193919290830182828015613a8557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613a67575b505050919092525050506000858152600660209081526040808320815160608101835290546001600160601b03808216808452600160601b8304909116948301859052600160c01b9091046001600160401b0316928201929092529096509094509192505b826040015151811015613b61576004600084604001518381518110613b1157613b11615de1565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120898252909252902080546001600160401b031916905580613b5981615d49565b915050613aea565b50600085815260056020526040812080546001600160a01b03199081168255600182018054909116905590613b996002830182615038565b5050600085815260066020526040812055613bb5600886614219565b50600a8054859190600090613bd49084906001600160601b0316615cc5565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555082600a600c8282829054906101000a90046001600160601b0316613c1c9190615cc5565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050915091565b6040805160208082018790526001600160a01b03959095168183015260608101939093526001600160401b03919091166080808401919091528151808403909101815260a08301825280519084012060c083019490945260e0808301859052815180840390910181526101009092019052805191012091565b60408051602081019091526000815281613ce957506040805160208101909152600081526113b9565b63125fa26760e31b613cfb8385615ced565b6001600160e01b03191614613d2357604051632923fee760e11b815260040160405180910390fd5b613d308260048186615bf5565b8101906139399190615406565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa82604051602401613d7691511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b600046613dba81614225565b15613e375760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015613df957600080fd5b505afa158015613e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e3191906153ed565b91505090565b4391505090565b60006139398383614248565b60006113b9825490565b60006139398383614297565b6001600160a01b038116331415613eb35760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610b41565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600046613f1081614225565b15613fd757610100836001600160401b0316613f2a613dae565b613f349190615cae565b1180613f505750613f43613dae565b836001600160401b031610155b15613f5e5750600092915050565b6040516315a03d4160e11b81526001600160401b0384166004820152606490632b407a82906024015b60206040518083038186803b158015613f9f57600080fd5b505afa158015613fb3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061393991906153ed565b50506001600160401b03164090565b600061401a8360000151846020015185604001518660600151868860a001518960c001518a60e001518b61010001516142c1565b600383602001516040516020016140329291906159da565b60408051601f1981840301815291905280516020909101209392505050565b6000806140946000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506144dd92505050565b905060005a6140a38888615c1f565b6140ad9190615cae565b6140b79085615c8f565b905060006140d063ffffffff871664e8d4a51000615c8f565b9050826140dd8284615c1f565b6140e79190615c1f565b98975050505050505050565b6000806140fe6145a2565b905060008113614124576040516321ea67b360e11b815260048101829052602401610b41565b60006141666000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506144dd92505050565b9050600082825a6141778b8b615c1f565b6141819190615cae565b61418b9088615c8f565b6141959190615c1f565b6141a790670de0b6b3a7640000615c8f565b6141b19190615c7b565b905060006141ca63ffffffff881664e8d4a51000615c8f565b90506141e2816b033b2e3c9fd0803ce8000000615cae565b8211156142025760405163e80fa38160e01b815260040160405180910390fd5b61420c8183615c1f565b9998505050505050505050565b6000613939838361466d565b600061a4b1821480614239575062066eed82145b806113b957505062066eee1490565b600081815260018301602052604081205461428f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556113b9565b5060006113b9565b60008260000182815481106142ae576142ae615de1565b9060005260206000200154905092915050565b6142ca89614760565b6143135760405162461bcd60e51b815260206004820152601a6024820152797075626c6963206b6579206973206e6f74206f6e20637572766560301b6044820152606401610b41565b61431c88614760565b6143605760405162461bcd60e51b815260206004820152601560248201527467616d6d61206973206e6f74206f6e20637572766560581b6044820152606401610b41565b61436983614760565b6143b55760405162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e2063757276650000006044820152606401610b41565b6143be82614760565b61440a5760405162461bcd60e51b815260206004820152601c60248201527f73486173685769746e657373206973206e6f74206f6e206375727665000000006044820152606401610b41565b614416878a8887614823565b61445e5760405162461bcd60e51b81526020600482015260196024820152786164647228632a706b2b732a6729213d5f755769746e65737360381b6044820152606401610b41565b600061446a8a87614946565b9050600061447d898b878b8689896149aa565b9050600061448e838d8d8a86614abd565b9050808a146144cf5760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606401610b41565b505050505050505050505050565b6000466144e981614225565b1561452857606c6001600160a01b031663c6f7de0e6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f9f57600080fd5b61453181614afd565b156139f057600f602160991b016001600160a01b03166349948e0e84604051806080016040528060488152602001615e31604891396040516020016145779291906157a8565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401613f8791906158dc565b600c5460035460408051633fabe5a360e21b81529051600093600160381b900463ffffffff169283151592859283926001600160a01b03169163feaf968c9160048083019260a0929190829003018186803b15801561460057600080fd5b505afa158015614614573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146389190615683565b50945090925084915050801561465c57506146538242615cae565b8463ffffffff16105b156139875750601054949350505050565b60008181526001830160205260408120548015614756576000614691600183615cae565b85549091506000906146a590600190615cae565b905081811461470a5760008660000182815481106146c5576146c5615de1565b90600052602060002001549050808760000184815481106146e8576146e8615de1565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061471b5761471b615dcb565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506113b9565b60009150506113b9565b80516000906401000003d019116147ae5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420782d6f7264696e61746560701b6044820152606401610b41565b60208201516401000003d019116147fc5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420792d6f7264696e61746560701b6044820152606401610b41565b60208201516401000003d01990800961481c8360005b6020020151614b37565b1492915050565b60006001600160a01b0382166148695760405162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b6044820152606401610b41565b60208401516000906001161561488057601c614883565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe19918203925060009190890987516040805160008082526020820180845287905260ff88169282019290925260608101929092526080820183905291925060019060a0016020604051602081039080840390855afa15801561491e573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b61494e615056565b61497b6001848460405160200161496793929190615831565b604051602081830303815290604052614b5b565b90505b61498781614760565b6113b95780516040805160208101929092526149a39101614967565b905061497e565b6149b2615056565b825186516401000003d0199081900691061415614a115760405162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e637400006044820152606401610b41565b614a1c878988614ba9565b614a615760405162461bcd60e51b8152602060048201526016602482015275119a5c9cdd081b5d5b0818da1958dac819985a5b195960521b6044820152606401610b41565b614a6c848685614ba9565b614ab25760405162461bcd60e51b815260206004820152601760248201527614d958dbdb99081b5d5b0818da1958dac819985a5b1959604a1b6044820152606401610b41565b6140e7868484614cd1565b600060028686868587604051602001614adb969594939291906157d7565b60408051601f1981840301815291905280516020909101209695505050505050565b6000600a821480614b0f57506101a482145b80614b1c575062aa37dc82145b80614b28575061210582145b806113b957505062014a331490565b6000806401000003d01980848509840990506401000003d019600782089392505050565b614b63615056565b614b6c82614d94565b8152614b81614b7c826000614812565b614dcf565b602082018190526002900660011415612390576020810180516401000003d019039052919050565b600082614be65760405162461bcd60e51b815260206004820152600b60248201526a3d32b9379039b1b0b630b960a91b6044820152606401610b41565b83516020850151600090614bfc90600290615d8b565b15614c0857601c614c0b565b601b5b9050600070014551231950b75fc4402da1732fc9bebe198387096040805160008082526020820180845281905260ff86169282019290925260608101869052608081018390529192509060019060a0016020604051602081039080840390855afa158015614c7d573d6000803e3d6000fd5b505050602060405103519050600086604051602001614c9c9190615796565b60408051601f1981840301815291905280516020909101206001600160a01b0392831692169190911498975050505050505050565b614cd9615056565b835160208086015185519186015160009384938493614cfa93909190614def565b919450925090506401000003d019858209600114614d565760405162461bcd60e51b815260206004820152601960248201527834b73b2d1036bab9ba1031329034b73b32b939b29037b3103d60391b6044820152606401610b41565b60405180604001604052806401000003d01980614d7557614d75615db5565b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d019811061239057604080516020808201939093528151808203840181529082019091528051910120614d9c565b60006113b9826002614de86401000003d0196001615c1f565b901c614ecf565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a0890506000614e2f83838585614f66565b9098509050614e4088828e88614f8a565b9098509050614e5188828c87614f8a565b90985090506000614e648d878b85614f8a565b9098509050614e7588828686614f66565b9098509050614e8688828e89614f8a565b9098509050818114614ebb576401000003d019818a0998506401000003d01982890997506401000003d0198183099650614ebf565b8196505b5050505050509450945094915050565b600080614eda615074565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152614f0c615092565b60208160c0846005600019fa925082614f5c5760405162461bcd60e51b81526020600482015260126024820152716269674d6f64457870206661696c7572652160701b6044820152606401610b41565b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b828054828255906000526020600020908101928215615028579160200282015b8281111561502857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614ff3565b506150349291506150b0565b5090565b5080546000825590600052602060002090810190610b4a91906150b0565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b8082111561503457600081556001016150b1565b803561239081615e0d565b600082601f8301126150e157600080fd5b6150e9615b88565b8083856040860111156150fb57600080fd5b60005b600281101561511d5781358452602093840193909101906001016150fe565b509095945050505050565b600082601f83011261513957600080fd5b81356001600160401b038082111561515357615153615df7565b604051601f8301601f19908116603f0116810190828211818310171561517b5761517b615df7565b8160405283815286602085880101111561519457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060c082840312156151c657600080fd5b6151ce615bb0565b905081356001600160401b0380821682146151e857600080fd5b8183526020840135602084015261520160408501615267565b604084015261521260608501615267565b6060840152615223608085016150c5565b608084015260a084013591508082111561523c57600080fd5b5061524984828501615128565b60a08301525092915050565b803561ffff8116811461239057600080fd5b803563ffffffff8116811461239057600080fd5b805169ffffffffffffffffffff8116811461239057600080fd5b6000602082840312156152a757600080fd5b813561393981615e0d565b600080604083850312156152c557600080fd5b82356152d081615e0d565b915060208301356152e081615e0d565b809150509250929050565b6000806000806060858703121561530157600080fd5b843561530c81615e0d565b93506020850135925060408501356001600160401b038082111561532f57600080fd5b818701915087601f83011261534357600080fd5b81358181111561535257600080fd5b88602082850101111561536457600080fd5b95989497505060200194505050565b60006040828403121561538557600080fd5b8260408301111561539557600080fd5b50919050565b6000604082840312156153ad57600080fd5b61393983836150d0565b6000602082840312156153c957600080fd5b815161393981615e22565b6000602082840312156153e657600080fd5b5035919050565b6000602082840312156153ff57600080fd5b5051919050565b60006020828403121561541857600080fd5b604051602081018181106001600160401b038211171561543a5761543a615df7565b604052823561544881615e22565b81529392505050565b6000808284036101c081121561546657600080fd5b6101a08082121561547657600080fd5b61547e615bd2565b915061548a86866150d0565b825261549986604087016150d0565b60208301526080850135604083015260a0850135606083015260c085013560808301526154c860e086016150c5565b60a08301526101006154dc878288016150d0565b60c08401526154ef8761014088016150d0565b60e0840152610180860135908301529092508301356001600160401b0381111561551857600080fd5b615524858286016151b4565b9150509250929050565b60006020828403121561554057600080fd5b81356001600160401b0381111561555657600080fd5b820160c0818503121561393957600080fd5b60006020828403121561557a57600080fd5b61393982615255565b60008060008060008086880360e081121561559d57600080fd5b6155a688615255565b96506155b460208901615267565b95506155c260408901615267565b94506155d060608901615267565b9350608088013592506040609f19820112156155eb57600080fd5b506155f4615b88565b61560060a08901615267565b815261560e60c08901615267565b6020820152809150509295509295509295565b6000806040838503121561563457600080fd5b8235915060208301356152e081615e0d565b6000806040838503121561565957600080fd5b50508035926020909101359150565b60006020828403121561567a57600080fd5b61393982615267565b600080600080600060a0868803121561569b57600080fd5b6156a48661527b565b94506020860151935060408601519250606086015191506156c76080870161527b565b90509295509295909350565b600081518084526020808501945080840160005b8381101561570c5781516001600160a01b0316875295820195908201906001016156e7565b509495945050505050565b8060005b6002811015610d8357815184526020938401939091019060010161571b565b600081518084526020808501945080840160005b8381101561570c5781518752958201959082019060010161574e565b60008151808452615782816020860160208601615d1d565b601f01601f19169290920160200192915050565b6157a08183615717565b604001919050565b600083516157ba818460208801615d1d565b8351908301906157ce818360208801615d1d565b01949350505050565b8681526157e76020820187615717565b6157f46060820186615717565b61580160a0820185615717565b61580e60e0820184615717565b60609190911b6001600160601b0319166101208201526101340195945050505050565b8381526158416020820184615717565b606081019190915260800192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682526001600160601b0316602082015260400190565b604081016113b98284615717565b602081526000613939602083018461573a565b602081526000613939602083018461576a565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160c0608084015261593460e08401826156d3565b60808501516001600160601b0390811660a0868101919091529095015190941660c0909301929092525090919050565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b818110156159b557845183529383019391830191600101615999565b509098975050505050505050565b9182526001600160a01b0316602082015260400190565b828152606081016139396020830184615717565b828152604060208201526000613987604083018461573a565b86815285602082015261ffff85166040820152600063ffffffff808616606084015280851660808401525060c060a08301526140e760c083018461576a565b878152602081018790526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c0820181905260009061420c9083018461576a565b8781526001600160401b03871660208201526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c0820181905260009061420c9083018461576a565b6001600160601b038681168252851660208201526001600160401b03841660408201526001600160a01b038316606082015260a060808201819052600090615b30908301846156d3565b979650505050505050565b6000808335601e19843603018112615b5257600080fd5b8301803591506001600160401b03821115615b6c57600080fd5b602001915036819003821315615b8157600080fd5b9250929050565b604080519081016001600160401b0381118282101715615baa57615baa615df7565b60405290565b60405160c081016001600160401b0381118282101715615baa57615baa615df7565b60405161012081016001600160401b0381118282101715615baa57615baa615df7565b60008085851115615c0557600080fd5b83861115615c1257600080fd5b5050820193919092039150565b60008219821115615c3257615c32615d9f565b500190565b60006001600160401b038083168185168083038211156157ce576157ce615d9f565b60006001600160601b038281168482168083038211156157ce576157ce615d9f565b600082615c8a57615c8a615db5565b500490565b6000816000190483118215151615615ca957615ca9615d9f565b500290565b600082821015615cc057615cc0615d9f565b500390565b60006001600160601b0383811690831681811015615ce557615ce5615d9f565b039392505050565b6001600160e01b03198135818116916004851015615d155780818660040360031b1b83161692505b505092915050565b60005b83811015615d38578181015183820152602001615d20565b83811115610d835750506000910152565b6000600019821415615d5d57615d5d615d9f565b5060010190565b60006001600160401b0380831681811415615d8157615d81615d9f565b6001019392505050565b600082615d9a57615d9a615db5565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610b4a57600080fd5b8015158114610b4a57600080fdfe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000806000a", } var VRFCoordinatorV25ABI = VRFCoordinatorV25MetaData.ABI @@ -634,25 +634,25 @@ func (_VRFCoordinatorV25 *VRFCoordinatorV25CallerSession) SProvingKeyHashes(arg0 return _VRFCoordinatorV25.Contract.SProvingKeyHashes(&_VRFCoordinatorV25.CallOpts, arg0) } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Caller) SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { +func (_VRFCoordinatorV25 *VRFCoordinatorV25Caller) SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { var out []interface{} err := _VRFCoordinatorV25.contract.Call(opts, &out, "s_provingKeys", arg0) if err != nil { - return *new(common.Address), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) SProvingKeys(arg0 [32]byte) (common.Address, error) { +func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) SProvingKeys(arg0 [32]byte) (bool, error) { return _VRFCoordinatorV25.Contract.SProvingKeys(&_VRFCoordinatorV25.CallOpts, arg0) } -func (_VRFCoordinatorV25 *VRFCoordinatorV25CallerSession) SProvingKeys(arg0 [32]byte) (common.Address, error) { +func (_VRFCoordinatorV25 *VRFCoordinatorV25CallerSession) SProvingKeys(arg0 [32]byte) (bool, error) { return _VRFCoordinatorV25.Contract.SProvingKeys(&_VRFCoordinatorV25.CallOpts, arg0) } @@ -854,30 +854,6 @@ func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) OnTokenTransfer(ar return _VRFCoordinatorV25.Contract.OnTokenTransfer(&_VRFCoordinatorV25.TransactOpts, arg0, amount, data) } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) OracleWithdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.contract.Transact(opts, "oracleWithdraw", recipient, amount) -} - -func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) OracleWithdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.Contract.OracleWithdraw(&_VRFCoordinatorV25.TransactOpts, recipient, amount) -} - -func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) OracleWithdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.Contract.OracleWithdraw(&_VRFCoordinatorV25.TransactOpts, recipient, amount) -} - -func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) OracleWithdrawNative(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.contract.Transact(opts, "oracleWithdrawNative", recipient, amount) -} - -func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) OracleWithdrawNative(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.Contract.OracleWithdrawNative(&_VRFCoordinatorV25.TransactOpts, recipient, amount) -} - -func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) OracleWithdrawNative(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.Contract.OracleWithdrawNative(&_VRFCoordinatorV25.TransactOpts, recipient, amount) -} - func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) OwnerCancelSubscription(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { return _VRFCoordinatorV25.contract.Transact(opts, "ownerCancelSubscription", subId) } @@ -926,16 +902,16 @@ func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) RegisterMigratable return _VRFCoordinatorV25.Contract.RegisterMigratableCoordinator(&_VRFCoordinatorV25.TransactOpts, target) } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) RegisterProvingKey(opts *bind.TransactOpts, oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.contract.Transact(opts, "registerProvingKey", oracle, publicProvingKey) +func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorV25.contract.Transact(opts, "registerProvingKey", publicProvingKey) } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) RegisterProvingKey(oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.Contract.RegisterProvingKey(&_VRFCoordinatorV25.TransactOpts, oracle, publicProvingKey) +func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) RegisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorV25.Contract.RegisterProvingKey(&_VRFCoordinatorV25.TransactOpts, publicProvingKey) } -func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) RegisterProvingKey(oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV25.Contract.RegisterProvingKey(&_VRFCoordinatorV25.TransactOpts, oracle, publicProvingKey) +func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) RegisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorV25.Contract.RegisterProvingKey(&_VRFCoordinatorV25.TransactOpts, publicProvingKey) } func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { @@ -1010,6 +986,30 @@ func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) TransferOwnership( return _VRFCoordinatorV25.Contract.TransferOwnership(&_VRFCoordinatorV25.TransactOpts, to) } +func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV25.contract.Transact(opts, "withdraw", recipient) +} + +func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) Withdraw(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV25.Contract.Withdraw(&_VRFCoordinatorV25.TransactOpts, recipient) +} + +func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) Withdraw(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV25.Contract.Withdraw(&_VRFCoordinatorV25.TransactOpts, recipient) +} + +func (_VRFCoordinatorV25 *VRFCoordinatorV25Transactor) WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV25.contract.Transact(opts, "withdrawNative", recipient) +} + +func (_VRFCoordinatorV25 *VRFCoordinatorV25Session) WithdrawNative(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV25.Contract.WithdrawNative(&_VRFCoordinatorV25.TransactOpts, recipient) +} + +func (_VRFCoordinatorV25 *VRFCoordinatorV25TransactorSession) WithdrawNative(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV25.Contract.WithdrawNative(&_VRFCoordinatorV25.TransactOpts, recipient) +} + type VRFCoordinatorV25ConfigSetIterator struct { Event *VRFCoordinatorV25ConfigSet @@ -2054,32 +2054,21 @@ func (it *VRFCoordinatorV25ProvingKeyDeregisteredIterator) Close() error { type VRFCoordinatorV25ProvingKeyDeregistered struct { KeyHash [32]byte - Oracle common.Address Raw types.Log } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) FilterProvingKeyDeregistered(opts *bind.FilterOpts, oracle []common.Address) (*VRFCoordinatorV25ProvingKeyDeregisteredIterator, error) { - - var oracleRule []interface{} - for _, oracleItem := range oracle { - oracleRule = append(oracleRule, oracleItem) - } +func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) FilterProvingKeyDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorV25ProvingKeyDeregisteredIterator, error) { - logs, sub, err := _VRFCoordinatorV25.contract.FilterLogs(opts, "ProvingKeyDeregistered", oracleRule) + logs, sub, err := _VRFCoordinatorV25.contract.FilterLogs(opts, "ProvingKeyDeregistered") if err != nil { return nil, err } return &VRFCoordinatorV25ProvingKeyDeregisteredIterator{contract: _VRFCoordinatorV25.contract, event: "ProvingKeyDeregistered", logs: logs, sub: sub}, nil } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) WatchProvingKeyDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyDeregistered, oracle []common.Address) (event.Subscription, error) { +func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) WatchProvingKeyDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyDeregistered) (event.Subscription, error) { - var oracleRule []interface{} - for _, oracleItem := range oracle { - oracleRule = append(oracleRule, oracleItem) - } - - logs, sub, err := _VRFCoordinatorV25.contract.WatchLogs(opts, "ProvingKeyDeregistered", oracleRule) + logs, sub, err := _VRFCoordinatorV25.contract.WatchLogs(opts, "ProvingKeyDeregistered") if err != nil { return nil, err } @@ -2182,32 +2171,21 @@ func (it *VRFCoordinatorV25ProvingKeyRegisteredIterator) Close() error { type VRFCoordinatorV25ProvingKeyRegistered struct { KeyHash [32]byte - Oracle common.Address Raw types.Log } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) FilterProvingKeyRegistered(opts *bind.FilterOpts, oracle []common.Address) (*VRFCoordinatorV25ProvingKeyRegisteredIterator, error) { +func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) FilterProvingKeyRegistered(opts *bind.FilterOpts) (*VRFCoordinatorV25ProvingKeyRegisteredIterator, error) { - var oracleRule []interface{} - for _, oracleItem := range oracle { - oracleRule = append(oracleRule, oracleItem) - } - - logs, sub, err := _VRFCoordinatorV25.contract.FilterLogs(opts, "ProvingKeyRegistered", oracleRule) + logs, sub, err := _VRFCoordinatorV25.contract.FilterLogs(opts, "ProvingKeyRegistered") if err != nil { return nil, err } return &VRFCoordinatorV25ProvingKeyRegisteredIterator{contract: _VRFCoordinatorV25.contract, event: "ProvingKeyRegistered", logs: logs, sub: sub}, nil } -func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyRegistered, oracle []common.Address) (event.Subscription, error) { - - var oracleRule []interface{} - for _, oracleItem := range oracle { - oracleRule = append(oracleRule, oracleItem) - } +func (_VRFCoordinatorV25 *VRFCoordinatorV25Filterer) WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyRegistered) (event.Subscription, error) { - logs, sub, err := _VRFCoordinatorV25.contract.WatchLogs(opts, "ProvingKeyRegistered", oracleRule) + logs, sub, err := _VRFCoordinatorV25.contract.WatchLogs(opts, "ProvingKeyRegistered") if err != nil { return nil, err } @@ -3674,11 +3652,11 @@ func (VRFCoordinatorV25OwnershipTransferred) Topic() common.Hash { } func (VRFCoordinatorV25ProvingKeyDeregistered) Topic() common.Hash { - return common.HexToHash("0x72be339577868f868798bac2c93e52d6f034fef4689a9848996c14ebb7416c0d") + return common.HexToHash("0xbd242ec01625c15ecbc02cf700ac8b02c86f7346fa91a08e186810221ae509d0") } func (VRFCoordinatorV25ProvingKeyRegistered) Topic() common.Hash { - return common.HexToHash("0xe729ae16526293f74ade739043022254f1489f616295a25bf72dfb4511ed73b8") + return common.HexToHash("0xc9583fd3afa3d7f16eb0b88d0268e7d05c09bafa4b21e092cbd1320e1bc8089d") } func (VRFCoordinatorV25RandomWordsFulfilled) Topic() common.Hash { @@ -3768,7 +3746,7 @@ type VRFCoordinatorV25Interface interface { SProvingKeyHashes(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) - SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) + SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (bool, error) SRequestCommitments(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) @@ -3798,10 +3776,6 @@ type VRFCoordinatorV25Interface interface { OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) - OracleWithdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) - - OracleWithdrawNative(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) - OwnerCancelSubscription(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) RecoverFunds(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -3810,7 +3784,7 @@ type VRFCoordinatorV25Interface interface { RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) - RegisterProvingKey(opts *bind.TransactOpts, oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) + RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) @@ -3824,6 +3798,10 @@ type VRFCoordinatorV25Interface interface { TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) + + WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) + FilterConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorV25ConfigSetIterator, error) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ConfigSet) (event.Subscription, error) @@ -3872,15 +3850,15 @@ type VRFCoordinatorV25Interface interface { ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorV25OwnershipTransferred, error) - FilterProvingKeyDeregistered(opts *bind.FilterOpts, oracle []common.Address) (*VRFCoordinatorV25ProvingKeyDeregisteredIterator, error) + FilterProvingKeyDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorV25ProvingKeyDeregisteredIterator, error) - WatchProvingKeyDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyDeregistered, oracle []common.Address) (event.Subscription, error) + WatchProvingKeyDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyDeregistered) (event.Subscription, error) ParseProvingKeyDeregistered(log types.Log) (*VRFCoordinatorV25ProvingKeyDeregistered, error) - FilterProvingKeyRegistered(opts *bind.FilterOpts, oracle []common.Address) (*VRFCoordinatorV25ProvingKeyRegisteredIterator, error) + FilterProvingKeyRegistered(opts *bind.FilterOpts) (*VRFCoordinatorV25ProvingKeyRegisteredIterator, error) - WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyRegistered, oracle []common.Address) (event.Subscription, error) + WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV25ProvingKeyRegistered) (event.Subscription, error) ParseProvingKeyRegistered(log types.Log) (*VRFCoordinatorV25ProvingKeyRegistered, error) diff --git a/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go b/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go index 7aae3d37770..ae3b764b3ce 100644 --- a/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go +++ b/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go @@ -66,8 +66,8 @@ type VRFV2PlusClientRandomWordsRequest struct { } var VRFCoordinatorV2PlusUpgradedVersionMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"blockhashStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"internalBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalBalance\",\"type\":\"uint256\"}],\"name\":\"BalanceInvariantViolated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"}],\"name\":\"BlockhashNotInStore\",\"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\":[],\"name\":\"FailedToSendNative\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"GasLimitTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"transferredValue\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"expectedValue\",\"type\":\"uint96\"}],\"name\":\"InvalidNativeBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"have\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"min\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"max\",\"type\":\"uint16\"}],\"name\":\"InvalidRequestConfirmations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"requestVersion\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"expectedVersion\",\"type\":\"uint8\"}],\"name\":\"InvalidVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkAlreadySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkNotSet\",\"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\":[],\"name\":\"NoCorrespondingRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"NoSuchProvingKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"NumWordsTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SubscriptionIDCollisionFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structVRFCoordinatorV2PlusUpgradedVersion.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeFundsRecovered\",\"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\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"ProvingKeyRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"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\":\"amountLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountNative\",\"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\":false,\"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\":\"uint256\",\"name\":\"oldNativeBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNativeBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFundedWithNative\",\"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\":\"BLOCKHASH_STORE\",\"outputs\":[{\"internalType\":\"contractBlockhashStoreInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK_NATIVE_FEED\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_REQUEST_CONFIRMATIONS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"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\":\"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\":[{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"pk\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"gamma\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"uWitness\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"cGammaWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"sHashWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"zInv\",\"type\":\"uint256\"}],\"internalType\":\"structVRF.Proof\",\"name\":\"proof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockNum\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFCoordinatorV2PlusUpgradedVersion.RequestCommitment\",\"name\":\"rc\",\"type\":\"tuple\"}],\"name\":\"fulfillRandomWords\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"fundSubscriptionWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveSubscriptionIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequestConfig\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"reqCount\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicKey\",\"type\":\"uint256[2]\"}],\"name\":\"hashOfKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"}],\"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\":\"encodedData\",\"type\":\"bytes\"}],\"name\":\"onMigration\",\"outputs\":[],\"stateMutability\":\"payable\",\"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\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"ownerCancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"pendingRequestExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverNativeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"registerProvingKey\",\"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\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFV2PlusClient.RandomWordsRequest\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"requestRandomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"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_config\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_currentSubNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_provingKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestCommitments\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalNativeBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"internalType\":\"structVRFCoordinatorV2PlusUpgradedVersion.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLINKAndLINKNativeFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50604051620061a6380380620061a6833981016040819052620000349162000183565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d7565b50505060601b6001600160601b031916608052620001b5565b6001600160a01b038116331415620001325760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019657600080fd5b81516001600160a01b0381168114620001ae57600080fd5b9392505050565b60805160601c615fcb620001db600039600081816104a601526136530152615fcb6000f3fe6080604052600436106101e05760003560e01c8062012291146101e5578063088070f5146102125780630ae095401461029257806315c48b84146102b457806318e3dd27146102dc5780631b6b6d231461031b5780632949265714610348578063294daa4914610368578063330987b314610384578063405b84fa146103a457806340d6bb82146103c457806341af6c87146103ef5780635d06b4ab1461041f57806364d51a2a1461043f578063659827441461045457806366316d8d14610474578063689c4517146104945780636f64f03f146104c857806372e9d565146104e857806379ba5097146105085780638402595e1461051d57806386fe91c71461053d5780638da5cb5b1461055d57806395b55cfc1461057b5780639b1c385e1461058e5780639d40a6fd146105bc578063a21a23e4146105e9578063a4c0ed36146105fe578063aa433aff1461061e578063aefb212f1461063e578063b08c87951461066b578063b2a7cac51461068b578063bec4c08c146106ab578063caf70c4a146106cb578063cb631797146106eb578063ce3f47191461070b578063d98e620e1461071e578063dac83d291461073e578063dc311dd31461075e578063e72f6e301461078f578063ee9d2d38146107af578063f2fde38b146107dc575b600080fd5b3480156101f157600080fd5b506101fa6107fc565b60405161020993929190615a56565b60405180910390f35b34801561021e57600080fd5b50600d5461025a9061ffff81169063ffffffff62010000820481169160ff600160301b82041691600160381b8204811691600160581b90041685565b6040805161ffff909616865263ffffffff9485166020870152921515928501929092528216606084015216608082015260a001610209565b34801561029e57600080fd5b506102b26102ad3660046156c9565b610878565b005b3480156102c057600080fd5b506102c960c881565b60405161ffff9091168152602001610209565b3480156102e857600080fd5b50600a5461030390600160601b90046001600160601b031681565b6040516001600160601b039091168152602001610209565b34801561032757600080fd5b5060025461033b906001600160a01b031681565b60405161020991906158fa565b34801561035457600080fd5b506102b261036336600461523b565b610946565b34801561037457600080fd5b5060405160028152602001610209565b34801561039057600080fd5b5061030361039f36600461541e565b610ac3565b3480156103b057600080fd5b506102b26103bf3660046156c9565b610f9e565b3480156103d057600080fd5b506103da6101f481565b60405163ffffffff9091168152602001610209565b3480156103fb57600080fd5b5061040f61040a3660046156b0565b611389565b6040519015158152602001610209565b34801561042b57600080fd5b506102b261043a36600461521e565b61152a565b34801561044b57600080fd5b506102c9606481565b34801561046057600080fd5b506102b261046f366004615270565b6115e1565b34801561048057600080fd5b506102b261048f36600461523b565b611641565b3480156104a057600080fd5b5061033b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d457600080fd5b506102b26104e33660046152a9565b611809565b3480156104f457600080fd5b5060035461033b906001600160a01b031681565b34801561051457600080fd5b506102b2611910565b34801561052957600080fd5b506102b261053836600461521e565b6119ba565b34801561054957600080fd5b50600a54610303906001600160601b031681565b34801561056957600080fd5b506000546001600160a01b031661033b565b6102b26105893660046156b0565b611ac6565b34801561059a57600080fd5b506105ae6105a93660046154fb565b611c0a565b604051908152602001610209565b3480156105c857600080fd5b506007546105dc906001600160401b031681565b6040516102099190615bef565b3480156105f557600080fd5b506105ae611f7a565b34801561060a57600080fd5b506102b26106193660046152e5565b6121c8565b34801561062a57600080fd5b506102b26106393660046156b0565b612365565b34801561064a57600080fd5b5061065e6106593660046156ee565b6123c8565b6040516102099190615971565b34801561067757600080fd5b506102b2610686366004615612565b6124c9565b34801561069757600080fd5b506102b26106a63660046156b0565b61263d565b3480156106b757600080fd5b506102b26106c63660046156c9565b612761565b3480156106d757600080fd5b506105ae6106e6366004615340565b6128f8565b3480156106f757600080fd5b506102b26107063660046156c9565b612928565b6102b2610719366004615392565b612c15565b34801561072a57600080fd5b506105ae6107393660046156b0565b612f26565b34801561074a57600080fd5b506102b26107593660046156c9565b612f47565b34801561076a57600080fd5b5061077e6107793660046156b0565b613057565b604051610209959493929190615c03565b34801561079b57600080fd5b506102b26107aa36600461521e565b613152565b3480156107bb57600080fd5b506105ae6107ca3660046156b0565b60106020526000908152604090205481565b3480156107e857600080fd5b506102b26107f736600461521e565b61332d565b600d54600f805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff1693919283919083018282801561086657602002820191906000526020600020905b815481526020019060010190808311610852575b50505050509050925092509250909192565b60008281526005602052604090205482906001600160a01b0316806108b057604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146108e45780604051636c51fda960e11b81526004016108db91906158fa565b60405180910390fd5b600d54600160301b900460ff161561090f5760405163769dd35360e11b815260040160405180910390fd5b61091884611389565b1561093657604051631685ecdd60e31b815260040160405180910390fd5b610940848461333e565b50505050565b600d54600160301b900460ff16156109715760405163769dd35360e11b815260040160405180910390fd5b336000908152600c60205260409020546001600160601b03808316911610156109ad57604051631e9acf1760e31b815260040160405180910390fd5b336000908152600c6020526040812080548392906109d59084906001600160601b0316615e0b565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a600c8282829054906101000a90046001600160601b0316610a1d9190615e0b565b92506101000a8154816001600160601b0302191690836001600160601b031602179055506000826001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114610a97576040519150601f19603f3d011682016040523d82523d6000602084013e610a9c565b606091505b5050905080610abe5760405163950b247960e01b815260040160405180910390fd5b505050565b600d54600090600160301b900460ff1615610af15760405163769dd35360e11b815260040160405180910390fd5b60005a90506000610b0285856134f9565b90506000846060015163ffffffff166001600160401b03811115610b2857610b28615f3d565b604051908082528060200260200182016040528015610b51578160200160208202803683370190505b50905060005b856060015163ffffffff16811015610bc857826040015181604051602001610b80929190615984565b6040516020818303038152906040528051906020012060001c828281518110610bab57610bab615f27565b602090810291909101015280610bc081615e8f565b915050610b57565b5060208083018051600090815260109092526040808320839055905190518291631fe543e360e01b91610c0091908690602401615ae0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600d805460ff60301b1916600160301b179055908801516080890151919250600091610c659163ffffffff16908461376c565b600d805460ff60301b19169055602089810151600090815260069091526040902054909150600160c01b90046001600160401b0316610ca5816001615d7d565b6020808b0151600090815260069091526040812080546001600160401b0393909316600160c01b026001600160c01b039093169290921790915560a08a01518051610cf290600190615df4565b81518110610d0257610d02615f27565b602091010151600d5460f89190911c6001149150600090610d33908a90600160581b900463ffffffff163a856137ba565b90508115610e3c576020808c01516000908152600690915260409020546001600160601b03808316600160601b909204161015610d8357604051631e9acf1760e31b815260040160405180910390fd5b60208b81015160009081526006909152604090208054829190600c90610dba908490600160601b90046001600160601b0316615e0b565b82546101009290920a6001600160601b0381810219909316918316021790915589516000908152600e60209081526040808320546001600160a01b03168352600c909152812080548594509092610e1391859116615d9f565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550610f28565b6020808c01516000908152600690915260409020546001600160601b0380831691161015610e7d57604051631e9acf1760e31b815260040160405180910390fd5b6020808c015160009081526006909152604081208054839290610eaa9084906001600160601b0316615e0b565b82546101009290920a6001600160601b0381810219909316918316021790915589516000908152600e60209081526040808320546001600160a01b03168352600b909152812080548594509092610f0391859116615d9f565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b8a6020015188602001517f49580fdfd9497e1ed5c1b1cec0495087ae8e3f1267470ec2fb015db32e3d6aa78a604001518488604051610f85939291909283526001600160601b039190911660208301521515604082015260600190565b60405180910390a3985050505050505050505b92915050565b600d54600160301b900460ff1615610fc95760405163769dd35360e11b815260040160405180910390fd5b610fd281613809565b610ff15780604051635428d44960e01b81526004016108db91906158fa565b60008060008061100086613057565b945094505093509350336001600160a01b0316826001600160a01b0316146110635760405162461bcd60e51b81526020600482015260166024820152752737ba1039bab139b1b934b83a34b7b71037bbb732b960511b60448201526064016108db565b61106c86611389565b156110b25760405162461bcd60e51b815260206004820152601660248201527550656e64696e6720726571756573742065786973747360501b60448201526064016108db565b60006040518060c001604052806110c7600290565b60ff168152602001888152602001846001600160a01b03168152602001838152602001866001600160601b03168152602001856001600160601b0316815250905060008160405160200161111b91906159c3565b604051602081830303815290604052905061113588613873565b505060405163ce3f471960e01b81526001600160a01b0388169063ce3f4719906001600160601b0388169061116e9085906004016159b0565b6000604051808303818588803b15801561118757600080fd5b505af115801561119b573d6000803e3d6000fd5b50506002546001600160a01b0316158015935091506111c4905057506001600160601b03861615155b1561128e5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906111fb908a908a90600401615941565b602060405180830381600087803b15801561121557600080fd5b505af1158015611229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124d919061535c565b61128e5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b60448201526064016108db565b600d805460ff60301b1916600160301b17905560005b8351811015611337578381815181106112bf576112bf615f27565b60200260200101516001600160a01b0316638ea98117896040518263ffffffff1660e01b81526004016112f291906158fa565b600060405180830381600087803b15801561130c57600080fd5b505af1158015611320573d6000803e3d6000fd5b50505050808061132f90615e8f565b9150506112a4565b50600d805460ff60301b191690556040517fd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be4187906113779089908b9061590e565b60405180910390a15050505050505050565b6000818152600560209081526040808320815160608101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561141357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113f5575b505050505081525050905060005b8160400151518110156115205760005b600f5481101561150d5760006114d6600f838154811061145357611453615f27565b90600052602060002001548560400151858151811061147457611474615f27565b602002602001015188600460008960400151898151811061149757611497615f27565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208d82529092529020546001600160401b0316613ac1565b50600081815260106020526040902054909150156114fa5750600195945050505050565b508061150581615e8f565b915050611431565b508061151881615e8f565b915050611421565b5060009392505050565b611532613b4a565b61153b81613809565b1561155b578060405163ac8a27ef60e01b81526004016108db91906158fa565b601380546001810182556000919091527f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0900180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af01625906115d69083906158fa565b60405180910390a150565b6115e9613b4a565b6002546001600160a01b03161561161357604051631688c53760e11b815260040160405180910390fd5b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055565b600d54600160301b900460ff161561166c5760405163769dd35360e11b815260040160405180910390fd5b6002546001600160a01b03166116955760405163c1f0c0a160e01b815260040160405180910390fd5b336000908152600b60205260409020546001600160601b03808316911610156116d157604051631e9acf1760e31b815260040160405180910390fd5b336000908152600b6020526040812080548392906116f99084906001600160601b0316615e0b565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a60008282829054906101000a90046001600160601b03166117419190615e0b565b82546001600160601b039182166101009390930a92830291909202199091161790555060025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906117969085908590600401615941565b602060405180830381600087803b1580156117b057600080fd5b505af11580156117c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e8919061535c565b61180557604051631e9acf1760e31b815260040160405180910390fd5b5050565b611811613b4a565b6040805180820182526000916118409190849060029083908390808284376000920191909152506128f8915050565b6000818152600e60205260409020549091506001600160a01b03161561187c57604051634a0b8fa760e01b8152600481018290526024016108db565b6000818152600e6020908152604080832080546001600160a01b0319166001600160a01b038816908117909155600f805460018101825594527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802909301849055518381527fe729ae16526293f74ade739043022254f1489f616295a25bf72dfb4511ed73b8910160405180910390a2505050565b6001546001600160a01b031633146119635760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b60448201526064016108db565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6119c2613b4a565b600a544790600160601b90046001600160601b0316818111156119fc5780826040516354ced18160e11b81526004016108db929190615984565b81811015610abe576000611a108284615df4565b90506000846001600160a01b03168260405160006040518083038185875af1925050503d8060008114611a5f576040519150601f19603f3d011682016040523d82523d6000602084013e611a64565b606091505b5050905080611a865760405163950b247960e01b815260040160405180910390fd5b7f4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c8583604051611ab792919061590e565b60405180910390a15050505050565b600d54600160301b900460ff1615611af15760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b0316611b2657604051630fb532db60e11b815260040160405180910390fd5b60008181526006602052604090208054600160601b90046001600160601b0316903490600c611b558385615d9f565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555034600a600c8282829054906101000a90046001600160601b0316611b9d9190615d9f565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e902823484611bf09190615d65565b604051611bfe929190615984565b60405180910390a25050565b600d54600090600160301b900460ff1615611c385760405163769dd35360e11b815260040160405180910390fd5b6020808301356000908152600590915260409020546001600160a01b0316611c7357604051630fb532db60e11b815260040160405180910390fd5b3360009081526004602090815260408083208583013584529091529020546001600160401b031680611cc0578260200135336040516379bfd40160e01b81526004016108db929190615ab5565b600d5461ffff16611cd760608501604086016155f7565b61ffff161080611cfa575060c8611cf460608501604086016155f7565b61ffff16115b15611d3457611d0f60608401604085016155f7565b600d5460405163539c34bb60e11b81526108db929161ffff169060c890600401615a38565b600d5462010000900463ffffffff16611d536080850160608601615710565b63ffffffff161115611d9957611d6f6080840160608501615710565b600d54604051637aebf00f60e11b81526108db929162010000900463ffffffff1690600401615bd8565b6101f4611dac60a0850160808601615710565b63ffffffff161115611de657611dc860a0840160808501615710565b6101f46040516311ce1afb60e21b81526004016108db929190615bd8565b6000611df3826001615d7d565b9050600080611e09863533602089013586613ac1565b90925090506000611e25611e2060a0890189615c58565b613b9f565b90506000611e3282613c1c565b905083611e3d613c8d565b60208a0135611e5260808c0160608d01615710565b611e6260a08d0160808e01615710565b3386604051602001611e7a9796959493929190615b38565b604051602081830303815290604052805190602001206010600086815260200190815260200160002081905550336001600160a01b0316886020013589600001357feb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e87878d6040016020810190611ef191906155f7565b8e6060016020810190611f049190615710565b8f6080016020810190611f179190615710565b89604051611f2a96959493929190615af9565b60405180910390a45050336000908152600460209081526040808320898301358452909152902080546001600160401b0319166001600160401b039490941693909317909255925050505b919050565b600d54600090600160301b900460ff1615611fa85760405163769dd35360e11b815260040160405180910390fd5b600033611fb6600143615df4565b600754604051606093841b6001600160601b03199081166020830152924060348201523090931b909116605483015260c01b6001600160c01b031916606882015260700160408051601f198184030181529190528051602090910120600780549192506001600160401b0390911690600061203083615eaa565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550506000806001600160401b0381111561206f5761206f615f3d565b604051908082528060200260200182016040528015612098578160200160208202803683370190505b506040805160608082018352600080835260208084018281528486018381528984526006835286842095518654925191516001600160601b039182166001600160c01b031990941693909317600160601b9190921602176001600160c01b0316600160c01b6001600160401b039092169190910217909355835191820184523382528183018181528285018681528883526005855294909120825181546001600160a01b03199081166001600160a01b0392831617835592516001830180549094169116179091559251805194955090936121799260028501920190614e8f565b5061218991506008905083613d1d565b50817f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d336040516121ba91906158fa565b60405180910390a250905090565b600d54600160301b900460ff16156121f35760405163769dd35360e11b815260040160405180910390fd5b6002546001600160a01b0316331461221e576040516344b0e3c360e01b815260040160405180910390fd5b6020811461223f57604051638129bbcd60e01b815260040160405180910390fd5b600061224d828401846156b0565b6000818152600560205260409020549091506001600160a01b031661228557604051630fb532db60e11b815260040160405180910390fd5b600081815260066020526040812080546001600160601b0316918691906122ac8385615d9f565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600a60008282829054906101000a90046001600160601b03166122f49190615d9f565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a8287846123479190615d65565b604051612355929190615984565b60405180910390a2505050505050565b61236d613b4a565b6000818152600560205260409020546001600160a01b03166123a257604051630fb532db60e11b815260040160405180910390fd5b6000818152600560205260409020546123c59082906001600160a01b031661333e565b50565b606060006123d66008613d29565b90508084106123f857604051631390f2a160e01b815260040160405180910390fd5b60006124048486615d65565b905081811180612412575083155b61241c578061241e565b815b9050600061242c8683615df4565b6001600160401b0381111561244357612443615f3d565b60405190808252806020026020018201604052801561246c578160200160208202803683370190505b50905060005b81518110156124bf576124906124888883615d65565b600890613d33565b8282815181106124a2576124a2615f27565b6020908102919091010152806124b781615e8f565b915050612472565b5095945050505050565b6124d1613b4a565b60c861ffff871611156124fe57858660c860405163539c34bb60e11b81526004016108db93929190615a38565b60008213612522576040516321ea67b360e11b8152600481018390526024016108db565b6040805160a0808201835261ffff891680835263ffffffff89811660208086018290526000868801528a831660608088018290528b85166080988901819052600d805465ffffffffffff1916881762010000870217600160301b600160781b031916600160381b850263ffffffff60581b191617600160581b83021790558a51601280548d8701519289166001600160401b031990911617600160201b92891692909202919091179081905560118d90558a519788528785019590955298860191909152840196909652938201879052838116928201929092529190921c90911660c08201527f777357bb93f63d088f18112d3dba38457aec633eb8f1341e1d418380ad328e789060e00160405180910390a1505050505050565b600d54600160301b900460ff16156126685760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b031661269d57604051630fb532db60e11b815260040160405180910390fd5b6000818152600560205260409020600101546001600160a01b031633146126f4576000818152600560205260409081902060010154905163d084e97560e01b81526108db916001600160a01b0316906004016158fa565b6000818152600560205260409081902080546001600160a01b031980821633908117845560019093018054909116905591516001600160a01b039092169183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c938691611bfe918591615927565b60008281526005602052604090205482906001600160a01b03168061279957604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146127c45780604051636c51fda960e11b81526004016108db91906158fa565b600d54600160301b900460ff16156127ef5760405163769dd35360e11b815260040160405180910390fd5b60008481526005602052604090206002015460641415612822576040516305a48e0f60e01b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b03161561285957610940565b6001600160a01b0383166000818152600460209081526040808320888452825280832080546001600160401b031916600190811790915560058352818420600201805491820181558452919092200180546001600160a01b0319169092179091555184907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e1906128ea9086906158fa565b60405180910390a250505050565b60008160405160200161290b9190615963565b604051602081830303815290604052805190602001209050919050565b60008281526005602052604090205482906001600160a01b03168061296057604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b0382161461298b5780604051636c51fda960e11b81526004016108db91906158fa565b600d54600160301b900460ff16156129b65760405163769dd35360e11b815260040160405180910390fd5b6129bf84611389565b156129dd57604051631685ecdd60e31b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b0316612a2b5783836040516379bfd40160e01b81526004016108db929190615ab5565b600084815260056020908152604080832060020180548251818502810185019093528083529192909190830182828015612a8e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612a70575b50505050509050600060018251612aa59190615df4565b905060005b8251811015612bb157856001600160a01b0316838281518110612acf57612acf615f27565b60200260200101516001600160a01b03161415612b9f576000838381518110612afa57612afa615f27565b6020026020010151905080600560008a81526020019081526020016000206002018381548110612b2c57612b2c615f27565b600091825260208083209190910180546001600160a01b0319166001600160a01b039490941693909317909255898152600590915260409020600201805480612b7757612b77615f11565b600082815260209020810160001990810180546001600160a01b031916905501905550612bb1565b80612ba981615e8f565b915050612aaa565b506001600160a01b03851660009081526004602090815260408083208984529091529081902080546001600160401b03191690555186907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a7906123559088906158fa565b6000612c2382840184615535565b9050806000015160ff16600114612c5c57805160405163237d181f60e21b815260ff9091166004820152600160248201526044016108db565b8060a001516001600160601b03163414612ca05760a08101516040516306acf13560e41b81523460048201526001600160601b0390911660248201526044016108db565b6020808201516000908152600590915260409020546001600160a01b031615612cdc576040516326afa43560e11b815260040160405180910390fd5b60005b816060015151811015612d7c5760016004600084606001518481518110612d0857612d08615f27565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008460200151815260200190815260200160002060006101000a8154816001600160401b0302191690836001600160401b031602179055508080612d7490615e8f565b915050612cdf565b50604080516060808201835260808401516001600160601b03908116835260a0850151811660208085019182526000858701818152828901805183526006845288832097518854955192516001600160401b0316600160c01b026001600160c01b03938816600160601b026001600160c01b0319909716919097161794909417169390931790945584518084018652868601516001600160a01b03908116825281860184815294880151828801908152925184526005865295909220825181549087166001600160a01b0319918216178255935160018201805491909716941693909317909455925180519192612e7b92600285019290910190614e8f565b5050506080810151600a8054600090612e9e9084906001600160601b0316615d9f565b92506101000a8154816001600160601b0302191690836001600160601b031602179055508060a00151600a600c8282829054906101000a90046001600160601b0316612eea9190615d9f565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555061094081602001516008613d1d90919063ffffffff16565b600f8181548110612f3657600080fd5b600091825260209091200154905081565b60008281526005602052604090205482906001600160a01b031680612f7f57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614612faa5780604051636c51fda960e11b81526004016108db91906158fa565b600d54600160301b900460ff1615612fd55760405163769dd35360e11b815260040160405180910390fd5b6000848152600560205260409020600101546001600160a01b03848116911614610940576000848152600560205260409081902060010180546001600160a01b0319166001600160a01b0386161790555184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a1906128ea9033908790615927565b6000818152600560205260408120548190819081906060906001600160a01b031661309557604051630fb532db60e11b815260040160405180910390fd5b60008681526006602090815260408083205460058352928190208054600290910180548351818602810186019094528084526001600160601b0380871696600160601b810490911695600160c01b9091046001600160401b0316946001600160a01b039094169391839183018282801561313857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161311a575b505050505090509450945094509450945091939590929450565b61315a613b4a565b6002546001600160a01b03166131835760405163c1f0c0a160e01b815260040160405180910390fd5b6002546040516370a0823160e01b81526000916001600160a01b0316906370a08231906131b49030906004016158fa565b60206040518083038186803b1580156131cc57600080fd5b505afa1580156131e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132049190615379565b600a549091506001600160601b0316818111156132385780826040516354ced18160e11b81526004016108db929190615984565b81811015610abe57600061324c8284615df4565b60025460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb9061327f908790859060040161590e565b602060405180830381600087803b15801561329957600080fd5b505af11580156132ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d1919061535c565b6132ee57604051631f01ff1360e21b815260040160405180910390fd5b7f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b436600848260405161331f92919061590e565b60405180910390a150505050565b613335613b4a565b6123c581613d3f565b60008061334a84613873565b60025491935091506001600160a01b03161580159061337157506001600160601b03821615155b156134205760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906133b19086906001600160601b0387169060040161590e565b602060405180830381600087803b1580156133cb57600080fd5b505af11580156133df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613403919061535c565b61342057604051631e9acf1760e31b815260040160405180910390fd5b6000836001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114613476576040519150601f19603f3d011682016040523d82523d6000602084013e61347b565b606091505b505090508061349d5760405163950b247960e01b815260040160405180910390fd5b604080516001600160a01b03861681526001600160601b038581166020830152841681830152905186917f8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c4919081900360600190a25050505050565b6040805160608101825260008082526020820181905291810191909152600061352584600001516128f8565b6000818152600e60205260409020549091506001600160a01b03168061356157604051631dfd6e1360e21b8152600481018390526024016108db565b600082866080015160405160200161357a929190615984565b60408051601f19818403018152918152815160209283012060008181526010909352912054909150806135c057604051631b44092560e11b815260040160405180910390fd5b85516020808801516040808a015160608b015160808c015160a08d015193516135ef978a979096959101615b84565b6040516020818303038152906040528051906020012081146136245760405163354a450b60e21b815260040160405180910390fd5b60006136338760000151613de3565b9050806136fa578651604051631d2827a760e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163e9413d38916136879190600401615bef565b60206040518083038186803b15801561369f57600080fd5b505afa1580156136b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d79190615379565b9050806136fa57865160405163175dadad60e01b81526108db9190600401615bef565b600088608001518260405160200161371c929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c905060006137438a83613ec0565b604080516060810182529889526020890196909652948701949094525093979650505050505050565b60005a61138881101561377e57600080fd5b61138881039050846040820482031161379657600080fd5b50823b6137a257600080fd5b60008083516020850160008789f190505b9392505050565b600081156137e7576012546137e09086908690600160201b900463ffffffff1686613f2b565b9050613801565b6012546137fe908690869063ffffffff1686613fcd565b90505b949350505050565b6000805b60135481101561386a57826001600160a01b03166013828154811061383457613834615f27565b6000918252602090912001546001600160a01b031614156138585750600192915050565b8061386281615e8f565b91505061380d565b50600092915050565b6000818152600560209081526040808320815160608101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879687969495948601939192908301828280156138ff57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116138e1575b505050919092525050506000858152600660209081526040808320815160608101835290546001600160601b03808216808452600160601b8304909116948301859052600160c01b9091046001600160401b0316928201929092529096509094509192505b8260400151518110156139db57600460008460400151838151811061398b5761398b615f27565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120898252909252902080546001600160401b0319169055806139d381615e8f565b915050613964565b50600085815260056020526040812080546001600160a01b03199081168255600182018054909116905590613a136002830182614ef4565b5050600085815260066020526040812055613a2f6008866140f2565b50600a8054859190600090613a4e9084906001600160601b0316615e0b565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555082600a600c8282829054906101000a90046001600160601b0316613a969190615e0b565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050915091565b60408051602081018690526001600160a01b03851691810191909152606081018390526001600160401b03821660808201526000908190819060a00160408051601f198184030181529082905280516020918201209250613b26918991849101615984565b60408051808303601f19018152919052805160209091012097909650945050505050565b6000546001600160a01b03163314613b9d5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b60448201526064016108db565b565b60408051602081019091526000815281613bc85750604080516020810190915260008152610f98565b63125fa26760e31b613bda8385615e33565b6001600160e01b03191614613c0257604051632923fee760e11b815260040160405180910390fd5b613c0f8260048186615d3b565b8101906137b391906153d3565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa82604051602401613c5591511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b600046613c99816140fe565b15613d165760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015613cd857600080fd5b505afa158015613cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d109190615379565b91505090565b4391505090565b60006137b38383614121565b6000610f98825490565b60006137b38383614170565b6001600160a01b038116331415613d925760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b60448201526064016108db565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600046613def816140fe565b15613eb157610100836001600160401b0316613e09613c8d565b613e139190615df4565b1180613e2f5750613e22613c8d565b836001600160401b031610155b15613e3d5750600092915050565b6040516315a03d4160e11b8152606490632b407a8290613e61908690600401615bef565b60206040518083038186803b158015613e7957600080fd5b505afa158015613e8d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137b39190615379565b50506001600160401b03164090565b6000613ef48360000151846020015185604001518660600151868860a001518960c001518a60e001518b610100015161419a565b60038360200151604051602001613f0c929190615acc565b60408051601f1981840301815291905280516020909101209392505050565b600080613f6e6000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506143b592505050565b905060005a613f7d8888615d65565b613f879190615df4565b613f919085615dd5565b90506000613faa63ffffffff871664e8d4a51000615dd5565b905082613fb78284615d65565b613fc19190615d65565b98975050505050505050565b600080613fd861447a565b905060008113613ffe576040516321ea67b360e11b8152600481018290526024016108db565b60006140406000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506143b592505050565b9050600082825a6140518b8b615d65565b61405b9190615df4565b6140659088615dd5565b61406f9190615d65565b61408190670de0b6b3a7640000615dd5565b61408b9190615dc1565b905060006140a463ffffffff881664e8d4a51000615dd5565b90506140bb81676765c793fa10079d601b1b615df4565b8211156140db5760405163e80fa38160e01b815260040160405180910390fd5b6140e58183615d65565b9998505050505050505050565b60006137b38383614545565b600061a4b1821480614112575062066eed82145b80610f9857505062066eee1490565b600081815260018301602052604081205461416857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f98565b506000610f98565b600082600001828154811061418757614187615f27565b9060005260206000200154905092915050565b6141a389614638565b6141ec5760405162461bcd60e51b815260206004820152601a6024820152797075626c6963206b6579206973206e6f74206f6e20637572766560301b60448201526064016108db565b6141f588614638565b6142395760405162461bcd60e51b815260206004820152601560248201527467616d6d61206973206e6f74206f6e20637572766560581b60448201526064016108db565b61424283614638565b61428e5760405162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e20637572766500000060448201526064016108db565b61429782614638565b6142e25760405162461bcd60e51b815260206004820152601c60248201527b73486173685769746e657373206973206e6f74206f6e20637572766560201b60448201526064016108db565b6142ee878a88876146fb565b6143365760405162461bcd60e51b81526020600482015260196024820152786164647228632a706b2b732a6729213d5f755769746e65737360381b60448201526064016108db565b60006143428a8761480f565b90506000614355898b878b868989614873565b90506000614366838d8d8a86614986565b9050808a146143a75760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b60448201526064016108db565b505050505050505050505050565b6000466143c1816140fe565b1561440057606c6001600160a01b031663c6f7de0e6040518163ffffffff1660e01b815260040160206040518083038186803b158015613e7957600080fd5b614409816149c6565b1561386a57600f602160991b016001600160a01b03166349948e0e84604051806080016040528060488152602001615f776048913960405160200161444f929190615850565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401613e6191906159b0565b600d5460035460408051633fabe5a360e21b81529051600093600160381b900463ffffffff169283151592859283926001600160a01b03169163feaf968c9160048083019260a0929190829003018186803b1580156144d857600080fd5b505afa1580156144ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614510919061572b565b509450909250849150508015614534575061452b8242615df4565b8463ffffffff16105b156138015750601154949350505050565b6000818152600183016020526040812054801561462e576000614569600183615df4565b855490915060009061457d90600190615df4565b90508181146145e257600086600001828154811061459d5761459d615f27565b90600052602060002001549050808760000184815481106145c0576145c0615f27565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806145f3576145f3615f11565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f98565b6000915050610f98565b80516000906401000003d019116146865760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420782d6f7264696e61746560701b60448201526064016108db565b60208201516401000003d019116146d45760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420792d6f7264696e61746560701b60448201526064016108db565b60208201516401000003d0199080096146f48360005b6020020151614a00565b1492915050565b60006001600160a01b0382166147415760405162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b60448201526064016108db565b60208401516000906001161561475857601c61475b565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe19918203925060009190890987516040805160008082526020909101918290529293506001916147c591869188918790615992565b6020604051602081039080840390855afa1580156147e7573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b614817614f12565b61484460018484604051602001614830939291906158d9565b604051602081830303815290604052614a24565b90505b61485081614638565b610f9857805160408051602081019290925261486c9101614830565b9050614847565b61487b614f12565b825186516401000003d01990819006910614156148da5760405162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e6374000060448201526064016108db565b6148e5878988614a72565b61492a5760405162461bcd60e51b8152602060048201526016602482015275119a5c9cdd081b5d5b0818da1958dac819985a5b195960521b60448201526064016108db565b614935848685614a72565b61497b5760405162461bcd60e51b815260206004820152601760248201527614d958dbdb99081b5d5b0818da1958dac819985a5b1959604a1b60448201526064016108db565b613fc1868484614b8d565b6000600286868685876040516020016149a49695949392919061587f565b60408051601f1981840301815291905280516020909101209695505050505050565b6000600a8214806149d857506101a482145b806149e5575062aa37dc82145b806149f1575061210582145b80610f9857505062014a331490565b6000806401000003d01980848509840990506401000003d019600782089392505050565b614a2c614f12565b614a3582614c50565b8152614a4a614a458260006146ea565b614c8b565b602082018190526002900660011415611f75576020810180516401000003d019039052919050565b600082614aaf5760405162461bcd60e51b815260206004820152600b60248201526a3d32b9379039b1b0b630b960a91b60448201526064016108db565b83516020850151600090614ac590600290615ed1565b15614ad157601c614ad4565b601b5b9050600070014551231950b75fc4402da1732fc9bebe19838709604080516000808252602090910191829052919250600190614b17908390869088908790615992565b6020604051602081039080840390855afa158015614b39573d6000803e3d6000fd5b505050602060405103519050600086604051602001614b58919061583e565b60408051601f1981840301815291905280516020909101206001600160a01b0392831692169190911498975050505050505050565b614b95614f12565b835160208086015185519186015160009384938493614bb693909190614cab565b919450925090506401000003d019858209600114614c125760405162461bcd60e51b815260206004820152601960248201527834b73b2d1036bab9ba1031329034b73b32b939b29037b3103d60391b60448201526064016108db565b60405180604001604052806401000003d01980614c3157614c31615efb565b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d0198110611f7557604080516020808201939093528151808203840181529082019091528051910120614c58565b6000610f98826002614ca46401000003d0196001615d65565b901c614d8b565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a0890506000614ceb83838585614e22565b9098509050614cfc88828e88614e46565b9098509050614d0d88828c87614e46565b90985090506000614d208d878b85614e46565b9098509050614d3188828686614e22565b9098509050614d4288828e89614e46565b9098509050818114614d77576401000003d019818a0998506401000003d01982890997506401000003d0198183099650614d7b565b8196505b5050505050509450945094915050565b600080614d96614f30565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152614dc8614f4e565b60208160c0846005600019fa925082614e185760405162461bcd60e51b81526020600482015260126024820152716269674d6f64457870206661696c7572652160701b60448201526064016108db565b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b828054828255906000526020600020908101928215614ee4579160200282015b82811115614ee457825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614eaf565b50614ef0929150614f6c565b5090565b50805460008255906000526020600020908101906123c59190614f6c565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b80821115614ef05760008155600101614f6d565b8035611f7581615f53565b600082601f830112614f9d57600080fd5b813560206001600160401b03821115614fb857614fb8615f3d565b8160051b614fc7828201615d0b565b838152828101908684018388018501891015614fe257600080fd5b600093505b8584101561500e578035614ffa81615f53565b835260019390930192918401918401614fe7565b50979650505050505050565b600082601f83011261502b57600080fd5b615033615c9e565b80838560408601111561504557600080fd5b60005b6002811015615067578135845260209384019390910190600101615048565b509095945050505050565b60008083601f84011261508457600080fd5b5081356001600160401b0381111561509b57600080fd5b6020830191508360208285010111156150b357600080fd5b9250929050565b600082601f8301126150cb57600080fd5b81356001600160401b038111156150e4576150e4615f3d565b6150f7601f8201601f1916602001615d0b565b81815284602083860101111561510c57600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561513b57600080fd5b615143615cc6565b905081356001600160401b03808216821461515d57600080fd5b81835260208401356020840152615176604085016151dc565b6040840152615187606085016151dc565b606084015261519860808501614f81565b608084015260a08401359150808211156151b157600080fd5b506151be848285016150ba565b60a08301525092915050565b803561ffff81168114611f7557600080fd5b803563ffffffff81168114611f7557600080fd5b80516001600160501b0381168114611f7557600080fd5b80356001600160601b0381168114611f7557600080fd5b60006020828403121561523057600080fd5b81356137b381615f53565b6000806040838503121561524e57600080fd5b823561525981615f53565b915061526760208401615207565b90509250929050565b6000806040838503121561528357600080fd5b823561528e81615f53565b9150602083013561529e81615f53565b809150509250929050565b600080606083850312156152bc57600080fd5b82356152c781615f53565b9150606083018410156152d957600080fd5b50926020919091019150565b600080600080606085870312156152fb57600080fd5b843561530681615f53565b93506020850135925060408501356001600160401b0381111561532857600080fd5b61533487828801615072565b95989497509550505050565b60006040828403121561535257600080fd5b6137b3838361501a565b60006020828403121561536e57600080fd5b81516137b381615f68565b60006020828403121561538b57600080fd5b5051919050565b600080602083850312156153a557600080fd5b82356001600160401b038111156153bb57600080fd5b6153c785828601615072565b90969095509350505050565b6000602082840312156153e557600080fd5b604051602081016001600160401b038111828210171561540757615407615f3d565b604052823561541581615f68565b81529392505050565b6000808284036101c081121561543357600080fd5b6101a08082121561544357600080fd5b61544b615ce8565b9150615457868661501a565b8252615466866040870161501a565b60208301526080850135604083015260a0850135606083015260c0850135608083015261549560e08601614f81565b60a08301526101006154a98782880161501a565b60c08401526154bc87610140880161501a565b60e0840152610180860135908301529092508301356001600160401b038111156154e557600080fd5b6154f185828601615129565b9150509250929050565b60006020828403121561550d57600080fd5b81356001600160401b0381111561552357600080fd5b820160c081850312156137b357600080fd5b60006020828403121561554757600080fd5b81356001600160401b038082111561555e57600080fd5b9083019060c0828603121561557257600080fd5b61557a615cc6565b823560ff8116811461558b57600080fd5b8152602083810135908201526155a360408401614f81565b60408201526060830135828111156155ba57600080fd5b6155c687828601614f8c565b6060830152506155d860808401615207565b60808201526155e960a08401615207565b60a082015295945050505050565b60006020828403121561560957600080fd5b6137b3826151ca565b60008060008060008086880360e081121561562c57600080fd5b615635886151ca565b9650615643602089016151dc565b9550615651604089016151dc565b945061565f606089016151dc565b9350608088013592506040609f198201121561567a57600080fd5b50615683615c9e565b61568f60a089016151dc565b815261569d60c089016151dc565b6020820152809150509295509295509295565b6000602082840312156156c257600080fd5b5035919050565b600080604083850312156156dc57600080fd5b82359150602083013561529e81615f53565b6000806040838503121561570157600080fd5b50508035926020909101359150565b60006020828403121561572257600080fd5b6137b3826151dc565b600080600080600060a0868803121561574357600080fd5b61574c866151f0565b945060208601519350604086015192506060860151915061576f608087016151f0565b90509295509295909350565b600081518084526020808501945080840160005b838110156157b45781516001600160a01b03168752958201959082019060010161578f565b509495945050505050565b8060005b60028110156109405781518452602093840193909101906001016157c3565b600081518084526020808501945080840160005b838110156157b4578151875295820195908201906001016157f6565b6000815180845261582a816020860160208601615e63565b601f01601f19169290920160200192915050565b61584881836157bf565b604001919050565b60008351615862818460208801615e63565b835190830190615876818360208801615e63565b01949350505050565b86815261588f60208201876157bf565b61589c60608201866157bf565b6158a960a08201856157bf565b6158b660e08201846157bf565b60609190911b6001600160601b0319166101208201526101340195945050505050565b8381526158e960208201846157bf565b606081019190915260800192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682526001600160601b0316602082015260400190565b60408101610f9882846157bf565b6020815260006137b360208301846157e2565b918252602082015260400190565b93845260ff9290921660208401526040830152606082015260800190565b6020815260006137b36020830184615812565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160c06080840152615a0860e084018261577b565b60808501516001600160601b0390811660a0868101919091529095015190941660c0909301929092525090919050565b61ffff93841681529183166020830152909116604082015260600190565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b81811015615aa757845183529383019391830191600101615a8b565b509098975050505050505050565b9182526001600160a01b0316602082015260400190565b828152606081016137b360208301846157bf565b82815260406020820152600061380160408301846157e2565b86815285602082015261ffff85166040820152600063ffffffff808616606084015280851660808401525060c060a0830152613fc160c0830184615812565b878152602081018790526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c082018190526000906140e590830184615812565b8781526001600160401b03871660208201526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c082018190526000906140e590830184615812565b63ffffffff92831681529116602082015260400190565b6001600160401b0391909116815260200190565b6001600160601b038681168252851660208201526001600160401b03841660408201526001600160a01b038316606082015260a060808201819052600090615c4d9083018461577b565b979650505050505050565b6000808335601e19843603018112615c6f57600080fd5b8301803591506001600160401b03821115615c8957600080fd5b6020019150368190038213156150b357600080fd5b604080519081016001600160401b0381118282101715615cc057615cc0615f3d565b60405290565b60405160c081016001600160401b0381118282101715615cc057615cc0615f3d565b60405161012081016001600160401b0381118282101715615cc057615cc0615f3d565b604051601f8201601f191681016001600160401b0381118282101715615d3357615d33615f3d565b604052919050565b60008085851115615d4b57600080fd5b83861115615d5857600080fd5b5050820193919092039150565b60008219821115615d7857615d78615ee5565b500190565b60006001600160401b0382811684821680830382111561587657615876615ee5565b60006001600160601b0382811684821680830382111561587657615876615ee5565b600082615dd057615dd0615efb565b500490565b6000816000190483118215151615615def57615def615ee5565b500290565b600082821015615e0657615e06615ee5565b500390565b60006001600160601b0383811690831681811015615e2b57615e2b615ee5565b039392505050565b6001600160e01b03198135818116916004851015615e5b5780818660040360031b1b83161692505b505092915050565b60005b83811015615e7e578181015183820152602001615e66565b838111156109405750506000910152565b6000600019821415615ea357615ea3615ee5565b5060010190565b60006001600160401b0382811680821415615ec757615ec7615ee5565b6001019392505050565b600082615ee057615ee0615efb565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146123c557600080fd5b80151581146123c557600080fdfe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000806000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"blockhashStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"internalBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalBalance\",\"type\":\"uint256\"}],\"name\":\"BalanceInvariantViolated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"}],\"name\":\"BlockhashNotInStore\",\"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\":[],\"name\":\"FailedToSendNative\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"GasLimitTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"transferredValue\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"expectedValue\",\"type\":\"uint96\"}],\"name\":\"InvalidNativeBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"have\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"min\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"max\",\"type\":\"uint16\"}],\"name\":\"InvalidRequestConfirmations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"requestVersion\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"expectedVersion\",\"type\":\"uint8\"}],\"name\":\"InvalidVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkAlreadySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkNotSet\",\"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\":[],\"name\":\"NoCorrespondingRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"NoSuchProvingKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"NumWordsTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SubscriptionIDCollisionFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structVRFCoordinatorV2PlusUpgradedVersion.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeFundsRecovered\",\"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\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"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\":\"amountLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountNative\",\"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\":false,\"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\":\"uint256\",\"name\":\"oldNativeBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNativeBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFundedWithNative\",\"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\":\"BLOCKHASH_STORE\",\"outputs\":[{\"internalType\":\"contractBlockhashStoreInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK_NATIVE_FEED\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_REQUEST_CONFIRMATIONS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"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\":\"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\":[{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"pk\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"gamma\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"uWitness\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"cGammaWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"sHashWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"zInv\",\"type\":\"uint256\"}],\"internalType\":\"structVRF.Proof\",\"name\":\"proof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockNum\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFCoordinatorV2PlusUpgradedVersion.RequestCommitment\",\"name\":\"rc\",\"type\":\"tuple\"}],\"name\":\"fulfillRandomWords\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"fundSubscriptionWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveSubscriptionIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequestConfig\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"reqCount\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicKey\",\"type\":\"uint256[2]\"}],\"name\":\"hashOfKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"}],\"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\":\"encodedData\",\"type\":\"bytes\"}],\"name\":\"onMigration\",\"outputs\":[],\"stateMutability\":\"payable\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"ownerCancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"pendingRequestExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverNativeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"registerProvingKey\",\"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\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFV2PlusClient.RandomWordsRequest\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"requestRandomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"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_config\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_currentSubNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_provingKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestCommitments\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalNativeBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"}],\"internalType\":\"structVRFCoordinatorV2PlusUpgradedVersion.FeeConfig\",\"name\":\"feeConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLINKAndLINKNativeFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200610538038062006105833981016040819052620000349162000183565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d7565b50505060601b6001600160601b031916608052620001b5565b6001600160a01b038116331415620001325760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019657600080fd5b81516001600160a01b0381168114620001ae57600080fd5b9392505050565b60805160601c615f2a620001db600039600081816104a601526136510152615f2a6000f3fe6080604052600436106101e05760003560e01c8062012291146101e5578063088070f5146102125780630ae095401461029257806315c48b84146102b457806318e3dd27146102dc5780631b6b6d231461031b578063294daa49146103485780632f622e6b14610364578063330987b314610384578063405b84fa146103a457806340d6bb82146103c457806341af6c87146103ef57806351cff8d91461041f5780635d06b4ab1461043f57806364d51a2a1461045f5780636598274414610474578063689c45171461049457806372e9d565146104c857806379ba5097146104e85780637bce14d1146104fd5780638402595e1461051d57806386fe91c71461053d5780638da5cb5b1461055d57806395b55cfc1461057b5780639b1c385e1461058e5780639d40a6fd146105bc578063a21a23e4146105e9578063a4c0ed36146105fe578063aa433aff1461061e578063aefb212f1461063e578063b08c87951461066b578063b2a7cac51461068b578063bec4c08c146106ab578063caf70c4a146106cb578063cb631797146106eb578063ce3f47191461070b578063d98e620e1461071e578063dac83d291461073e578063dc311dd31461075e578063e72f6e301461078f578063ee9d2d38146107af578063f2fde38b146107dc575b600080fd5b3480156101f157600080fd5b506101fa6107fc565b604051610209939291906159b5565b60405180910390f35b34801561021e57600080fd5b50600c5461025a9061ffff81169063ffffffff62010000820481169160ff600160301b82041691600160381b8204811691600160581b90041685565b6040805161ffff909616865263ffffffff9485166020870152921515928501929092528216606084015216608082015260a001610209565b34801561029e57600080fd5b506102b26102ad366004615628565b610878565b005b3480156102c057600080fd5b506102c960c881565b60405161ffff9091168152602001610209565b3480156102e857600080fd5b50600a5461030390600160601b90046001600160601b031681565b6040516001600160601b039091168152602001610209565b34801561032757600080fd5b5060025461033b906001600160a01b031681565b6040516102099190615859565b34801561035457600080fd5b5060405160028152602001610209565b34801561037057600080fd5b506102b261037f3660046151c6565b610946565b34801561039057600080fd5b5061030361039f36600461537d565b610aba565b3480156103b057600080fd5b506102b26103bf366004615628565b610f73565b3480156103d057600080fd5b506103da6101f481565b60405163ffffffff9091168152602001610209565b3480156103fb57600080fd5b5061040f61040a36600461560f565b61135e565b6040519015158152602001610209565b34801561042b57600080fd5b506102b261043a3660046151c6565b6114ff565b34801561044b57600080fd5b506102b261045a3660046151c6565b6116b0565b34801561046b57600080fd5b506102c9606481565b34801561048057600080fd5b506102b261048f3660046151e3565b611767565b3480156104a057600080fd5b5061033b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d457600080fd5b5060035461033b906001600160a01b031681565b3480156104f457600080fd5b506102b26117c7565b34801561050957600080fd5b506102b2610518366004615277565b611871565b34801561052957600080fd5b506102b26105383660046151c6565b61196a565b34801561054957600080fd5b50600a54610303906001600160601b031681565b34801561056957600080fd5b506000546001600160a01b031661033b565b6102b261058936600461560f565b611a76565b34801561059a57600080fd5b506105ae6105a936600461545a565b611bba565b604051908152602001610209565b3480156105c857600080fd5b506007546105dc906001600160401b031681565b6040516102099190615b4e565b3480156105f557600080fd5b506105ae611f2a565b34801561060a57600080fd5b506102b261061936600461521c565b612178565b34801561062a57600080fd5b506102b261063936600461560f565b612315565b34801561064a57600080fd5b5061065e61065936600461564d565b612378565b60405161020991906158d0565b34801561067757600080fd5b506102b2610686366004615571565b612479565b34801561069757600080fd5b506102b26106a636600461560f565b6125ed565b3480156106b757600080fd5b506102b26106c6366004615628565b612711565b3480156106d757600080fd5b506105ae6106e636600461529f565b6128a8565b3480156106f757600080fd5b506102b2610706366004615628565b6128d8565b6102b26107193660046152f1565b612bc5565b34801561072a57600080fd5b506105ae61073936600461560f565b612ed6565b34801561074a57600080fd5b506102b2610759366004615628565b612ef7565b34801561076a57600080fd5b5061077e61077936600461560f565b613007565b604051610209959493929190615b62565b34801561079b57600080fd5b506102b26107aa3660046151c6565b613102565b3480156107bb57600080fd5b506105ae6107ca36600461560f565b600f6020526000908152604090205481565b3480156107e857600080fd5b506102b26107f73660046151c6565b6132dd565b600c54600e805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff1693919283919083018282801561086657602002820191906000526020600020905b815481526020019060010190808311610852575b50505050509050925092509250909192565b60008281526005602052604090205482906001600160a01b0316806108b057604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146108e45780604051636c51fda960e11b81526004016108db9190615859565b60405180910390fd5b600c54600160301b900460ff161561090f5760405163769dd35360e11b815260040160405180910390fd5b6109188461135e565b1561093657604051631685ecdd60e31b815260040160405180910390fd5b61094084846132ee565b50505050565b600c54600160301b900460ff16156109715760405163769dd35360e11b815260040160405180910390fd5b6109796134a9565b600b54600160601b90046001600160601b03166109a957604051631e9acf1760e31b815260040160405180910390fd5b600b8054600160601b90046001600160601b0316908190600c6109cc8380615d6a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a600c8282829054906101000a90046001600160601b0316610a149190615d6a565b92506101000a8154816001600160601b0302191690836001600160601b031602179055506000826001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114610a8e576040519150601f19603f3d011682016040523d82523d6000602084013e610a93565b606091505b5050905080610ab55760405163950b247960e01b815260040160405180910390fd5b505050565b600c54600090600160301b900460ff1615610ae85760405163769dd35360e11b815260040160405180910390fd5b60005a90506000610af985856134fe565b90506000846060015163ffffffff166001600160401b03811115610b1f57610b1f615e9c565b604051908082528060200260200182016040528015610b48578160200160208202803683370190505b50905060005b856060015163ffffffff16811015610bbf57826040015181604051602001610b779291906158e3565b6040516020818303038152906040528051906020012060001c828281518110610ba257610ba2615e86565b602090810291909101015280610bb781615dee565b915050610b4e565b50602080830180516000908152600f9092526040808320839055905190518291631fe543e360e01b91610bf791908690602401615a3f565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600c805460ff60301b1916600160301b179055908801516080890151919250600091610c5c9163ffffffff169084613769565b600c805460ff60301b19169055602089810151600090815260069091526040902054909150600160c01b90046001600160401b0316610c9c816001615cdc565b6020808b0151600090815260069091526040812080546001600160401b0393909316600160c01b026001600160c01b039093169290921790915560a08a01518051610ce990600190615d53565b81518110610cf957610cf9615e86565b602091010151600c5460f89190911c6001149150600090610d2a908a90600160581b900463ffffffff163a856137b7565b90508115610e22576020808c01516000908152600690915260409020546001600160601b03808316600160601b909204161015610d7a57604051631e9acf1760e31b815260040160405180910390fd5b60208b81015160009081526006909152604090208054829190600c90610db1908490600160601b90046001600160601b0316615d6a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600b600c8282829054906101000a90046001600160601b0316610df99190615cfe565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550610efd565b6020808c01516000908152600690915260409020546001600160601b0380831691161015610e6357604051631e9acf1760e31b815260040160405180910390fd5b6020808c015160009081526006909152604081208054839290610e909084906001600160601b0316615d6a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600b60008282829054906101000a90046001600160601b0316610ed89190615cfe565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b8a6020015188602001517f49580fdfd9497e1ed5c1b1cec0495087ae8e3f1267470ec2fb015db32e3d6aa78a604001518488604051610f5a939291909283526001600160601b039190911660208301521515604082015260600190565b60405180910390a3985050505050505050505b92915050565b600c54600160301b900460ff1615610f9e5760405163769dd35360e11b815260040160405180910390fd5b610fa781613806565b610fc65780604051635428d44960e01b81526004016108db9190615859565b600080600080610fd586613007565b945094505093509350336001600160a01b0316826001600160a01b0316146110385760405162461bcd60e51b81526020600482015260166024820152752737ba1039bab139b1b934b83a34b7b71037bbb732b960511b60448201526064016108db565b6110418661135e565b156110875760405162461bcd60e51b815260206004820152601660248201527550656e64696e6720726571756573742065786973747360501b60448201526064016108db565b60006040518060c0016040528061109c600290565b60ff168152602001888152602001846001600160a01b03168152602001838152602001866001600160601b03168152602001856001600160601b031681525090506000816040516020016110f09190615922565b604051602081830303815290604052905061110a88613870565b505060405163ce3f471960e01b81526001600160a01b0388169063ce3f4719906001600160601b0388169061114390859060040161590f565b6000604051808303818588803b15801561115c57600080fd5b505af1158015611170573d6000803e3d6000fd5b50506002546001600160a01b031615801593509150611199905057506001600160601b03861615155b156112635760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906111d0908a908a906004016158a0565b602060405180830381600087803b1580156111ea57600080fd5b505af11580156111fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122291906152bb565b6112635760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b60448201526064016108db565b600c805460ff60301b1916600160301b17905560005b835181101561130c5783818151811061129457611294615e86565b60200260200101516001600160a01b0316638ea98117896040518263ffffffff1660e01b81526004016112c79190615859565b600060405180830381600087803b1580156112e157600080fd5b505af11580156112f5573d6000803e3d6000fd5b50505050808061130490615dee565b915050611279565b50600c805460ff60301b191690556040517fd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be41879061134c9089908b9061586d565b60405180910390a15050505050505050565b6000818152600560209081526040808320815160608101835281546001600160a01b03908116825260018301541681850152600282018054845181870281018701865281815287969395860193909291908301828280156113e857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113ca575b505050505081525050905060005b8160400151518110156114f55760005b600e548110156114e25760006114ab600e838154811061142857611428615e86565b90600052602060002001548560400151858151811061144957611449615e86565b602002602001015188600460008960400151898151811061146c5761146c615e86565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208d82529092529020546001600160401b0316613abe565b506000818152600f6020526040902054909150156114cf5750600195945050505050565b50806114da81615dee565b915050611406565b50806114ed81615dee565b9150506113f6565b5060009392505050565b600c54600160301b900460ff161561152a5760405163769dd35360e11b815260040160405180910390fd5b6115326134a9565b6002546001600160a01b031661155b5760405163c1f0c0a160e01b815260040160405180910390fd5b600b546001600160601b031661158457604051631e9acf1760e31b815260040160405180910390fd5b600b80546001600160601b031690819060006115a08380615d6a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a60008282829054906101000a90046001600160601b03166115e89190615d6a565b82546001600160601b039182166101009390930a92830291909202199091161790555060025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061163d90859085906004016158a0565b602060405180830381600087803b15801561165757600080fd5b505af115801561166b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168f91906152bb565b6116ac57604051631e9acf1760e31b815260040160405180910390fd5b5050565b6116b86134a9565b6116c181613806565b156116e1578060405163ac8a27ef60e01b81526004016108db9190615859565b601280546001810182556000919091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af016259061175c908390615859565b60405180910390a150565b61176f6134a9565b6002546001600160a01b03161561179957604051631688c53760e11b815260040160405180910390fd5b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055565b6001546001600160a01b0316331461181a5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b60448201526064016108db565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6118796134a9565b6040805180820182526000916118a89190849060029083908390808284376000920191909152506128a8915050565b6000818152600d602052604090205490915060ff16156118de57604051634a0b8fa760e01b8152600481018290526024016108db565b6000818152600d6020526040808220805460ff19166001908117909155600e805491820181559092527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd909101829055517fc9583fd3afa3d7f16eb0b88d0268e7d05c09bafa4b21e092cbd1320e1bc8089d9061195e9083815260200190565b60405180910390a15050565b6119726134a9565b600a544790600160601b90046001600160601b0316818111156119ac5780826040516354ced18160e11b81526004016108db9291906158e3565b81811015610ab55760006119c08284615d53565b90506000846001600160a01b03168260405160006040518083038185875af1925050503d8060008114611a0f576040519150601f19603f3d011682016040523d82523d6000602084013e611a14565b606091505b5050905080611a365760405163950b247960e01b815260040160405180910390fd5b7f4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c8583604051611a6792919061586d565b60405180910390a15050505050565b600c54600160301b900460ff1615611aa15760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b0316611ad657604051630fb532db60e11b815260040160405180910390fd5b60008181526006602052604090208054600160601b90046001600160601b0316903490600c611b058385615cfe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555034600a600c8282829054906101000a90046001600160601b0316611b4d9190615cfe565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e902823484611ba09190615cc4565b604051611bae9291906158e3565b60405180910390a25050565b600c54600090600160301b900460ff1615611be85760405163769dd35360e11b815260040160405180910390fd5b6020808301356000908152600590915260409020546001600160a01b0316611c2357604051630fb532db60e11b815260040160405180910390fd5b3360009081526004602090815260408083208583013584529091529020546001600160401b031680611c70578260200135336040516379bfd40160e01b81526004016108db929190615a14565b600c5461ffff16611c876060850160408601615556565b61ffff161080611caa575060c8611ca46060850160408601615556565b61ffff16115b15611ce457611cbf6060840160408501615556565b600c5460405163539c34bb60e11b81526108db929161ffff169060c890600401615997565b600c5462010000900463ffffffff16611d03608085016060860161566f565b63ffffffff161115611d4957611d1f608084016060850161566f565b600c54604051637aebf00f60e11b81526108db929162010000900463ffffffff1690600401615b37565b6101f4611d5c60a085016080860161566f565b63ffffffff161115611d9657611d7860a084016080850161566f565b6101f46040516311ce1afb60e21b81526004016108db929190615b37565b6000611da3826001615cdc565b9050600080611db9863533602089013586613abe565b90925090506000611dd5611dd060a0890189615bb7565b613b47565b90506000611de282613bc4565b905083611ded613c35565b60208a0135611e0260808c0160608d0161566f565b611e1260a08d0160808e0161566f565b3386604051602001611e2a9796959493929190615a97565b60405160208183030381529060405280519060200120600f600086815260200190815260200160002081905550336001600160a01b0316886020013589600001357feb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e87878d6040016020810190611ea19190615556565b8e6060016020810190611eb4919061566f565b8f6080016020810190611ec7919061566f565b89604051611eda96959493929190615a58565b60405180910390a45050336000908152600460209081526040808320898301358452909152902080546001600160401b0319166001600160401b039490941693909317909255925050505b919050565b600c54600090600160301b900460ff1615611f585760405163769dd35360e11b815260040160405180910390fd5b600033611f66600143615d53565b600754604051606093841b6001600160601b03199081166020830152924060348201523090931b909116605483015260c01b6001600160c01b031916606882015260700160408051601f198184030181529190528051602090910120600780549192506001600160401b03909116906000611fe083615e09565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550506000806001600160401b0381111561201f5761201f615e9c565b604051908082528060200260200182016040528015612048578160200160208202803683370190505b506040805160608082018352600080835260208084018281528486018381528984526006835286842095518654925191516001600160601b039182166001600160c01b031990941693909317600160601b9190921602176001600160c01b0316600160c01b6001600160401b039092169190910217909355835191820184523382528183018181528285018681528883526005855294909120825181546001600160a01b03199081166001600160a01b0392831617835592516001830180549094169116179091559251805194955090936121299260028501920190614e37565b5061213991506008905083613cc5565b50817f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d3360405161216a9190615859565b60405180910390a250905090565b600c54600160301b900460ff16156121a35760405163769dd35360e11b815260040160405180910390fd5b6002546001600160a01b031633146121ce576040516344b0e3c360e01b815260040160405180910390fd5b602081146121ef57604051638129bbcd60e01b815260040160405180910390fd5b60006121fd8284018461560f565b6000818152600560205260409020549091506001600160a01b031661223557604051630fb532db60e11b815260040160405180910390fd5b600081815260066020526040812080546001600160601b03169186919061225c8385615cfe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600a60008282829054906101000a90046001600160601b03166122a49190615cfe565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a8287846122f79190615cc4565b6040516123059291906158e3565b60405180910390a2505050505050565b61231d6134a9565b6000818152600560205260409020546001600160a01b031661235257604051630fb532db60e11b815260040160405180910390fd5b6000818152600560205260409020546123759082906001600160a01b03166132ee565b50565b606060006123866008613cd1565b90508084106123a857604051631390f2a160e01b815260040160405180910390fd5b60006123b48486615cc4565b9050818111806123c2575083155b6123cc57806123ce565b815b905060006123dc8683615d53565b6001600160401b038111156123f3576123f3615e9c565b60405190808252806020026020018201604052801561241c578160200160208202803683370190505b50905060005b815181101561246f576124406124388883615cc4565b600890613cdb565b82828151811061245257612452615e86565b60209081029190910101528061246781615dee565b915050612422565b5095945050505050565b6124816134a9565b60c861ffff871611156124ae57858660c860405163539c34bb60e11b81526004016108db93929190615997565b600082136124d2576040516321ea67b360e11b8152600481018390526024016108db565b6040805160a0808201835261ffff891680835263ffffffff89811660208086018290526000868801528a831660608088018290528b85166080988901819052600c805465ffffffffffff1916881762010000870217600160301b600160781b031916600160381b850263ffffffff60581b191617600160581b83021790558a51601180548d8701519289166001600160401b031990911617600160201b92891692909202919091179081905560108d90558a519788528785019590955298860191909152840196909652938201879052838116928201929092529190921c90911660c08201527f777357bb93f63d088f18112d3dba38457aec633eb8f1341e1d418380ad328e789060e00160405180910390a1505050505050565b600c54600160301b900460ff16156126185760405163769dd35360e11b815260040160405180910390fd5b6000818152600560205260409020546001600160a01b031661264d57604051630fb532db60e11b815260040160405180910390fd5b6000818152600560205260409020600101546001600160a01b031633146126a4576000818152600560205260409081902060010154905163d084e97560e01b81526108db916001600160a01b031690600401615859565b6000818152600560205260409081902080546001600160a01b031980821633908117845560019093018054909116905591516001600160a01b039092169183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c938691611bae918591615886565b60008281526005602052604090205482906001600160a01b03168061274957604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146127745780604051636c51fda960e11b81526004016108db9190615859565b600c54600160301b900460ff161561279f5760405163769dd35360e11b815260040160405180910390fd5b600084815260056020526040902060020154606414156127d2576040516305a48e0f60e01b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b03161561280957610940565b6001600160a01b0383166000818152600460209081526040808320888452825280832080546001600160401b031916600190811790915560058352818420600201805491820181558452919092200180546001600160a01b0319169092179091555184907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e19061289a908690615859565b60405180910390a250505050565b6000816040516020016128bb91906158c2565b604051602081830303815290604052805190602001209050919050565b60008281526005602052604090205482906001600160a01b03168061291057604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b0382161461293b5780604051636c51fda960e11b81526004016108db9190615859565b600c54600160301b900460ff16156129665760405163769dd35360e11b815260040160405180910390fd5b61296f8461135e565b1561298d57604051631685ecdd60e31b815260040160405180910390fd5b6001600160a01b03831660009081526004602090815260408083208784529091529020546001600160401b03166129db5783836040516379bfd40160e01b81526004016108db929190615a14565b600084815260056020908152604080832060020180548251818502810185019093528083529192909190830182828015612a3e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612a20575b50505050509050600060018251612a559190615d53565b905060005b8251811015612b6157856001600160a01b0316838281518110612a7f57612a7f615e86565b60200260200101516001600160a01b03161415612b4f576000838381518110612aaa57612aaa615e86565b6020026020010151905080600560008a81526020019081526020016000206002018381548110612adc57612adc615e86565b600091825260208083209190910180546001600160a01b0319166001600160a01b039490941693909317909255898152600590915260409020600201805480612b2757612b27615e70565b600082815260209020810160001990810180546001600160a01b031916905501905550612b61565b80612b5981615dee565b915050612a5a565b506001600160a01b03851660009081526004602090815260408083208984529091529081902080546001600160401b03191690555186907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a790612305908890615859565b6000612bd382840184615494565b9050806000015160ff16600114612c0c57805160405163237d181f60e21b815260ff9091166004820152600160248201526044016108db565b8060a001516001600160601b03163414612c505760a08101516040516306acf13560e41b81523460048201526001600160601b0390911660248201526044016108db565b6020808201516000908152600590915260409020546001600160a01b031615612c8c576040516326afa43560e11b815260040160405180910390fd5b60005b816060015151811015612d2c5760016004600084606001518481518110612cb857612cb8615e86565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008460200151815260200190815260200160002060006101000a8154816001600160401b0302191690836001600160401b031602179055508080612d2490615dee565b915050612c8f565b50604080516060808201835260808401516001600160601b03908116835260a0850151811660208085019182526000858701818152828901805183526006845288832097518854955192516001600160401b0316600160c01b026001600160c01b03938816600160601b026001600160c01b0319909716919097161794909417169390931790945584518084018652868601516001600160a01b03908116825281860184815294880151828801908152925184526005865295909220825181549087166001600160a01b0319918216178255935160018201805491909716941693909317909455925180519192612e2b92600285019290910190614e37565b5050506080810151600a8054600090612e4e9084906001600160601b0316615cfe565b92506101000a8154816001600160601b0302191690836001600160601b031602179055508060a00151600a600c8282829054906101000a90046001600160601b0316612e9a9190615cfe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555061094081602001516008613cc590919063ffffffff16565b600e8181548110612ee657600080fd5b600091825260209091200154905081565b60008281526005602052604090205482906001600160a01b031680612f2f57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614612f5a5780604051636c51fda960e11b81526004016108db9190615859565b600c54600160301b900460ff1615612f855760405163769dd35360e11b815260040160405180910390fd5b6000848152600560205260409020600101546001600160a01b03848116911614610940576000848152600560205260409081902060010180546001600160a01b0319166001600160a01b0386161790555184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a19061289a9033908790615886565b6000818152600560205260408120548190819081906060906001600160a01b031661304557604051630fb532db60e11b815260040160405180910390fd5b60008681526006602090815260408083205460058352928190208054600290910180548351818602810186019094528084526001600160601b0380871696600160601b810490911695600160c01b9091046001600160401b0316946001600160a01b03909416939183918301828280156130e857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116130ca575b505050505090509450945094509450945091939590929450565b61310a6134a9565b6002546001600160a01b03166131335760405163c1f0c0a160e01b815260040160405180910390fd5b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613164903090600401615859565b60206040518083038186803b15801561317c57600080fd5b505afa158015613190573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131b491906152d8565b600a549091506001600160601b0316818111156131e85780826040516354ced18160e11b81526004016108db9291906158e3565b81811015610ab55760006131fc8284615d53565b60025460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb9061322f908790859060040161586d565b602060405180830381600087803b15801561324957600080fd5b505af115801561325d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061328191906152bb565b61329e57604051631f01ff1360e21b815260040160405180910390fd5b7f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b43660084826040516132cf92919061586d565b60405180910390a150505050565b6132e56134a9565b61237581613ce7565b6000806132fa84613870565b60025491935091506001600160a01b03161580159061332157506001600160601b03821615155b156133d05760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906133619086906001600160601b0387169060040161586d565b602060405180830381600087803b15801561337b57600080fd5b505af115801561338f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b391906152bb565b6133d057604051631e9acf1760e31b815260040160405180910390fd5b6000836001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114613426576040519150601f19603f3d011682016040523d82523d6000602084013e61342b565b606091505b505090508061344d5760405163950b247960e01b815260040160405180910390fd5b604080516001600160a01b03861681526001600160601b038581166020830152841681830152905186917f8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c4919081900360600190a25050505050565b6000546001600160a01b031633146134fc5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b60448201526064016108db565b565b6040805160608101825260008082526020820181905291810191909152600061352a84600001516128a8565b6000818152600d602052604090205490915060ff1661355f57604051631dfd6e1360e21b8152600481018290526024016108db565b60008185608001516040516020016135789291906158e3565b60408051601f1981840301815291815281516020928301206000818152600f909352912054909150806135be57604051631b44092560e11b815260040160405180910390fd5b845160208087015160408089015160608a015160808b015160a08c015193516135ed978a979096959101615ae3565b6040516020818303038152906040528051906020012081146136225760405163354a450b60e21b815260040160405180910390fd5b60006136318660000151613d8b565b9050806136f8578551604051631d2827a760e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163e9413d38916136859190600401615b4e565b60206040518083038186803b15801561369d57600080fd5b505afa1580156136b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d591906152d8565b9050806136f857855160405163175dadad60e01b81526108db9190600401615b4e565b600087608001518260405160200161371a929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c905060006137418983613e68565b6040805160608101825297885260208801969096529486019490945250929695505050505050565b60005a61138881101561377b57600080fd5b61138881039050846040820482031161379357600080fd5b50823b61379f57600080fd5b60008083516020850160008789f190505b9392505050565b600081156137e4576011546137dd9086908690600160201b900463ffffffff1686613ed3565b90506137fe565b6011546137fb908690869063ffffffff1686613f75565b90505b949350505050565b6000805b60125481101561386757826001600160a01b03166012828154811061383157613831615e86565b6000918252602090912001546001600160a01b031614156138555750600192915050565b8061385f81615dee565b91505061380a565b50600092915050565b6000818152600560209081526040808320815160608101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879687969495948601939192908301828280156138fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116138de575b505050919092525050506000858152600660209081526040808320815160608101835290546001600160601b03808216808452600160601b8304909116948301859052600160c01b9091046001600160401b0316928201929092529096509094509192505b8260400151518110156139d857600460008460400151838151811061398857613988615e86565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120898252909252902080546001600160401b0319169055806139d081615dee565b915050613961565b50600085815260056020526040812080546001600160a01b03199081168255600182018054909116905590613a106002830182614e9c565b5050600085815260066020526040812055613a2c60088661409a565b50600a8054859190600090613a4b9084906001600160601b0316615d6a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555082600a600c8282829054906101000a90046001600160601b0316613a939190615d6a565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050915091565b60408051602081018690526001600160a01b03851691810191909152606081018390526001600160401b03821660808201526000908190819060a00160408051601f198184030181529082905280516020918201209250613b239189918491016158e3565b60408051808303601f19018152919052805160209091012097909650945050505050565b60408051602081019091526000815281613b705750604080516020810190915260008152610f6d565b63125fa26760e31b613b828385615d92565b6001600160e01b03191614613baa57604051632923fee760e11b815260040160405180910390fd5b613bb78260048186615c9a565b8101906137b09190615332565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa82604051602401613bfd91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b600046613c41816140a6565b15613cbe5760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015613c8057600080fd5b505afa158015613c94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cb891906152d8565b91505090565b4391505090565b60006137b083836140c9565b6000610f6d825490565b60006137b08383614118565b6001600160a01b038116331415613d3a5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b60448201526064016108db565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600046613d97816140a6565b15613e5957610100836001600160401b0316613db1613c35565b613dbb9190615d53565b1180613dd75750613dca613c35565b836001600160401b031610155b15613de55750600092915050565b6040516315a03d4160e11b8152606490632b407a8290613e09908690600401615b4e565b60206040518083038186803b158015613e2157600080fd5b505afa158015613e35573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137b091906152d8565b50506001600160401b03164090565b6000613e9c8360000151846020015185604001518660600151868860a001518960c001518a60e001518b6101000151614142565b60038360200151604051602001613eb4929190615a2b565b60408051601f1981840301815291905280516020909101209392505050565b600080613f166000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061435d92505050565b905060005a613f258888615cc4565b613f2f9190615d53565b613f399085615d34565b90506000613f5263ffffffff871664e8d4a51000615d34565b905082613f5f8284615cc4565b613f699190615cc4565b98975050505050505050565b600080613f80614422565b905060008113613fa6576040516321ea67b360e11b8152600481018290526024016108db565b6000613fe86000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061435d92505050565b9050600082825a613ff98b8b615cc4565b6140039190615d53565b61400d9088615d34565b6140179190615cc4565b61402990670de0b6b3a7640000615d34565b6140339190615d20565b9050600061404c63ffffffff881664e8d4a51000615d34565b905061406381676765c793fa10079d601b1b615d53565b8211156140835760405163e80fa38160e01b815260040160405180910390fd5b61408d8183615cc4565b9998505050505050505050565b60006137b083836144ed565b600061a4b18214806140ba575062066eed82145b80610f6d57505062066eee1490565b600081815260018301602052604081205461411057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f6d565b506000610f6d565b600082600001828154811061412f5761412f615e86565b9060005260206000200154905092915050565b61414b896145e0565b6141945760405162461bcd60e51b815260206004820152601a6024820152797075626c6963206b6579206973206e6f74206f6e20637572766560301b60448201526064016108db565b61419d886145e0565b6141e15760405162461bcd60e51b815260206004820152601560248201527467616d6d61206973206e6f74206f6e20637572766560581b60448201526064016108db565b6141ea836145e0565b6142365760405162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e20637572766500000060448201526064016108db565b61423f826145e0565b61428a5760405162461bcd60e51b815260206004820152601c60248201527b73486173685769746e657373206973206e6f74206f6e20637572766560201b60448201526064016108db565b614296878a88876146a3565b6142de5760405162461bcd60e51b81526020600482015260196024820152786164647228632a706b2b732a6729213d5f755769746e65737360381b60448201526064016108db565b60006142ea8a876147b7565b905060006142fd898b878b86898961481b565b9050600061430e838d8d8a8661492e565b9050808a1461434f5760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b60448201526064016108db565b505050505050505050505050565b600046614369816140a6565b156143a857606c6001600160a01b031663c6f7de0e6040518163ffffffff1660e01b815260040160206040518083038186803b158015613e2157600080fd5b6143b18161496e565b1561386757600f602160991b016001600160a01b03166349948e0e84604051806080016040528060488152602001615ed6604891396040516020016143f79291906157af565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401613e09919061590f565b600c5460035460408051633fabe5a360e21b81529051600093600160381b900463ffffffff169283151592859283926001600160a01b03169163feaf968c9160048083019260a0929190829003018186803b15801561448057600080fd5b505afa158015614494573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b8919061568a565b5094509092508491505080156144dc57506144d38242615d53565b8463ffffffff16105b156137fe5750601054949350505050565b600081815260018301602052604081205480156145d6576000614511600183615d53565b855490915060009061452590600190615d53565b905081811461458a57600086600001828154811061454557614545615e86565b906000526020600020015490508087600001848154811061456857614568615e86565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061459b5761459b615e70565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f6d565b6000915050610f6d565b80516000906401000003d0191161462e5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420782d6f7264696e61746560701b60448201526064016108db565b60208201516401000003d0191161467c5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420792d6f7264696e61746560701b60448201526064016108db565b60208201516401000003d01990800961469c8360005b60200201516149a8565b1492915050565b60006001600160a01b0382166146e95760405162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b60448201526064016108db565b60208401516000906001161561470057601c614703565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe199182039250600091908909875160408051600080825260209091019182905292935060019161476d918691889187906158f1565b6020604051602081039080840390855afa15801561478f573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b6147bf614eba565b6147ec600184846040516020016147d893929190615838565b6040516020818303038152906040526149cc565b90505b6147f8816145e0565b610f6d57805160408051602081019290925261481491016147d8565b90506147ef565b614823614eba565b825186516401000003d01990819006910614156148825760405162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e6374000060448201526064016108db565b61488d878988614a1a565b6148d25760405162461bcd60e51b8152602060048201526016602482015275119a5c9cdd081b5d5b0818da1958dac819985a5b195960521b60448201526064016108db565b6148dd848685614a1a565b6149235760405162461bcd60e51b815260206004820152601760248201527614d958dbdb99081b5d5b0818da1958dac819985a5b1959604a1b60448201526064016108db565b613f69868484614b35565b60006002868686858760405160200161494c969594939291906157de565b60408051601f1981840301815291905280516020909101209695505050505050565b6000600a82148061498057506101a482145b8061498d575062aa37dc82145b80614999575061210582145b80610f6d57505062014a331490565b6000806401000003d01980848509840990506401000003d019600782089392505050565b6149d4614eba565b6149dd82614bf8565b81526149f26149ed826000614692565b614c33565b602082018190526002900660011415611f25576020810180516401000003d019039052919050565b600082614a575760405162461bcd60e51b815260206004820152600b60248201526a3d32b9379039b1b0b630b960a91b60448201526064016108db565b83516020850151600090614a6d90600290615e30565b15614a7957601c614a7c565b601b5b9050600070014551231950b75fc4402da1732fc9bebe19838709604080516000808252602090910191829052919250600190614abf9083908690889087906158f1565b6020604051602081039080840390855afa158015614ae1573d6000803e3d6000fd5b505050602060405103519050600086604051602001614b00919061579d565b60408051601f1981840301815291905280516020909101206001600160a01b0392831692169190911498975050505050505050565b614b3d614eba565b835160208086015185519186015160009384938493614b5e93909190614c53565b919450925090506401000003d019858209600114614bba5760405162461bcd60e51b815260206004820152601960248201527834b73b2d1036bab9ba1031329034b73b32b939b29037b3103d60391b60448201526064016108db565b60405180604001604052806401000003d01980614bd957614bd9615e5a565b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d0198110611f2557604080516020808201939093528151808203840181529082019091528051910120614c00565b6000610f6d826002614c4c6401000003d0196001615cc4565b901c614d33565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a0890506000614c9383838585614dca565b9098509050614ca488828e88614dee565b9098509050614cb588828c87614dee565b90985090506000614cc88d878b85614dee565b9098509050614cd988828686614dca565b9098509050614cea88828e89614dee565b9098509050818114614d1f576401000003d019818a0998506401000003d01982890997506401000003d0198183099650614d23565b8196505b5050505050509450945094915050565b600080614d3e614ed8565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152614d70614ef6565b60208160c0846005600019fa925082614dc05760405162461bcd60e51b81526020600482015260126024820152716269674d6f64457870206661696c7572652160701b60448201526064016108db565b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b828054828255906000526020600020908101928215614e8c579160200282015b82811115614e8c57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614e57565b50614e98929150614f14565b5090565b50805460008255906000526020600020908101906123759190614f14565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b80821115614e985760008155600101614f15565b8035611f2581615eb2565b600082601f830112614f4557600080fd5b813560206001600160401b03821115614f6057614f60615e9c565b8160051b614f6f828201615c6a565b838152828101908684018388018501891015614f8a57600080fd5b600093505b85841015614fb6578035614fa281615eb2565b835260019390930192918401918401614f8f565b50979650505050505050565b600082601f830112614fd357600080fd5b614fdb615bfd565b808385604086011115614fed57600080fd5b60005b600281101561500f578135845260209384019390910190600101614ff0565b509095945050505050565b60008083601f84011261502c57600080fd5b5081356001600160401b0381111561504357600080fd5b60208301915083602082850101111561505b57600080fd5b9250929050565b600082601f83011261507357600080fd5b81356001600160401b0381111561508c5761508c615e9c565b61509f601f8201601f1916602001615c6a565b8181528460208386010111156150b457600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156150e357600080fd5b6150eb615c25565b905081356001600160401b03808216821461510557600080fd5b8183526020840135602084015261511e60408501615184565b604084015261512f60608501615184565b606084015261514060808501614f29565b608084015260a084013591508082111561515957600080fd5b5061516684828501615062565b60a08301525092915050565b803561ffff81168114611f2557600080fd5b803563ffffffff81168114611f2557600080fd5b80516001600160501b0381168114611f2557600080fd5b80356001600160601b0381168114611f2557600080fd5b6000602082840312156151d857600080fd5b81356137b081615eb2565b600080604083850312156151f657600080fd5b823561520181615eb2565b9150602083013561521181615eb2565b809150509250929050565b6000806000806060858703121561523257600080fd5b843561523d81615eb2565b93506020850135925060408501356001600160401b0381111561525f57600080fd5b61526b8782880161501a565b95989497509550505050565b60006040828403121561528957600080fd5b8260408301111561529957600080fd5b50919050565b6000604082840312156152b157600080fd5b6137b08383614fc2565b6000602082840312156152cd57600080fd5b81516137b081615ec7565b6000602082840312156152ea57600080fd5b5051919050565b6000806020838503121561530457600080fd5b82356001600160401b0381111561531a57600080fd5b6153268582860161501a565b90969095509350505050565b60006020828403121561534457600080fd5b604051602081016001600160401b038111828210171561536657615366615e9c565b604052823561537481615ec7565b81529392505050565b6000808284036101c081121561539257600080fd5b6101a0808212156153a257600080fd5b6153aa615c47565b91506153b68686614fc2565b82526153c58660408701614fc2565b60208301526080850135604083015260a0850135606083015260c085013560808301526153f460e08601614f29565b60a083015261010061540887828801614fc2565b60c084015261541b876101408801614fc2565b60e0840152610180860135908301529092508301356001600160401b0381111561544457600080fd5b615450858286016150d1565b9150509250929050565b60006020828403121561546c57600080fd5b81356001600160401b0381111561548257600080fd5b820160c081850312156137b057600080fd5b6000602082840312156154a657600080fd5b81356001600160401b03808211156154bd57600080fd5b9083019060c082860312156154d157600080fd5b6154d9615c25565b823560ff811681146154ea57600080fd5b81526020838101359082015261550260408401614f29565b604082015260608301358281111561551957600080fd5b61552587828601614f34565b606083015250615537608084016151af565b608082015261554860a084016151af565b60a082015295945050505050565b60006020828403121561556857600080fd5b6137b082615172565b60008060008060008086880360e081121561558b57600080fd5b61559488615172565b96506155a260208901615184565b95506155b060408901615184565b94506155be60608901615184565b9350608088013592506040609f19820112156155d957600080fd5b506155e2615bfd565b6155ee60a08901615184565b81526155fc60c08901615184565b6020820152809150509295509295509295565b60006020828403121561562157600080fd5b5035919050565b6000806040838503121561563b57600080fd5b82359150602083013561521181615eb2565b6000806040838503121561566057600080fd5b50508035926020909101359150565b60006020828403121561568157600080fd5b6137b082615184565b600080600080600060a086880312156156a257600080fd5b6156ab86615198565b94506020860151935060408601519250606086015191506156ce60808701615198565b90509295509295909350565b600081518084526020808501945080840160005b838110156157135781516001600160a01b0316875295820195908201906001016156ee565b509495945050505050565b8060005b6002811015610940578151845260209384019390910190600101615722565b600081518084526020808501945080840160005b8381101561571357815187529582019590820190600101615755565b60008151808452615789816020860160208601615dc2565b601f01601f19169290920160200192915050565b6157a7818361571e565b604001919050565b600083516157c1818460208801615dc2565b8351908301906157d5818360208801615dc2565b01949350505050565b8681526157ee602082018761571e565b6157fb606082018661571e565b61580860a082018561571e565b61581560e082018461571e565b60609190911b6001600160601b0319166101208201526101340195945050505050565b838152615848602082018461571e565b606081019190915260800192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682526001600160601b0316602082015260400190565b60408101610f6d828461571e565b6020815260006137b06020830184615741565b918252602082015260400190565b93845260ff9290921660208401526040830152606082015260800190565b6020815260006137b06020830184615771565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160c0608084015261596760e08401826156da565b60808501516001600160601b0390811660a0868101919091529095015190941660c0909301929092525090919050565b61ffff93841681529183166020830152909116604082015260600190565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b81811015615a06578451835293830193918301916001016159ea565b509098975050505050505050565b9182526001600160a01b0316602082015260400190565b828152606081016137b0602083018461571e565b8281526040602082015260006137fe6040830184615741565b86815285602082015261ffff85166040820152600063ffffffff808616606084015280851660808401525060c060a0830152613f6960c0830184615771565b878152602081018790526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c0820181905260009061408d90830184615771565b8781526001600160401b03871660208201526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c0820181905260009061408d90830184615771565b63ffffffff92831681529116602082015260400190565b6001600160401b0391909116815260200190565b6001600160601b038681168252851660208201526001600160401b03841660408201526001600160a01b038316606082015260a060808201819052600090615bac908301846156da565b979650505050505050565b6000808335601e19843603018112615bce57600080fd5b8301803591506001600160401b03821115615be857600080fd5b60200191503681900382131561505b57600080fd5b604080519081016001600160401b0381118282101715615c1f57615c1f615e9c565b60405290565b60405160c081016001600160401b0381118282101715615c1f57615c1f615e9c565b60405161012081016001600160401b0381118282101715615c1f57615c1f615e9c565b604051601f8201601f191681016001600160401b0381118282101715615c9257615c92615e9c565b604052919050565b60008085851115615caa57600080fd5b83861115615cb757600080fd5b5050820193919092039150565b60008219821115615cd757615cd7615e44565b500190565b60006001600160401b038281168482168083038211156157d5576157d5615e44565b60006001600160601b038281168482168083038211156157d5576157d5615e44565b600082615d2f57615d2f615e5a565b500490565b6000816000190483118215151615615d4e57615d4e615e44565b500290565b600082821015615d6557615d65615e44565b500390565b60006001600160601b0383811690831681811015615d8a57615d8a615e44565b039392505050565b6001600160e01b03198135818116916004851015615dba5780818660040360031b1b83161692505b505092915050565b60005b83811015615ddd578181015183820152602001615dc5565b838111156109405750506000910152565b6000600019821415615e0257615e02615e44565b5060010190565b60006001600160401b0382811680821415615e2657615e26615e44565b6001019392505050565b600082615e3f57615e3f615e5a565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461237557600080fd5b801515811461237557600080fdfe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000806000a", } var VRFCoordinatorV2PlusUpgradedVersionABI = VRFCoordinatorV2PlusUpgradedVersionMetaData.ABI @@ -768,30 +768,6 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionT return _VRFCoordinatorV2PlusUpgradedVersion.Contract.OnTokenTransfer(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, arg0, amount, data) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) OracleWithdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "oracleWithdraw", recipient, amount) -} - -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) OracleWithdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.OracleWithdraw(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient, amount) -} - -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) OracleWithdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.OracleWithdraw(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient, amount) -} - -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) OracleWithdrawNative(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "oracleWithdrawNative", recipient, amount) -} - -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) OracleWithdrawNative(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.OracleWithdrawNative(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient, amount) -} - -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) OracleWithdrawNative(recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.OracleWithdrawNative(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient, amount) -} - func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) OwnerCancelSubscription(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "ownerCancelSubscription", subId) } @@ -840,16 +816,16 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionT return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterMigratableCoordinator(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, target) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) RegisterProvingKey(opts *bind.TransactOpts, oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "registerProvingKey", oracle, publicProvingKey) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "registerProvingKey", publicProvingKey) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) RegisterProvingKey(oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, oracle, publicProvingKey) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) RegisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, publicProvingKey) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) RegisterProvingKey(oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, oracle, publicProvingKey) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) RegisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, publicProvingKey) } func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { @@ -924,6 +900,30 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionT return _VRFCoordinatorV2PlusUpgradedVersion.Contract.TransferOwnership(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, to) } +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "withdraw", recipient) +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) Withdraw(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.Withdraw(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient) +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) Withdraw(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.Withdraw(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient) +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "withdrawNative", recipient) +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) WithdrawNative(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.WithdrawNative(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient) +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) WithdrawNative(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.WithdrawNative(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, recipient) +} + type VRFCoordinatorV2PlusUpgradedVersionConfigSetIterator struct { Event *VRFCoordinatorV2PlusUpgradedVersionConfigSet @@ -1851,32 +1851,21 @@ func (it *VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegisteredIterator) Close type VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered struct { KeyHash [32]byte - Oracle common.Address Raw types.Log } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) FilterProvingKeyRegistered(opts *bind.FilterOpts, oracle []common.Address) (*VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegisteredIterator, error) { +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) FilterProvingKeyRegistered(opts *bind.FilterOpts) (*VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegisteredIterator, error) { - var oracleRule []interface{} - for _, oracleItem := range oracle { - oracleRule = append(oracleRule, oracleItem) - } - - logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.FilterLogs(opts, "ProvingKeyRegistered", oracleRule) + logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.FilterLogs(opts, "ProvingKeyRegistered") if err != nil { return nil, err } return &VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegisteredIterator{contract: _VRFCoordinatorV2PlusUpgradedVersion.contract, event: "ProvingKeyRegistered", logs: logs, sub: sub}, nil } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered, oracle []common.Address) (event.Subscription, error) { - - var oracleRule []interface{} - for _, oracleItem := range oracle { - oracleRule = append(oracleRule, oracleItem) - } +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered) (event.Subscription, error) { - logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.WatchLogs(opts, "ProvingKeyRegistered", oracleRule) + logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.WatchLogs(opts, "ProvingKeyRegistered") if err != nil { return nil, err } @@ -3331,7 +3320,7 @@ func (VRFCoordinatorV2PlusUpgradedVersionOwnershipTransferred) Topic() common.Ha } func (VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered) Topic() common.Hash { - return common.HexToHash("0xe729ae16526293f74ade739043022254f1489f616295a25bf72dfb4511ed73b8") + return common.HexToHash("0xc9583fd3afa3d7f16eb0b88d0268e7d05c09bafa4b21e092cbd1320e1bc8089d") } func (VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled) Topic() common.Hash { @@ -3441,10 +3430,6 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) - OracleWithdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) - - OracleWithdrawNative(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) - OwnerCancelSubscription(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) RecoverFunds(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -3453,7 +3438,7 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) - RegisterProvingKey(opts *bind.TransactOpts, oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) + RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) @@ -3467,6 +3452,10 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) + + WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) + FilterConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorV2PlusUpgradedVersionConfigSetIterator, error) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionConfigSet) (event.Subscription, error) @@ -3509,9 +3498,9 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorV2PlusUpgradedVersionOwnershipTransferred, error) - FilterProvingKeyRegistered(opts *bind.FilterOpts, oracle []common.Address) (*VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegisteredIterator, error) + FilterProvingKeyRegistered(opts *bind.FilterOpts) (*VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegisteredIterator, error) - WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered, oracle []common.Address) (event.Subscription, error) + WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered) (event.Subscription, error) ParseProvingKeyRegistered(log types.Log) (*VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered, 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 5e9dcfc3326..dcc0a4dea37 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 @@ -1,4 +1,4 @@ -GETH_VERSION: 1.12.0 +GETH_VERSION: 1.12.2 aggregator_v2v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.bin 95e8814b408bb05bf21742ef580d98698b7db6a9bac6a35c3de12b23aec4ee28 aggregator_v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.bin 351b55d3b0f04af67db6dfb5c92f1c64479400ca1fec77afc20bc0ce65cb49ab authorized_forwarder: ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin 8ea76c883d460f8353a45a493f2aebeb5a2d9a7b4619d1bc4fff5fb590bb3e10 @@ -38,7 +38,7 @@ keeper_registry_wrapper1_3: ../../contracts/solc/v0.8.6/KeeperRegistry1_3/Keeper keeper_registry_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.bin c32dea7d5ef66b7c58ddc84ddf69aa44df1b3ae8601fbc271c95be4ff5853056 keeper_registry_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.bin 604e4a0cd980c713929b523b999462a3aa0ed06f96ff563a4c8566cf59c8445b keepers_vrf_consumer: ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.abi ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.bin fa75572e689c9e84705c63e8dbe1b7b8aa1a8fe82d66356c4873d024bb9166e8 -log_emitter: ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.bin 244ba13730c036de0b02beef4e3d9c9a96946ce353c27f366baecc7f5be5a6fd +log_emitter: ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.bin 4b129ab93432c95ff9143f0631323e189887668889e0b36ccccf18a571e41ccf log_triggered_streams_lookup_wrapper: ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.bin f8da43a927c1a66238a9f4fd5d5dd7e280e361daa0444da1f7f79498ace901e1 log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.bin 42426bbb83f96dfbe55fc576d6c65020eaeed690e2289cf99b0c4aa810a5f4ec mock_aggregator_proxy: ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.bin b16c108f3dd384c342ddff5e94da7c0a8d39d1be5e3d8f2cf61ecc7f0e50ff42 @@ -50,7 +50,7 @@ operator_factory: ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.a operator_wrapper: ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin c5e1db81070d940a82ef100b0bce38e055593cbeebbc73abf9d45c30d6020cd2 oracle_wrapper: ../../contracts/solc/v0.6/Oracle/Oracle.abi ../../contracts/solc/v0.6/Oracle/Oracle.bin 7af2fbac22a6e8c2847e8e685a5400cac5101d72ddf5365213beb79e4dede43a perform_data_checker_wrapper: ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73 -simple_log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.abi ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.bin 0a7a0cc4da7dc2a3d0a0c36c746b1adc044af5cad1838367356a0604f3255a01 +simple_log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.abi ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.bin a2532ca73e227f846be39b52fa63cfa9d088116c3cfc311d972fe8db886fa915 solidity_vrf_consumer_interface: ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.bin ecc99378aa798014de9db42b2eb81320778b0663dbe208008dad75ccdc1d4366 solidity_vrf_consumer_interface_v08: ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.bin b14f9136b15e3dc9d6154d5700f3ed4cf88ddc4f70f20c3bb57fc46050904c8f solidity_vrf_coordinator_interface: ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.bin a23d3c395156804788c7f6fbda2994e8f7184304c0f0c9f2c4ddeaf073d346d2 @@ -75,7 +75,7 @@ vrf_consumer_v2_plus_upgradeable_example: ../../contracts/solc/v0.8.6/VRFConsume vrf_consumer_v2_upgradeable_example: ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.bin f1790a9a2f2a04c730593e483459709cb89e897f8a19d7a3ac0cfe6a97265e6e vrf_coordinator_mock: ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.abi ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.bin 5c495cf8df1f46d8736b9150cdf174cce358cb8352f60f0d5bb9581e23920501 vrf_coordinator_v2: ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.bin 295f35ce282060317dfd01f45959f5a2b05ba26913e422fbd4fb6bf90b107006 -vrf_coordinator_v2_5: ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.bin b0e7c42a30b36d9d31fa9a3f26bad7937152e3dddee5bd8dd3d121390c879ab6 +vrf_coordinator_v2_5: ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.bin bcad64e1b41278998c94867370fd9c4809b1376ccc004955bc7ed33fe716408c vrf_coordinator_v2_plus_v2_example: ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.bin 4a5b86701983b1b65f0a8dfa116b3f6d75f8f706fa274004b57bdf5992e4cec3 vrf_coordinator_v2plus_interface: ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.abi ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.bin 834a2ce0e83276372a0e1446593fd89798f4cf6dc95d4be0113e99fadf61558b vrf_external_sub_owner_example: ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.bin 14f888eb313930b50233a6f01ea31eba0206b7f41a41f6311670da8bb8a26963 @@ -93,7 +93,7 @@ vrf_v2_consumer_wrapper: ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer vrf_v2plus_load_test_with_metrics: ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.bin 0a89cb7ed9dfb42f91e559b03dc351ccdbe14d281a7ab71c63bd3f47eeed7711 vrf_v2plus_single_consumer: ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.bin 6226d05afa1664033b182bfbdde11d5dfb1d4c8e3eb0bd0448c8bfb76f5b96e4 vrf_v2plus_sub_owner: ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.bin 7541f986571b8a5671a256edc27ae9b8df9bcdff45ac3b96e5609bbfcc320e4e -vrf_v2plus_upgraded_version: ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.bin c0793d86fb6e45342c4424184fe241c16da960c0b4de76816364b933344d0756 +vrf_v2plus_upgraded_version: ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.bin 3bcd359eddf2bc861dda86f9bb10b78bac1e0370badd15f67ae17b35c5d228d4 vrfv2_proxy_admin: ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.abi ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.bin 402b1103087ffe1aa598854a8f8b38f8cd3de2e3aaa86369e28017a9157f4980 vrfv2_reverting_example: ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.bin 1ae46f80351d428bd85ba58b9041b2a608a1845300d79a8fed83edf96606de87 vrfv2_transparent_upgradeable_proxy: ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.abi ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.bin fe1a8e6852fbd06d91f64315c5cede86d340891f5b5cc981fb5b86563f7eac3f diff --git a/core/gethwrappers/go_generate_test.go b/core/gethwrappers/go_generate_test.go index 9ded44c0785..e0779c306c4 100644 --- a/core/gethwrappers/go_generate_test.go +++ b/core/gethwrappers/go_generate_test.go @@ -14,6 +14,7 @@ import ( gethParams "github.com/ethereum/go-ethereum/params" "github.com/fatih/color" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" @@ -112,7 +113,7 @@ func init() { for db.Scan() { line := strings.Fields(db.Text()) if stripTrailingColon(line[0], "") != "GETH_VERSION" { - if os.IsNotExist(utils.JustError(os.Stat(line[1]))) { + if os.IsNotExist(cutils.JustError(os.Stat(line[1]))) { solidityArtifactsMissing = append(solidityArtifactsMissing, line[1]) } } diff --git a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 293defcfbe0..29f0deb7b2c 100644 --- a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ -GETH_VERSION: 1.12.0 +GETH_VERSION: 1.12.2 errored_verifier: ../../../contracts/solc/v0.8.16/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.16/ErroredVerifier/ErroredVerifier.bin 510d18a58bfda646be35e46491baf73041eb333a349615465b20e2b5b41c5f73 exposed_verifier: ../../../contracts/solc/v0.8.16/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.16/ExposedVerifier/ExposedVerifier.bin 6932cea8f2738e874d3ec9e1a4231d2421704030c071d9e15dd2f7f08482c246 fee_manager: ../../../contracts/solc/v0.8.16/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.16/FeeManager/FeeManager.bin 1b852df75bfabcc2b57539e84309cd57f9e693a2bb6b25a50e4a6101ccf32c49 diff --git a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt index af907ce85eb..ff9bfa2fea4 100644 --- a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ -GETH_VERSION: 1.12.0 +GETH_VERSION: 1.12.2 burn_mint_erc677: ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.bin 405c9016171e614b17e10588653ef8d33dcea21dd569c3fddc596a46fcff68a3 erc20: ../../../contracts/solc/v0.8.19/ERC20/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20/ERC20.bin 5b1a93d9b24f250e49a730c96335a8113c3f7010365cba578f313b483001d4fc link_token: ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.bin c0ef9b507103aae541ebc31d87d051c2764ba9d843076b30ec505d37cdfffaba diff --git a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt index a6d32bf0a85..cded1f0c5e5 100644 --- a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ -GETH_VERSION: 1.12.0 +GETH_VERSION: 1.12.2 entry_point: ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.bin 2cb4bb2ba3efa8df3dfb0a57eb3727d17b68fe202682024fa7cfb4faf026833e greeter: ../../../contracts/solc/v0.8.15/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c greeter_wrapper: ../../../contracts/solc/v0.8.15/Greeter/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index c5e1fc5e4d0..dcd16b8e59c 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -51,6 +51,7 @@ import ( httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/cmd" @@ -310,8 +311,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn auditLogger = audit.NoopLogger } - var eventBroadcaster pg.EventBroadcaster = pg.NewNullEventBroadcaster() - url := cfg.Database().URL() db, err := pg.NewConnection(url.String(), cfg.Database().Dialect(), cfg.Database()) require.NoError(t, err) @@ -328,8 +327,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn ethClient = dep case webhook.ExternalInitiatorManager: externalInitiatorManager = dep - case pg.EventBroadcaster: - eventBroadcaster = dep default: switch flag { case UseRealExternalInitiatorManager: @@ -341,7 +338,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn keyStore := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database()) - mailMon := mailbox.NewMonitor(cfg.AppID().String()) + mailMon := mailbox.NewMonitor(cfg.AppID().String(), lggr.Named("Mailbox")) loopRegistry := plugins.NewLoopRegistry(lggr, nil) mercuryPool := wsrpc.NewPool(lggr, cache.Config{ @@ -359,10 +356,9 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn evmOpts := chainlink.EVMFactoryConfig{ ChainOpts: legacyevm.ChainOpts{ - AppConfig: cfg, - EventBroadcaster: eventBroadcaster, - MailMon: mailMon, - DB: db, + AppConfig: cfg, + MailMon: mailMon, + DB: db, }, CSAETHKeystore: keyStore, } @@ -415,7 +411,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn c := clhttptest.NewTestLocalOnlyHTTPClient() appInstance, err := chainlink.NewApplication(chainlink.ApplicationOpts{ Config: cfg, - EventBroadcaster: eventBroadcaster, MailMon: mailMon, SqlxDB: db, KeyStore: keyStore, @@ -504,14 +499,14 @@ func NewEthMocksWithTransactionsOnBlocksAssertions(t testing.TB) *evmclimocks.Cl if len(elems) > 0 { elems[0].Result = &evmtypes.Block{ Number: 42, - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), Transactions: LegacyTransactionsFromGasPrices(9001, 9002), } } if len(elems) > 1 { elems[1].Result = &evmtypes.Block{ Number: 41, - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), Transactions: LegacyTransactionsFromGasPrices(9003, 9004), } } @@ -974,16 +969,14 @@ func AssertPipelineRunsStays(t testing.TB, pipelineSpecID int32, db *sqlx.DB, wa } // AssertEthTxAttemptCountStays asserts that the number of tx attempts remains at the provided value -func AssertEthTxAttemptCountStays(t testing.TB, db *sqlx.DB, want int) []int64 { +func AssertEthTxAttemptCountStays(t testing.TB, txStore txmgr.TestEvmTxStore, want int) []int64 { g := gomega.NewWithT(t) var txaIds []int64 - var err error - g.Consistently(func() []int64 { - txaIds = make([]int64, 0) - err = db.Select(&txaIds, `SELECT ID FROM evm.tx_attempts ORDER BY id ASC`) + g.Consistently(func() []txmgr.TxAttempt { + attempts, err := txStore.GetAllTxAttempts(testutils.Context(t)) assert.NoError(t, err) - return txaIds + return attempts }, AssertNoActionTimeout, DBPollingInterval).Should(gomega.HaveLen(want)) return txaIds } @@ -994,13 +987,13 @@ func Head(val interface{}) *evmtypes.Head { time := uint64(0) switch t := val.(type) { case int: - h = evmtypes.NewHead(big.NewInt(int64(t)), utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(int64(t)), evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(&FixtureChainID)) case uint64: - h = evmtypes.NewHead(big.NewInt(int64(t)), utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(int64(t)), evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(&FixtureChainID)) case int64: - h = evmtypes.NewHead(big.NewInt(t), utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(t), evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(&FixtureChainID)) case *big.Int: - h = evmtypes.NewHead(t, utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) + h = evmtypes.NewHead(t, evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(&FixtureChainID)) default: panic(fmt.Sprintf("Could not convert %v of type %T to Head", val, val)) } @@ -1010,7 +1003,7 @@ func Head(val interface{}) *evmtypes.Head { func HeadWithHash(n int64, hash common.Hash) *evmtypes.Head { var h evmtypes.Head time := uint64(0) - h = evmtypes.NewHead(big.NewInt(n), hash, utils.NewHash(), time, ubig.New(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(n), hash, evmutils.NewHash(), time, ubig.New(&FixtureChainID)) return &h } @@ -1387,7 +1380,7 @@ func (b *Blocks) NewHead(number uint64) *evmtypes.Head { } head := &evmtypes.Head{ Number: parent.Number + 1, - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), ParentHash: parent.Hash, Parent: parent, Timestamp: time.Unix(parent.Number+1, 0), @@ -1427,7 +1420,7 @@ func NewBlocks(t *testing.T, numHashes int) *Blocks { hashes := make([]common.Hash, 0) heads := make(map[int64]*evmtypes.Head) for i := int64(0); i < int64(numHashes); i++ { - hash := utils.NewHash() + hash := evmutils.NewHash() hashes = append(hashes, hash) heads[i] = &evmtypes.Head{Hash: hash, Number: i, Timestamp: time.Unix(i, 0), EVMChainID: ubig.New(&FixtureChainID)} diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index bece916ecc5..804dbe2d088 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -32,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -146,6 +147,18 @@ func NewEthTx(fromAddress common.Address) txmgr.Tx { } } +func NewLegacyTransaction(nonce uint64, to common.Address, value *big.Int, gasLimit uint32, gasPrice *big.Int, data []byte) *types.Transaction { + tx := types.LegacyTx{ + Nonce: nonce, + To: &to, + Value: value, + Gas: uint64(gasLimit), + GasPrice: gasPrice, + Data: data, + } + return types.NewTx(&tx) +} + func MustInsertUnconfirmedEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, opts ...interface{}) txmgr.Tx { broadcastAt := time.Now() chainID := &FixtureChainID @@ -173,7 +186,7 @@ func MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t *testing.T, txStore etx := MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) attempt := NewLegacyEthTxAttempt(t, etx.ID) - tx := types.NewTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + tx := NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) rlp := new(bytes.Buffer) require.NoError(t, tx.EncodeRLP(rlp)) attempt.SignedRawTx = rlp.Bytes() @@ -213,7 +226,7 @@ func NewLegacyEthTxAttempt(t *testing.T, etxID int64) txmgr.TxAttempt { // Just a random signed raw tx that decodes correctly // Ignore all actual values SignedRawTx: hexutil.MustDecode("0xf889808504a817c8008307a12094000000000000000000000000000000000000000080a400000000000000000000000000000000000000000000000000000000000000000000000025a0838fe165906e2547b9a052c099df08ec891813fea4fcdb3c555362285eb399c5a070db99322490eb8a0f2270be6eca6e3aedbc49ff57ef939cf2774f12d08aa85e"), - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), State: txmgrtypes.TxAttemptInProgress, } } @@ -231,7 +244,7 @@ func NewDynamicFeeEthTxAttempt(t *testing.T, etxID int64) txmgr.TxAttempt { // Just a random signed raw tx that decodes correctly // Ignore all actual values SignedRawTx: hexutil.MustDecode("0xf889808504a817c8008307a12094000000000000000000000000000000000000000080a400000000000000000000000000000000000000000000000000000000000000000000000025a0838fe165906e2547b9a052c099df08ec891813fea4fcdb3c555362285eb399c5a070db99322490eb8a0f2270be6eca6e3aedbc49ff57ef939cf2774f12d08aa85e"), - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), State: txmgrtypes.TxAttemptInProgress, ChainSpecificFeeLimit: 42, } @@ -300,7 +313,7 @@ func MustGenerateRandomKeyState(_ testing.TB) ethkey.State { } func MustInsertHead(t *testing.T, db *sqlx.DB, cfg pg.QConfig, number int64) evmtypes.Head { - h := evmtypes.NewHead(big.NewInt(number), utils.NewHash(), utils.NewHash(), 0, ubig.New(&FixtureChainID)) + h := evmtypes.NewHead(big.NewInt(number), evmutils.NewHash(), evmutils.NewHash(), 0, ubig.New(&FixtureChainID)) horm := headtracker.NewORM(db, logger.TestLogger(t), cfg, FixtureChainID) err := horm.IdempotentInsertHead(testutils.Context(t), &h) @@ -480,23 +493,23 @@ func RandomLog(t *testing.T) types.Log { topics := make([]common.Hash, 4) for i := range topics { - topics[i] = utils.NewHash() + topics[i] = evmutils.NewHash() } return types.Log{ Address: testutils.NewAddress(), - BlockHash: utils.NewHash(), + BlockHash: evmutils.NewHash(), BlockNumber: uint64(mathrand.Intn(9999999)), Index: uint(mathrand.Intn(9999999)), Data: MustRandomBytes(t, 512), - Topics: []common.Hash{utils.NewHash(), utils.NewHash(), utils.NewHash(), utils.NewHash()}, + Topics: []common.Hash{evmutils.NewHash(), evmutils.NewHash(), evmutils.NewHash(), evmutils.NewHash()}, } } func RawNewRoundLog(t *testing.T, contractAddr common.Address, blockHash common.Hash, blockNumber uint64, logIndex uint, removed bool) types.Log { t.Helper() topic := (flux_aggregator_wrapper.FluxAggregatorNewRound{}).Topic() - topics := []common.Hash{topic, utils.NewHash(), utils.NewHash()} + topics := []common.Hash{topic, evmutils.NewHash(), evmutils.NewHash()} return RawNewRoundLogWithTopics(t, contractAddr, blockHash, blockNumber, logIndex, removed, topics) } diff --git a/core/internal/cltest/heavyweight/orm.go b/core/internal/cltest/heavyweight/orm.go index 5df28a49778..f49a94be05b 100644 --- a/core/internal/cltest/heavyweight/orm.go +++ b/core/internal/cltest/heavyweight/orm.go @@ -1,13 +1,8 @@ -package heavyweight - -// The heavyweight package contains cltest items that are costly and you should +// Package heavyweight contains test helpers that are costly and you should // think **real carefully** before using in your tests. +package heavyweight import ( - "database/sql" - "errors" - "fmt" - "net/url" "os" "path" "runtime" @@ -20,41 +15,45 @@ import ( "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink/v2/core/cmd" "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" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/internal/testdb" ) // FullTestDBV2 creates a pristine DB which runs in a separate database than the normal // unit tests, so you can do things like use other Postgres connection types with it. func FullTestDBV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { - return prepareFullTestDBV2(t, false, true, overrideFn) + return KindFixtures.PrepareDB(t, overrideFn) } // FullTestDBNoFixturesV2 is the same as FullTestDB, but it does not load fixtures. func FullTestDBNoFixturesV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { - return prepareFullTestDBV2(t, false, false, overrideFn) + return KindTemplate.PrepareDB(t, overrideFn) } // FullTestDBEmptyV2 creates an empty DB (without migrations). func FullTestDBEmptyV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { - return prepareFullTestDBV2(t, true, false, overrideFn) + return KindEmpty.PrepareDB(t, overrideFn) } func generateName() string { return strings.ReplaceAll(uuid.New().String(), "-", "") } -func prepareFullTestDBV2(t testing.TB, empty bool, loadFixtures bool, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { - testutils.SkipShort(t, "FullTestDB") +type Kind int - if empty && loadFixtures { - t.Fatal("could not load fixtures into an empty DB") - } +const ( + KindEmpty Kind = iota + KindTemplate + KindFixtures +) + +func (c Kind) PrepareDB(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { + testutils.SkipShort(t, "FullTestDB") gcfg := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Database.Dialect = dialects.Postgres @@ -64,7 +63,7 @@ func prepareFullTestDBV2(t testing.TB, empty bool, loadFixtures bool, overrideFn }) require.NoError(t, os.MkdirAll(gcfg.RootDir(), 0700)) - migrationTestDBURL, err := dropAndCreateThrowawayTestDB(gcfg.Database().URL(), generateName(), empty) + migrationTestDBURL, err := testdb.CreateOrReplace(gcfg.Database().URL(), generateName(), c != KindEmpty) require.NoError(t, err) db, err := pg.NewConnection(migrationTestDBURL, dialects.Postgres, gcfg.Database()) require.NoError(t, err) @@ -81,7 +80,7 @@ func prepareFullTestDBV2(t testing.TB, empty bool, loadFixtures bool, overrideFn } }) - if loadFixtures { + if c == KindFixtures { _, filename, _, ok := runtime.Caller(1) if !ok { t.Fatal("could not get runtime.Caller(1)") @@ -95,39 +94,3 @@ func prepareFullTestDBV2(t testing.TB, empty bool, loadFixtures bool, overrideFn return gcfg, db } - -func dropAndCreateThrowawayTestDB(parsed url.URL, postfix string, empty bool) (string, error) { - if parsed.Path == "" { - return "", errors.New("path missing from database URL") - } - - // Match the naming schema that our dangling DB cleanup methods expect - dbname := cmd.TestDBNamePrefix + postfix - if l := len(dbname); l > 63 { - return "", fmt.Errorf("dbname %v too long (%d), max is 63 bytes. Try a shorter postfix", dbname, l) - } - // Cannot drop test database if we are connected to it, so we must connect - // to a different one. 'postgres' should be present on all postgres installations - parsed.Path = "/postgres" - db, err := sql.Open(string(dialects.Postgres), parsed.String()) - if err != nil { - return "", fmt.Errorf("In order to drop the test database, we need to connect to a separate database"+ - " called 'postgres'. But we are unable to open 'postgres' database: %+v\n", err) - } - defer db.Close() - - _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", dbname)) - if err != nil { - return "", fmt.Errorf("unable to drop postgres migrations test database: %v", err) - } - if empty { - _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbname)) - } else { - _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s WITH TEMPLATE %s", dbname, cmd.PristineDBName)) - } - if err != nil { - return "", fmt.Errorf("unable to create postgres test database with name '%s': %v", dbname, err) - } - parsed.Path = fmt.Sprintf("/%s", dbname) - return parsed.String(), nil -} diff --git a/core/internal/cltest/simulated_backend.go b/core/internal/cltest/simulated_backend.go index 0aecc7f8324..cde060d7f4a 100644 --- a/core/internal/cltest/simulated_backend.go +++ b/core/internal/cltest/simulated_backend.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/core" - "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -16,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) func NewSimulatedBackend(t *testing.T, alloc core.GenesisAlloc, gasLimit uint32) *backends.SimulatedBackend { @@ -41,9 +39,8 @@ func NewApplicationWithConfigV2OnSimulatedBlockchain( require.Zero(t, evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()).Cmp(testutils.SimulatedChainID)) chainID := big.New(testutils.SimulatedChainID) client := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) - eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New()) - flagsAndDeps = append(flagsAndDeps, client, eventBroadcaster, chainID) + flagsAndDeps = append(flagsAndDeps, client, chainID) // app.Stop() will call client.Close on the simulated backend app := NewApplicationWithConfig(t, cfg, flagsAndDeps...) @@ -66,9 +63,8 @@ func NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain( require.Zero(t, evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()).Cmp(testutils.SimulatedChainID)) chainID := big.New(testutils.SimulatedChainID) client := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) - eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New()) - flagsAndDeps = append(flagsAndDeps, client, eventBroadcaster, chainID) + flagsAndDeps = append(flagsAndDeps, client, chainID) // app.Stop() will call client.Close on the simulated backend return NewApplicationWithConfigAndKey(t, cfg, flagsAndDeps...) diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index f115a3f8858..a0588f6abdc 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -21,7 +21,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/rpc" "github.com/google/uuid" @@ -46,6 +45,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/consumer_wrapper" @@ -380,7 +380,7 @@ func TestIntegration_DirectRequest(t *testing.T) { // Fund node account with ETH. n, err := b.NonceAt(testutils.Context(t), operatorContracts.user.From, nil) require.NoError(t, err) - tx = types.NewTransaction(n, sendingKeys[0].Address, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) + tx = cltest.NewLegacyTransaction(n, sendingKeys[0].Address, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) signedTx, err := operatorContracts.user.Signer(operatorContracts.user.From, tx) require.NoError(t, err) err = b.SendTransaction(testutils.Context(t), signedTx) @@ -479,7 +479,7 @@ func setupAppForEthTx(t *testing.T, operatorContracts OperatorContracts) (app *c // Fund node account with ETH. n, err := b.NonceAt(testutils.Context(t), operatorContracts.user.From, nil) require.NoError(t, err) - tx := types.NewTransaction(n, sendingKeys[0].Address, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) + tx := cltest.NewLegacyTransaction(n, sendingKeys[0].Address, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) signedTx, err := operatorContracts.user.Signer(operatorContracts.user.From, tx) require.NoError(t, err) err = b.SendTransaction(testutils.Context(t), signedTx) @@ -709,7 +709,7 @@ func setupNode(t *testing.T, owner *bind.TransactOpts, portV2 int, n, err := b.NonceAt(testutils.Context(t), owner.From, nil) require.NoError(t, err) - tx := types.NewTransaction(n, transmitter, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) + tx := cltest.NewLegacyTransaction(n, transmitter, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) signedTx, err := owner.Signer(owner.From, tx) require.NoError(t, err) err = b.SendTransaction(testutils.Context(t), signedTx) @@ -751,7 +751,7 @@ func setupForwarderEnabledNode(t *testing.T, owner *bind.TransactOpts, portV2 in n, err := b.NonceAt(testutils.Context(t), owner.From, nil) require.NoError(t, err) - tx := types.NewTransaction(n, transmitter, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) + tx := cltest.NewLegacyTransaction(n, transmitter, assets.Ether(100).ToInt(), 21000, big.NewInt(1000000000), nil) signedTx, err := owner.Signer(owner.From, tx) require.NoError(t, err) err = b.SendTransaction(testutils.Context(t), signedTx) @@ -880,7 +880,7 @@ isBootstrapPeer = true // Raising flags to initiate hibernation _, err = flagsContract.RaiseFlag(owner, ocrContractAddress) require.NoError(t, err, "failed to raise flag for ocrContractAddress") - _, err = flagsContract.RaiseFlag(owner, utils.ZeroAddress) + _, err = flagsContract.RaiseFlag(owner, evmutils.ZeroAddress) require.NoError(t, err, "failed to raise flag for ZeroAddress") b.Commit() @@ -1106,7 +1106,7 @@ isBootstrapPeer = true // Raising flags to initiate hibernation _, err = flagsContract.RaiseFlag(owner, ocrContractAddress) require.NoError(t, err, "failed to raise flag for ocrContractAddress") - _, err = flagsContract.RaiseFlag(owner, utils.ZeroAddress) + _, err = flagsContract.RaiseFlag(owner, evmutils.ZeroAddress) require.NoError(t, err, "failed to raise flag for ZeroAddress") b.Commit() @@ -1264,22 +1264,22 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { b41 := evmtypes.Block{ Number: 41, - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), Transactions: cltest.LegacyTransactionsFromGasPrices(41_000_000_000, 41_500_000_000), } b42 := evmtypes.Block{ Number: 42, - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), Transactions: cltest.LegacyTransactionsFromGasPrices(44_000_000_000, 45_000_000_000), } b43 := evmtypes.Block{ Number: 43, - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), Transactions: cltest.LegacyTransactionsFromGasPrices(48_000_000_000, 49_000_000_000, 31_000_000_000), } evmChainID := ubig.New(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs())) - h40 := evmtypes.Head{Hash: utils.NewHash(), Number: 40, EVMChainID: evmChainID} + h40 := evmtypes.Head{Hash: evmutils.NewHash(), Number: 40, EVMChainID: evmChainID} h41 := evmtypes.Head{Hash: b41.Hash, ParentHash: h40.Hash, Number: 41, EVMChainID: evmChainID} h42 := evmtypes.Head{Hash: b42.Hash, ParentHash: h41.Hash, Number: 42, EVMChainID: evmChainID} diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index 70d4b0d79fd..e3b6c1a24d1 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -143,7 +143,7 @@ func setupNodeOCR2( n, err := b.NonceAt(testutils.Context(t), owner.From, nil) require.NoError(t, err) - tx := types.NewTransaction( + tx := cltest.NewLegacyTransaction( n, transmitter, assets.Ether(1).ToInt(), 21000, diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index eb1a03530ae..cc56c3c9e9b 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains" @@ -36,7 +37,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "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" ) @@ -81,15 +81,15 @@ func NewChainRelayExtenders(t testing.TB, testopts TestChainOpts) *evmrelay.Chai func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainRelayExtenderConfig { require.NotNil(t, testopts.KeyStore) + lggr := logger.TestLogger(t) opts := legacyevm.ChainRelayExtenderConfig{ - Logger: logger.TestLogger(t), + Logger: lggr, KeyStore: testopts.KeyStore, ChainOpts: legacyevm.ChainOpts{ - AppConfig: testopts.GeneralConfig, - EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: testopts.MailMon, - GasEstimator: testopts.GasEstimator, - DB: testopts.DB, + AppConfig: testopts.GeneralConfig, + MailMon: testopts.MailMon, + GasEstimator: testopts.GasEstimator, + DB: testopts.DB, }, } opts.GenEthClient = func(*big.Int) evmclient.Client { @@ -119,7 +119,7 @@ func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainR } } if opts.MailMon == nil { - opts.MailMon = servicetest.Run(t, mailbox.NewMonitor(t.Name())) + opts.MailMon = servicetest.Run(t, mailboxtest.NewMonitor(t)) } if testopts.GasEstimator != nil { opts.GenGasEstimator = func(*big.Int) gas.EvmFeeEstimator { diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index 01024b39c37..686483f2d41 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "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" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func NewQConfig(logSQL bool) pg.QConfig { diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index 6ffd873d092..81c09b1c362 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -425,15 +425,6 @@ func AssertCount(t *testing.T, db *sqlx.DB, tableName string, expected int64) { require.Equal(t, expected, count) } -func AssertCountPerSubject(t *testing.T, db *sqlx.DB, expected int64, subject uuid.UUID) { - t.Helper() - var count int64 - err := db.Get(&count, `SELECT COUNT(*) FROM evm.txes - WHERE state = 'unstarted' AND subject = $1;`, subject) - require.NoError(t, err) - require.Equal(t, expected, count) -} - func NewTestFlagSet() *flag.FlagSet { return flag.NewFlagSet("test", flag.PanicOnError) } diff --git a/core/scripts/chaincli/.env.debugging.example b/core/scripts/chaincli/.env.debugging.example new file mode 100644 index 00000000000..6934bb107f5 --- /dev/null +++ b/core/scripts/chaincli/.env.debugging.example @@ -0,0 +1,15 @@ +# [Mandatory] http url of the archival node for your network +NODE_URL= +# [Mandatory] address of the KeeperRegistry contract for your upkeep +KEEPER_REGISTRY_ADDRESS= + +# [Optional] it is strongly recommended (not mandatory) to use tenderly for more debugging info +#TENDERLY_KEY= +#TENDERLY_ACCOUNT_NAME= +#TENDERLY_PROJECT_NAME= + +# [Optional] add mercury info only if your upkeep uses mercury +#MERCURY_ID= +#MERCURY_KEY= +#MERCURY_LEGACY_URL= +#MERCURY_URL= \ No newline at end of file diff --git a/core/scripts/chaincli/command/keeper/upkeep.go b/core/scripts/chaincli/command/keeper/upkeep.go index 8e2bc8bd993..c615bbf1aec 100644 --- a/core/scripts/chaincli/command/keeper/upkeep.go +++ b/core/scripts/chaincli/command/keeper/upkeep.go @@ -82,14 +82,11 @@ var ocr2UpkeepReportHistoryCmd = &cobra.Command{ hdlr := handler.NewBaseHandler(cfg) var hashes []string - var err error - var path string - - path, err = cmd.Flags().GetString("csv") + path, err := cmd.Flags().GetString("csv") if err == nil && len(path) != 0 { - rec, err := readCsvFile(path) - if err != nil { - log.Fatal(err) + rec, err2 := readCsvFile(path) + if err2 != nil { + log.Fatal(err2) } if len(rec) < 1 { @@ -107,7 +104,7 @@ var ocr2UpkeepReportHistoryCmd = &cobra.Command{ } } - if err := handler.OCR2AutomationReports(hdlr, hashes); err != nil { + if err = handler.OCR2AutomationReports(hdlr, hashes); err != nil { log.Fatalf("failed to collect transaction data: %s", err) } }, diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go index 288c7a68b80..9782f5b72fe 100644 --- a/core/scripts/chaincli/handler/debug.go +++ b/core/scripts/chaincli/handler/debug.go @@ -24,6 +24,8 @@ import ( evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" + commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" + "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" @@ -34,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" - "github.com/smartcontractkit/chainlink/v2/core/utils" bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) @@ -86,7 +87,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { } // get upkeepID from command args upkeepID := big.NewInt(0) - upkeepIDNoPrefix := utils.RemoveHexPrefix(args[0]) + upkeepIDNoPrefix := commonhex.TrimPrefix(args[0]) _, wasBase10 := upkeepID.SetString(upkeepIDNoPrefix, 10) if !wasBase10 { _, wasBase16 := upkeepID.SetString(upkeepIDNoPrefix, 16) @@ -308,10 +309,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { var values [][]byte values, err = streams.DoMercuryRequest(ctx, streamsLookup, checkResults, 0) - if checkResults[0].IneligibilityReason == uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput) { + if checkResults[0].IneligibilityReason == uint8(encoding.UpkeepFailureReasonInvalidRevertDataInput) { resolveIneligible("upkeep used invalid revert data") } - if checkResults[0].PipelineExecutionState == uint8(mercury.InvalidMercuryRequest) { + if checkResults[0].PipelineExecutionState == uint8(encoding.InvalidMercuryRequest) { resolveIneligible("the mercury request data is invalid") } if err != nil { @@ -362,7 +363,17 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if simulateResult.Success { resolveEligible() } else { - resolveIneligible("simulate perform upkeep unsuccessful") + // Convert performGas to *big.Int for comparison + performGasBigInt := new(big.Int).SetUint64(uint64(upkeepInfo.PerformGas)) + // Compare PerformGas and GasUsed + result := performGasBigInt.Cmp(simulateResult.GasUsed) + + if result < 0 { + // PerformGas is smaller than GasUsed + resolveIneligible(fmt.Sprintf("simulate perform upkeep unsuccessful, PerformGas (%d) is lower than GasUsed (%s)", upkeepInfo.PerformGas, simulateResult.GasUsed.String())) + } else { + resolveIneligible("simulate perform upkeep unsuccessful") + } } } diff --git a/core/scripts/chaincli/handler/handler.go b/core/scripts/chaincli/handler/handler.go index f72e94605d4..6423df3aa23 100644 --- a/core/scripts/chaincli/handler/handler.go +++ b/core/scripts/chaincli/handler/handler.go @@ -411,44 +411,44 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain if writeLogs { var rdr io.ReadCloser - rdr, err := dockerClient.ContainerLogs(ctx, nodeContainerResp.ID, types.ContainerLogsOptions{ + rdr, err2 := dockerClient.ContainerLogs(ctx, nodeContainerResp.ID, types.ContainerLogsOptions{ ShowStderr: true, Timestamps: true, }) - if err != nil { + if err2 != nil { rdr.Close() - log.Fatal("Failed to collect logs from container: ", err) + log.Fatal("Failed to collect logs from container: ", err2) } - stdErr, err := os.OpenFile(fmt.Sprintf("./%s-stderr.log", nodeContainerResp.ID), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) - if err != nil { + stdErr, err2 := os.OpenFile(fmt.Sprintf("./%s-stderr.log", nodeContainerResp.ID), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) + if err2 != nil { rdr.Close() stdErr.Close() - log.Fatal("Failed to open file: ", err) + log.Fatal("Failed to open file: ", err2) } - if _, err := stdcopy.StdCopy(io.Discard, stdErr, rdr); err != nil { + if _, err2 := stdcopy.StdCopy(io.Discard, stdErr, rdr); err2 != nil { rdr.Close() stdErr.Close() - log.Fatal("Failed to write logs to file: ", err) + log.Fatal("Failed to write logs to file: ", err2) } rdr.Close() stdErr.Close() } - if err = dockerClient.ContainerStop(ctx, nodeContainerResp.ID, container.StopOptions{}); err != nil { - log.Fatal("Failed to stop node container: ", err) + if err2 := dockerClient.ContainerStop(ctx, nodeContainerResp.ID, container.StopOptions{}); err2 != nil { + log.Fatal("Failed to stop node container: ", err2) } - if err = dockerClient.ContainerRemove(ctx, nodeContainerResp.ID, types.ContainerRemoveOptions{}); err != nil { - log.Fatal("Failed to remove node container: ", err) + if err2 := dockerClient.ContainerRemove(ctx, nodeContainerResp.ID, types.ContainerRemoveOptions{}); err2 != nil { + log.Fatal("Failed to remove node container: ", err2) } - if err = dockerClient.ContainerStop(ctx, dbContainerResp.ID, container.StopOptions{}); err != nil { - log.Fatal("Failed to stop DB container: ", err) + if err2 := dockerClient.ContainerStop(ctx, dbContainerResp.ID, container.StopOptions{}); err2 != nil { + log.Fatal("Failed to stop DB container: ", err2) } - if err = dockerClient.ContainerRemove(ctx, dbContainerResp.ID, types.ContainerRemoveOptions{}); err != nil { - log.Fatal("Failed to remove DB container: ", err) + if err2 := dockerClient.ContainerRemove(ctx, dbContainerResp.ID, types.ContainerRemoveOptions{}); err2 != nil { + log.Fatal("Failed to remove DB container: ", err2) } }, nil } diff --git a/core/scripts/chaincli/handler/keeper.go b/core/scripts/chaincli/handler/keeper.go index ad8bd93649c..a5fb505adb4 100644 --- a/core/scripts/chaincli/handler/keeper.go +++ b/core/scripts/chaincli/handler/keeper.go @@ -528,13 +528,11 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, var registerUpkeepTx *types.Transaction var logUpkeepCounter *log_upkeep_counter_wrapper.LogUpkeepCounter var checkData []byte - var err error + switch k.cfg.UpkeepType { case config.Conditional: checkData = []byte(k.cfg.UpkeepCheckData) - if err != nil { - log.Fatal(err) - } + var err error if k.cfg.UpkeepAverageEligibilityCadence > 0 { upkeepAddr, deployUpkeepTx, _, err = upkeep.DeployUpkeepPerformCounterRestrictive( k.buildTxOpts(ctx), @@ -570,9 +568,7 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, } case config.Mercury: checkData = []byte(k.cfg.UpkeepCheckData) - if err != nil { - log.Fatal(err) - } + var err error if k.cfg.VerifiableLoadTest { upkeepAddr, deployUpkeepTx, _, err = verifiable_load_streams_lookup_upkeep_wrapper.DeployVerifiableLoadStreamsLookupUpkeep( k.buildTxOpts(ctx), @@ -603,6 +599,7 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, log.Fatal(i, upkeepAddr.Hex(), ": RegisterUpkeep failed - ", err) } case config.LogTrigger: + var err error upkeepAddr, deployUpkeepTx, logUpkeepCounter, err = log_upkeep_counter_wrapper.DeployLogUpkeepCounter( k.buildTxOpts(ctx), k.client, @@ -637,7 +634,7 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, if err != nil { log.Fatal("failed to start log upkeep counter", err) } - if err := k.waitTx(ctx, logUpkeepStartTx); err != nil { + if err = k.waitTx(ctx, logUpkeepStartTx); err != nil { log.Fatalf("Log upkeep Start() failed for upkeepId: %s, error is %s", upkeepAddr.Hex(), err.Error()) } log.Println(i, upkeepAddr.Hex(), ": Log upkeep successfully started - ", helpers.ExplorerLink(k.cfg.ChainID, logUpkeepStartTx.Hash())) @@ -653,32 +650,34 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, upkeepAddrs = append(upkeepAddrs, upkeepAddr) } - var err error var upkeepGetter activeUpkeepGetter upkeepCount := big.NewInt(k.cfg.UpkeepCount) // second arg in GetActiveUpkeepIds (on registry) - switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - panic("not supported 1.1 registry") - case keeper.RegistryVersion_1_2: - upkeepGetter, err = registry12.NewKeeperRegistry( - registryAddr, - k.client, - ) - case keeper.RegistryVersion_2_0: - upkeepGetter, err = registry20.NewKeeperRegistry( - registryAddr, - k.client, - ) - case keeper.RegistryVersion_2_1: - upkeepGetter, err = iregistry21.NewIKeeperRegistryMaster( - registryAddr, - k.client, - ) - default: - panic("unexpected registry address") - } - if err != nil { - log.Fatal("Registry failed: ", err) + { + var err error + switch k.cfg.RegistryVersion { + case keeper.RegistryVersion_1_1: + panic("not supported 1.1 registry") + case keeper.RegistryVersion_1_2: + upkeepGetter, err = registry12.NewKeeperRegistry( + registryAddr, + k.client, + ) + case keeper.RegistryVersion_2_0: + upkeepGetter, err = registry20.NewKeeperRegistry( + registryAddr, + k.client, + ) + case keeper.RegistryVersion_2_1: + upkeepGetter, err = iregistry21.NewIKeeperRegistryMaster( + registryAddr, + k.client, + ) + default: + panic("unexpected registry address") + } + if err != nil { + log.Fatal("Registry failed: ", err) + } } activeUpkeepIds := k.getActiveUpkeepIds(ctx, upkeepGetter, big.NewInt(existingCount), upkeepCount) @@ -724,22 +723,24 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, } for _, id := range activeUpkeepIds { - tx, err := reg21.SetUpkeepPrivilegeConfig(k.buildTxOpts(ctx), id, adminBytes) - if err != nil { - log.Fatalf("failed to upkeep privilege config: %v", err) + tx, err2 := reg21.SetUpkeepPrivilegeConfig(k.buildTxOpts(ctx), id, adminBytes) + if err2 != nil { + log.Fatalf("failed to upkeep privilege config: %v", err2) } - err = k.waitTx(ctx, tx) - if err != nil { - log.Fatalf("failed to wait for tx: %v", err) - } else { - log.Printf("upkeep privilege config is set for %s", id.String()) + err2 = k.waitTx(ctx, tx) + if err2 != nil { + log.Fatalf("failed to wait for tx: %v", err2) } + log.Printf("upkeep privilege config is set for %s", id.String()) - info, err := reg21.GetUpkeep(nil, id) - if err != nil { - log.Fatalf("failed to fetch upkeep id %s from registry 2.1: %v", id, err) + info, err2 := reg21.GetUpkeep(nil, id) + if err2 != nil { + log.Fatalf("failed to fetch upkeep id %s from registry 2.1: %v", id, err2) + } + min, err2 := reg21.GetMinBalanceForUpkeep(nil, id) + if err2 != nil { + log.Fatalf("failed to fetch upkeep id %s from registry 2.1: %v", id, err2) } - min, err := reg21.GetMinBalanceForUpkeep(nil, id) log.Printf(" Balance: %s", info.Balance) log.Printf("Min Balance: %s", min.String()) } @@ -757,7 +758,7 @@ func (k *Keeper) setKeepers(ctx context.Context, cls []cmd.HTTPClient, deployer log.Fatal("SetKeepers failed: ", err) } - if err := k.waitTx(ctx, setKeepersTx); err != nil { + if err = k.waitTx(ctx, setKeepersTx); err != nil { log.Fatalf("SetKeepers failed, error is: %s", err.Error()) } @@ -777,24 +778,6 @@ func (k *Keeper) keepers() ([]common.Address, []common.Address) { return addrs, fromAddrs } -// createKeeperJobOnExistingNode connect to existing node to create keeper job -func (k *Keeper) createKeeperJobOnExistingNode(urlStr, email, password, registryAddr, nodeAddr string) error { - lggr, closeLggr := logger.NewLogger() - logger.Sugared(lggr).ErrorIfFn(closeLggr, "Failed to close logger") - - cl, err := authenticate(urlStr, email, password, lggr) - if err != nil { - return err - } - - if err = k.createKeeperJob(cl, registryAddr, nodeAddr); err != nil { - log.Println("Failed to create keeper job: ", err) - return err - } - - return nil -} - type activeUpkeepGetter interface { Address() common.Address GetActiveUpkeepIDs(opts *bind.CallOpts, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) diff --git a/core/scripts/chaincli/handler/keeper_launch.go b/core/scripts/chaincli/handler/keeper_launch.go index 22b67763945..e8be82a4bb7 100644 --- a/core/scripts/chaincli/handler/keeper_launch.go +++ b/core/scripts/chaincli/handler/keeper_launch.go @@ -18,6 +18,7 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/cmd" iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" registry12 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" @@ -100,14 +101,12 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, if len(k.cfg.KeeperKeys) > 0 { // import key if exists - var err error nodeAddrHex, err = k.addKeyToKeeper(cl, k.cfg.KeeperKeys[i]) if err != nil { log.Fatal("could not add key to keeper", err) } } else { // get node's default wallet address - var err error nodeAddrHex, err = getNodeAddress(cl) if err != nil { log.Println("Failed to get node addr: ", err) @@ -220,35 +219,35 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, // cancelAndWithdrawActiveUpkeeps cancels all active upkeeps and withdraws funds for registry 1.2 func (k *Keeper) cancelAndWithdrawActiveUpkeeps(ctx context.Context, activeUpkeepIds []*big.Int, canceller canceller) error { - var err error for i := 0; i < len(activeUpkeepIds); i++ { - var tx *ethtypes.Transaction upkeepId := activeUpkeepIds[i] - if tx, err = canceller.CancelUpkeep(k.buildTxOpts(ctx), upkeepId); err != nil { + tx, err := canceller.CancelUpkeep(k.buildTxOpts(ctx), upkeepId) + if err != nil { return fmt.Errorf("failed to cancel upkeep %s: %s", upkeepId.String(), err) } - if err := k.waitTx(ctx, tx); err != nil { + if err = k.waitTx(ctx, tx); err != nil { log.Fatalf("failed to cancel upkeep for upkeepId: %s, error is: %s", upkeepId.String(), err.Error()) } - if tx, err = canceller.WithdrawFunds(k.buildTxOpts(ctx), upkeepId, k.fromAddr); err != nil { + tx, err = canceller.WithdrawFunds(k.buildTxOpts(ctx), upkeepId, k.fromAddr) + if err != nil { return fmt.Errorf("failed to withdraw upkeep %s: %s", upkeepId.String(), err) } - if err := k.waitTx(ctx, tx); err != nil { + if err = k.waitTx(ctx, tx); err != nil { log.Fatalf("failed to withdraw upkeep for upkeepId: %s, error is: %s", upkeepId.String(), err.Error()) } log.Printf("Upkeep %s successfully canceled and refunded: ", upkeepId.String()) } - var tx *ethtypes.Transaction - if tx, err = canceller.RecoverFunds(k.buildTxOpts(ctx)); err != nil { + tx, err := canceller.RecoverFunds(k.buildTxOpts(ctx)) + if err != nil { return fmt.Errorf("failed to recover funds: %s", err) } - if err := k.waitTx(ctx, tx); err != nil { + if err = k.waitTx(ctx, tx); err != nil { log.Fatalf("failed to recover funds, error is: %s", err.Error()) } @@ -264,7 +263,7 @@ func (k *Keeper) cancelAndWithdrawUpkeeps(ctx context.Context, upkeepCount *big. return fmt.Errorf("failed to cancel upkeep %d: %s", i, err) } - if err := k.waitTx(ctx, tx); err != nil { + if err = k.waitTx(ctx, tx); err != nil { log.Fatalf("failed to cancel upkeep, error is: %s", err.Error()) } @@ -272,7 +271,7 @@ func (k *Keeper) cancelAndWithdrawUpkeeps(ctx context.Context, upkeepCount *big. return fmt.Errorf("failed to withdraw upkeep %d: %s", i, err) } - if err := k.waitTx(ctx, tx); err != nil { + if err = k.waitTx(ctx, tx); err != nil { log.Fatalf("failed to withdraw upkeep, error is: %s", err.Error()) } @@ -284,7 +283,7 @@ func (k *Keeper) cancelAndWithdrawUpkeeps(ctx context.Context, upkeepCount *big. return fmt.Errorf("failed to recover funds: %s", err) } - if err := k.waitTx(ctx, tx); err != nil { + if err = k.waitTx(ctx, tx); err != nil { log.Fatalf("failed to recover funds, error is: %s", err.Error()) } @@ -411,7 +410,7 @@ func (k *Keeper) createOCR2KeeperJob(client cmd.HTTPClient, contractAddr, nodeAd // addKeyToKeeper imports the provided ETH sending key to the keeper func (k *Keeper) addKeyToKeeper(client cmd.HTTPClient, privKeyHex string) (string, error) { - privkey, err := crypto.HexToECDSA(utils.RemoveHexPrefix(privKeyHex)) + privkey, err := crypto.HexToECDSA(hex.TrimPrefix(privKeyHex)) if err != nil { log.Fatalf("Failed to decode priv key %s: %v", privKeyHex, err) } diff --git a/core/scripts/chaincli/handler/ocr2_config.go b/core/scripts/chaincli/handler/ocr2_config.go index 21b2ad414a3..caa96112ea8 100644 --- a/core/scripts/chaincli/handler/ocr2_config.go +++ b/core/scripts/chaincli/handler/ocr2_config.go @@ -54,7 +54,7 @@ func OCR2GetConfig(hdlr *baseHandler, registry_addr string) error { func configFromBlock(bl *types.Block, addr common.Address, detail keeper_registry_wrapper2_0.LatestConfigDetails) (*confighelper.PublicConfig, error) { for _, tx := range bl.Transactions() { - if tx.To() != nil && bytes.Compare(tx.To()[:], addr[:]) == 0 { + if tx.To() != nil && bytes.Equal(tx.To()[:], addr[:]) { // this is our transaction // txRes, txErr, err := getTransactionDetailForHashes(hdlr, []string{tx}) ocr2Tx, err := NewBaseOCR2Tx(tx) diff --git a/core/scripts/chaincli/handler/report.go b/core/scripts/chaincli/handler/report.go index 10970b5f03b..1dcbb21ee83 100644 --- a/core/scripts/chaincli/handler/report.go +++ b/core/scripts/chaincli/handler/report.go @@ -85,24 +85,26 @@ func OCR2AutomationReports(hdlr *baseHandler, txs []string) error { } txRes, txErr, err = getSimulationsForTxs(hdlr, simBatch) + if err != nil { + return err + } for i := range txRes { if txErr[i] == nil { continue } - err, ok := txErr[i].(JsonError) + err2, ok := txErr[i].(JsonError) //nolint:errorlint if ok { - decoded, err := hexutil.Decode(err.ErrorData().(string)) + decoded, err := hexutil.Decode(err2.ErrorData().(string)) if err != nil { elements[i].Err = err.Error() continue } elements[i].Err = ocr2Txs[i].DecodeError(decoded) - } else if err != nil { - elements[i].Err = err.Error() + } else if err2 != nil { + elements[i].Err = err2.Error() } - } data := make([][]string, len(elements)) @@ -275,7 +277,7 @@ func (t *OCR2Transaction) DecodeError(b []byte) string { } } - return fmt.Sprintf("%s", j) + return j } func NewOCR2TransmitTx(raw map[string]interface{}) (*OCR2TransmitTx, error) { diff --git a/core/scripts/common/avalanche.go b/core/scripts/common/avalanche.go index c9c53779905..8699463c365 100644 --- a/core/scripts/common/avalanche.go +++ b/core/scripts/common/avalanche.go @@ -79,8 +79,8 @@ func (b *AvaBloom) UnmarshalText(input []byte) error { // bloomValues returns the bytes (index-value pairs) to set for the given data func bloomValues(data []byte, hashbuf []byte) (uint, byte, uint, byte, uint, byte) { sha := crypto.NewKeccakState() - sha.Write(data) - sha.Read(hashbuf) + sha.Write(data) //nolint:errcheck + sha.Read(hashbuf) //nolint:errcheck // The actual bits to flip v1 := byte(1 << (hashbuf[1] & 0x7)) v2 := byte(1 << (hashbuf[3] & 0x7)) @@ -259,7 +259,7 @@ func (h *AvaHeader) Hash() common.Hash { func rlpHash(x interface{}) (h common.Hash) { sha := crypto.NewKeccakState() sha.Reset() - rlp.Encode(sha, x) - sha.Read(h[:]) + rlp.Encode(sha, x) //nolint:errcheck + sha.Read(h[:]) //nolint:errcheck return h } diff --git a/core/scripts/common/helpers.go b/core/scripts/common/helpers.go index b5a3b1ed943..9d2d06c89d0 100644 --- a/core/scripts/common/helpers.go +++ b/core/scripts/common/helpers.go @@ -395,12 +395,12 @@ func FundNode(e Environment, address string, fundingAmount *big.Int) { var gasLimit uint64 if IsArbitrumChainID(e.ChainID) { to := common.HexToAddress(address) - estimated, err := e.Ec.EstimateGas(context.Background(), ethereum.CallMsg{ + estimated, err2 := e.Ec.EstimateGas(context.Background(), ethereum.CallMsg{ From: e.Owner.From, To: &to, Value: fundingAmount, }) - PanicErr(err) + PanicErr(err2) gasLimit = estimated } else { gasLimit = uint64(21_000) @@ -461,7 +461,7 @@ func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks boo hashes = make([]string, 0) - var offset *big.Int = big.NewInt(0) + offset := big.NewInt(0) if getParentBlocks { offset = big.NewInt(1) } @@ -475,15 +475,15 @@ func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks boo var h AvaHeader // Get child block since it's the one that has the parent hash in its header. nextBlockNum := new(big.Int).Set(blockNum).Add(blockNum, offset) - err := env.Jc.CallContext(context.Background(), &h, "eth_getBlockByNumber", hexutil.EncodeBig(nextBlockNum), false) - if err != nil { - return nil, hashes, fmt.Errorf("failed to get header: %+v", err) + err2 := env.Jc.CallContext(context.Background(), &h, "eth_getBlockByNumber", hexutil.EncodeBig(nextBlockNum), false) + if err2 != nil { + return nil, hashes, fmt.Errorf("failed to get header: %+v", err2) } // We can still use vanilla go-ethereum rlp.EncodeToBytes, see e.g // https://github.com/ava-labs/coreth/blob/e3ca41bf5295a9a7ca1aeaf29d541fcbb94f79b1/core/types/hashing.go#L49-L57. - rlpHeader, err = rlp.EncodeToBytes(h) - if err != nil { - return nil, hashes, fmt.Errorf("failed to encode rlp: %+v", err) + rlpHeader, err2 = rlp.EncodeToBytes(h) + if err2 != nil { + return nil, hashes, fmt.Errorf("failed to encode rlp: %+v", err2) } hashes = append(hashes, h.Hash().String()) @@ -509,16 +509,16 @@ func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks boo } else { // Get child block since it's the one that has the parent hash in its header. - h, err := env.Ec.HeaderByNumber( + h, err2 := env.Ec.HeaderByNumber( context.Background(), new(big.Int).Set(blockNum).Add(blockNum, offset), ) - if err != nil { - return nil, hashes, fmt.Errorf("failed to get header: %+v", err) + if err2 != nil { + return nil, hashes, fmt.Errorf("failed to get header: %+v", err2) } - rlpHeader, err = rlp.EncodeToBytes(h) - if err != nil { - return nil, hashes, fmt.Errorf("failed to encode rlp: %+v", err) + rlpHeader, err2 = rlp.EncodeToBytes(h) + if err2 != nil { + return nil, hashes, fmt.Errorf("failed to encode rlp: %+v", err2) } hashes = append(hashes, h.Hash().String()) diff --git a/core/scripts/common/vrf/model/model.go b/core/scripts/common/vrf/model/model.go index 0972c47e618..1b4e59fe4f3 100644 --- a/core/scripts/common/vrf/model/model.go +++ b/core/scripts/common/vrf/model/model.go @@ -21,7 +21,6 @@ type Node struct { NumberOfSendingKeysToCreate int SendingKeyFundingAmount *big.Int VrfKeys []string - jobSpec string } type SendingKey struct { diff --git a/core/scripts/common/vrf/setup-envs/main.go b/core/scripts/common/vrf/setup-envs/main.go index e9ea252e4c4..598238bebef 100644 --- a/core/scripts/common/vrf/setup-envs/main.go +++ b/core/scripts/common/vrf/setup-envs/main.go @@ -50,7 +50,6 @@ func newApp(remoteNodeURL string, writer io.Writer) (*clcmd.Shell, *cli.App) { var ( checkMarkEmoji = "✅" xEmoji = "❌" - infoEmoji = "ℹ️" ) func main() { @@ -142,7 +141,7 @@ func main() { output := &bytes.Buffer{} for key, node := range nodesMap { - + node := node client, app := connectToNode(&node.URL, output, node.CredsFile) ethKeys := createETHKeysIfNeeded(client, app, output, numEthKeys, &node.URL, maxGasPriceGwei) if key == model.VRFPrimaryNodeName { @@ -242,6 +241,7 @@ func main() { } for key, node := range nodesMap { + node := node client, app := connectToNode(&node.URL, output, node.CredsFile) //GET ALL JOBS @@ -318,7 +318,7 @@ func getVRFKeys(client *clcmd.Shell, app *cli.App, output *bytes.Buffer) []prese } func createJob(jobSpec string, client *clcmd.Shell, app *cli.App, output *bytes.Buffer) { - if err := os.WriteFile("job-spec.toml", []byte(jobSpec), 0666); err != nil { + if err := os.WriteFile("job-spec.toml", []byte(jobSpec), 0666); err != nil { //nolint:gosec helpers.PanicErr(err) } job := presenters.JobResource{} @@ -332,7 +332,7 @@ func createJob(jobSpec string, client *clcmd.Shell, app *cli.App, output *bytes. } func exportVRFKey(client *clcmd.Shell, app *cli.App, vrfKey presenters.VRFKeyResource, output *bytes.Buffer) { - if err := os.WriteFile("vrf-key-password.txt", []byte("twochains"), 0666); err != nil { + if err := os.WriteFile("vrf-key-password.txt", []byte("twochains"), 0666); err != nil { //nolint:gosec helpers.PanicErr(err) } flagSet := flag.NewFlagSet("blah", flag.ExitOnError) @@ -346,7 +346,7 @@ func exportVRFKey(client *clcmd.Shell, app *cli.App, vrfKey presenters.VRFKeyRes } func importVRFKey(client *clcmd.Shell, app *cli.App, output *bytes.Buffer) { - if err := os.WriteFile("vrf-key-password.txt", []byte("twochains"), 0666); err != nil { + if err := os.WriteFile("vrf-key-password.txt", []byte("twochains"), 0666); err != nil { //nolint:gosec helpers.PanicErr(err) } flagSet := flag.NewFlagSet("blah", flag.ExitOnError) @@ -465,12 +465,8 @@ func createVRFKeyIfNeeded(client *clcmd.Shell, app *cli.App, output *bytes.Buffe }(), ", ")) } fmt.Println() - for _, vrfKey := range vrfKeys { - allVRFKeys = append(allVRFKeys, vrfKey) - } - for _, nk := range newKeys { - allVRFKeys = append(allVRFKeys, nk) - } + allVRFKeys = append(allVRFKeys, vrfKeys...) + allVRFKeys = append(allVRFKeys, newKeys...) return allVRFKeys } @@ -526,11 +522,7 @@ func createETHKeysIfNeeded(client *clcmd.Shell, app *cli.App, output *bytes.Buff } output.Reset() fmt.Println() - for _, ethKey := range ethKeys { - allETHKeysNode = append(allETHKeysNode, ethKey) - } - for _, nk := range newKeys { - allETHKeysNode = append(allETHKeysNode, nk) - } + allETHKeysNode = append(allETHKeysNode, ethKeys...) + allETHKeysNode = append(allETHKeysNode, newKeys...) return allETHKeysNode } diff --git a/core/scripts/functions/src/delete_jobs.go b/core/scripts/functions/src/delete_jobs.go index 632a239a62b..4fac1a4a772 100644 --- a/core/scripts/functions/src/delete_jobs.go +++ b/core/scripts/functions/src/delete_jobs.go @@ -62,7 +62,7 @@ func (g *deleteJobs) Run(args []string) { output.Reset() fileFs := flag.NewFlagSet("test", flag.ExitOnError) - client.ListJobs(cli.NewContext(app, fileFs, nil)) + err = client.ListJobs(cli.NewContext(app, fileFs, nil)) helpers.PanicErr(err) var parsed []JobSpec @@ -73,7 +73,8 @@ func (g *deleteJobs) Run(args []string) { if jobSpec.BootstrapSpec.ContractID == *contractAddress || jobSpec.OffChainReporting2OracleSpec.ContractID == *contractAddress { fmt.Println("Deleting job ID:", jobSpec.Id, "name:", jobSpec.Name) set := flag.NewFlagSet("test", flag.ExitOnError) - set.Parse([]string{jobSpec.Id}) + err = set.Parse([]string{jobSpec.Id}) + helpers.PanicErr(err) err = client.DeleteJob(cli.NewContext(app, set, nil)) helpers.PanicErr(err) } diff --git a/core/scripts/functions/src/deploy_jobspecs_cmd.go b/core/scripts/functions/src/deploy_jobspecs_cmd.go index 0039aaa4601..e892370cc22 100644 --- a/core/scripts/functions/src/deploy_jobspecs_cmd.go +++ b/core/scripts/functions/src/deploy_jobspecs_cmd.go @@ -27,18 +27,18 @@ func (g *deployJobSpecs) Name() string { func (g *deployJobSpecs) Run(args []string) { fs := flag.NewFlagSet(g.Name(), flag.ContinueOnError) nodesFile := fs.String("nodes", "", "a file containing nodes urls, logins and passwords") - err := fs.Parse(args) - if err != nil || nodesFile == nil || *nodesFile == "" { + + if err := fs.Parse(args); err != nil || nodesFile == nil || *nodesFile == "" { fs.Usage() os.Exit(1) } nodes := mustReadNodesList(*nodesFile) - for _, node := range nodes { + for _, n := range nodes { output := &bytes.Buffer{} - client, app := newApp(node, output) + client, app := newApp(n, output) - fmt.Println("Logging in:", node.url) + fmt.Println("Logging in:", n.url) loginFs := flag.NewFlagSet("test", flag.ContinueOnError) loginFs.Bool("bypass-version-check", true, "") loginCtx := cli.NewContext(app, loginFs, nil) @@ -46,18 +46,19 @@ func (g *deployJobSpecs) Run(args []string) { helpers.PanicErr(err) output.Reset() - tomlPath := filepath.Join(artefactsDir, node.url.Host+".toml") + tomlPath := filepath.Join(artefactsDir, n.url.Host+".toml") tomlPath, err = filepath.Abs(tomlPath) if err != nil { helpers.PanicErr(err) } fmt.Println("Deploying jobspec:", tomlPath) - if _, err := os.Stat(tomlPath); err != nil { + if _, err = os.Stat(tomlPath); err != nil { helpers.PanicErr(errors.New("toml file does not exist")) } fileFs := flag.NewFlagSet("test", flag.ExitOnError) - fileFs.Parse([]string{tomlPath}) + err = fileFs.Parse([]string{tomlPath}) + helpers.PanicErr(err) err = client.CreateJob(cli.NewContext(app, fileFs, nil)) helpers.PanicErr(err) output.Reset() diff --git a/core/scripts/functions/src/fetching.go b/core/scripts/functions/src/fetching.go index 9be624a40b6..2e0841b49de 100644 --- a/core/scripts/functions/src/fetching.go +++ b/core/scripts/functions/src/fetching.go @@ -11,6 +11,7 @@ import ( "github.com/urfave/cli" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -23,11 +24,11 @@ type ocr2Bundle struct { } func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { - for _, node := range nodes { + for _, n := range nodes { output := &bytes.Buffer{} - client, app := newApp(node, output) + client, app := newApp(n, output) - fmt.Println("Logging in:", node.url) + fmt.Println("Logging in:", n.url) loginFs := flag.NewFlagSet("test", flag.ContinueOnError) loginFs.Bool("bypass-version-check", true, "") loginCtx := cli.NewContext(app, loginFs, nil) @@ -67,7 +68,7 @@ func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { if ocr2BundleIndex == -1 { helpers.PanicErr(errors.New("node must have EVM OCR2 bundle")) } - ocr2Bundle := ocr2Bundles[ocr2BundleIndex] + ocr2Bndl := ocr2Bundles[ocr2BundleIndex] output.Reset() err = client.ListCSAKeys(&cli.Context{ @@ -83,10 +84,10 @@ func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { nc := NodeKeys{ EthAddress: ethAddress, P2PPeerID: peerID, - OCR2BundleID: ocr2Bundle.ID, - OCR2ConfigPublicKey: strings.TrimPrefix(ocr2Bundle.ConfigPublicKey, "ocr2cfg_evm_"), - OCR2OnchainPublicKey: strings.TrimPrefix(ocr2Bundle.OnchainPublicKey, "ocr2on_evm_"), - OCR2OffchainPublicKey: strings.TrimPrefix(ocr2Bundle.OffchainPublicKey, "ocr2off_evm_"), + OCR2BundleID: ocr2Bndl.ID, + OCR2ConfigPublicKey: strings.TrimPrefix(ocr2Bndl.ConfigPublicKey, "ocr2cfg_evm_"), + OCR2OnchainPublicKey: strings.TrimPrefix(ocr2Bndl.OnchainPublicKey, "ocr2on_evm_"), + OCR2OffchainPublicKey: strings.TrimPrefix(ocr2Bndl.OffchainPublicKey, "ocr2off_evm_"), CSAPublicKey: csaPubKey, } diff --git a/core/scripts/functions/src/generate_ocr2_config_cmd.go b/core/scripts/functions/src/generate_ocr2_config_cmd.go index 1cfddf4413c..7ac3b68d11d 100644 --- a/core/scripts/functions/src/generate_ocr2_config_cmd.go +++ b/core/scripts/functions/src/generate_ocr2_config_cmd.go @@ -134,8 +134,7 @@ func (g *generateOCR2Config) Run(args []string) { keysFile := fs.String("keys", "", "a file containing nodes public keys") configFile := fs.String("config", "", "a file containing JSON config") chainID := fs.Int64("chainid", 80001, "chain id") - err := fs.Parse(args) - if err != nil || (*nodesFile == "" && *keysFile == "") || *configFile == "" || chainID == nil { + if err := fs.Parse(args); err != nil || (*nodesFile == "" && *keysFile == "") || *configFile == "" || chainID == nil { fs.Usage() os.Exit(1) } diff --git a/core/scripts/gateway/client/send_request.go b/core/scripts/gateway/client/send_request.go index 8ab4e8bce79..eeb85ff0dcb 100644 --- a/core/scripts/gateway/client/send_request.go +++ b/core/scripts/gateway/client/send_request.go @@ -52,7 +52,6 @@ func main() { var s4SetPayload []byte if *methodName == functions.MethodSecretsSet { - var err error s4SetPayload, err = os.ReadFile(*s4SetPayloadFile) if err != nil { fmt.Println("error reading S4 payload file", err) @@ -70,23 +69,21 @@ func main() { Payload: s4SetPayload, Expiration: time.Now().UnixMilli() + *s4SetExpirationPeriod, } - signature, err := envelope.Sign(key) - if err != nil { - fmt.Println("error signing S4 envelope", err) + signature, err2 := envelope.Sign(key) + if err2 != nil { + fmt.Println("error signing S4 envelope", err2) return } - s4SetPayload := functions.SecretsSetRequest{ + payloadJSON, err2 = json.Marshal(functions.SecretsSetRequest{ SlotID: envelope.SlotID, Version: envelope.Version, Expiration: envelope.Expiration, Payload: s4SetPayload, Signature: signature, - } - - payloadJSON, err = json.Marshal(s4SetPayload) - if err != nil { - fmt.Println("error marshaling S4 payload", err) + }) + if err2 != nil { + fmt.Println("error marshaling S4 payload", err2) return } } @@ -122,27 +119,27 @@ func main() { client := &http.Client{} sendRequest := func() { - req, err := createRequest() - if err != nil { - fmt.Println("error creating a request", err) + req, err2 := createRequest() + if err2 != nil { + fmt.Println("error creating a request", err2) return } - resp, err := client.Do(req) - if err != nil { - fmt.Println("error sending a request", err) + resp, err2 := client.Do(req) + if err2 != nil { + fmt.Println("error sending a request", err2) return } defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - fmt.Println("error sending a request", err) + body, err2 := io.ReadAll(resp.Body) + if err2 != nil { + fmt.Println("error sending a request", err2) return } var prettyJSON bytes.Buffer - if err := json.Indent(&prettyJSON, body, "", " "); err != nil { + if err2 = json.Indent(&prettyJSON, body, "", " "); err2 != nil { fmt.Println(string(body)) } else { fmt.Println(prettyJSON.String()) diff --git a/core/scripts/gateway/connector/run_connector.go b/core/scripts/gateway/connector/run_connector.go index 248162ef822..c6ad187461c 100644 --- a/core/scripts/gateway/connector/run_connector.go +++ b/core/scripts/gateway/connector/run_connector.go @@ -31,7 +31,10 @@ type client struct { func (h *client) HandleGatewayMessage(ctx context.Context, gatewayId string, msg *api.Message) { h.lggr.Infof("received message from gateway %s. Echoing back.", gatewayId) - h.connector.SendToGateway(context.Background(), gatewayId, msg) + err := h.connector.SendToGateway(ctx, gatewayId, msg) + if err != nil { + h.lggr.Errorw("failed to send to gateway", "id", gatewayId, "err", err) + } } func (h *client) Sign(data ...[]byte) ([]byte, error) { @@ -70,8 +73,16 @@ func main() { client.connector = connector ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt) - connector.Start(ctx) + err = connector.Start(ctx) + if err != nil { + fmt.Println("error staring connector:", err) + return + } <-ctx.Done() - connector.Close() + err = connector.Close() + if err != nil { + fmt.Println("error closing connector:", err) + return + } } diff --git a/core/scripts/gateway/run_gateway.go b/core/scripts/gateway/run_gateway.go index 1f0230bb8ad..5dbcd02bf56 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, lggr) + handlerFactory := gateway.NewHandlerFactory(nil, nil, nil, lggr) gw, err := gateway.NewGatewayFromConfig(&cfg, handlerFactory, lggr) if err != nil { fmt.Println("error creating Gateway object:", err) @@ -56,8 +56,16 @@ func main() { } ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt) - gw.Start(ctx) + err = gw.Start(ctx) + if err != nil { + fmt.Println("error staring gateway:", err) + return + } <-ctx.Done() - gw.Close() + err = gw.Close() + if err != nil { + fmt.Println("error closing gateway:", err) + return + } } diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 895363a53f8..98ab5cbfaf9 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -8,7 +8,7 @@ replace github.com/smartcontractkit/chainlink/v2 => ../../ require ( github.com/docker/docker v24.0.7+incompatible github.com/docker/go-connections v0.4.0 - github.com/ethereum/go-ethereum v1.12.0 + github.com/ethereum/go-ethereum v1.12.2 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.4.0 github.com/jmoiron/sqlx v1.3.5 @@ -19,6 +19,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.1 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.1 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a 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-20231130143053-c5102a9c0fb7 @@ -56,10 +57,10 @@ require ( github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -74,6 +75,8 @@ require ( github.com/cometbft/cometbft v0.37.2 // indirect github.com/cometbft/cometbft-db v0.7.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.10.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect github.com/cosmos/cosmos-sdk v0.47.4 // indirect @@ -84,6 +87,7 @@ require ( github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab // indirect github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -98,6 +102,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/esote/minmaxheap v1.0.0 // indirect + github.com/ethereum/c-kzg-4844 v0.3.1 // indirect github.com/fatih/color v1.16.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fxamacker/cbor/v2 v2.5.0 // indirect @@ -202,6 +207,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect @@ -236,12 +242,11 @@ require ( github.com/shirou/gopsutil/v3 v3.23.11 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect - github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.7.2 // indirect @@ -251,6 +256,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/go-amino v0.16.0 // indirect @@ -311,6 +317,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect pgregory.net/rapid v0.5.5 // indirect + rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/core/scripts/go.sum b/core/scripts/go.sum index dcf47d392cc..170e36ad2cc 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -164,11 +164,14 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= @@ -179,8 +182,9 @@ github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUB github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -256,6 +260,10 @@ github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0 github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= +github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -294,6 +302,8 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= +github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -369,8 +379,10 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7 github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= -github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= +github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= +github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.12.2 h1:eGHJ4ij7oyVqUQn48LBz3B7pvQ8sV0wGJiIE6gDq/6Y= +github.com/ethereum/go-ethereum v1.12.2/go.mod h1:1cRAEV+rp/xX0zraSCBnu9Py3HQ+geRMj3HdR+k0wfI= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= @@ -611,6 +623,7 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -716,6 +729,8 @@ github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce h1:7UnVY3T/ZnHUrfv github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= @@ -949,6 +964,9 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1146,18 +1164,18 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 h1:lSYiaiIfAA+5ac45/UD8ciytlNw/S6fnhK7bxFHYI88= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e h1:xvqffqFec2HkEcUKrCkm4FDJRnn/+gHmvrE/dz3Zlw8= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e/go.mod h1:soVgcl4CbfR6hC9UptjuCQhz19HJaFEjwnOpiySkxg0= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a h1:ViX8kP1/WYW1dLG85Frqpvus1nRGif/1QiK7qeyS+Rc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5 h1:kBnmjv3fxU7krVIqZFvo1m4F6qBc4vPURQFX/mcChhI= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5/go.mod h1:EoM7wQ81mov7wsUzG4zEnnr0EH0POEo/I0hRDg433TU= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1/go.mod h1:GuPvyXryvbiUZIHmPeLBz4L+yJKeyGUjrDfd1KNne+o= github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d h1:w4MsbOtNk6nD/mcXLstHWk9hB6g7QLtcAfhPjhwvOaQ= github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d/go.mod h1:YPAfLNowdBwiKiYOwgwtbJHi8AJWbcxkbOY0ItAvkfc= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e h1:/tCHhoAJM+ittEHPZTtJsAgXmYujKiDW0ub9HXW9qtY= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e/go.mod h1:9YIi413QRRytafTzpWm+Z+5NWBNxSqokhKyeEZ3ynlA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725 h1:NbhPVwxx+53WN/Uld1V6c4iLgoGvUYFOsVd2kfcexe8= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725/go.mod h1:vHrPBipRL52NdPp77KXNU2k1IoCUa1B33N9otZQPYko= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312 h1:ziqC+WW/2/UI6w3DShy7HGzJMWWLIYHT5ev2Qaa3h6I= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312/go.mod h1:vqnojBNdzHNI6asWezJlottUiVEXudMEGf2Mz5R+xps= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a h1:atCXqF8e5U2zfEaA87cKJs+K1MAbOVh3V05gEd60fR0= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a/go.mod h1:YWKpf+hO9XMlzIWQT8yGoky3aeFLzMUVsjbs80LD77M= 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= @@ -1223,6 +1241,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= @@ -1952,5 +1972,7 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/core/scripts/ocr2vrf/setup_ocr2vrf.go b/core/scripts/ocr2vrf/setup_ocr2vrf.go index ab43dc0180f..1094b823b4e 100644 --- a/core/scripts/ocr2vrf/setup_ocr2vrf.go +++ b/core/scripts/ocr2vrf/setup_ocr2vrf.go @@ -232,9 +232,7 @@ func setupOCR2VRFNodes(e helpers.Environment) { transmitters[i+1] = f.String() } } else { - for _, t := range transmitters[1:] { - nodesToFund = append(nodesToFund, t) - } + nodesToFund = append(nodesToFund, transmitters[1:]...) } var payees []common.Address diff --git a/core/scripts/ocr2vrf/util.go b/core/scripts/ocr2vrf/util.go index 4ec78472e50..e57f349f1fd 100644 --- a/core/scripts/ocr2vrf/util.go +++ b/core/scripts/ocr2vrf/util.go @@ -27,6 +27,7 @@ import ( "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" + "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" @@ -35,7 +36,6 @@ import ( "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" - "github.com/smartcontractkit/chainlink/v2/core/utils" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" ) @@ -306,14 +306,6 @@ func findSubscriptionID(e helpers.Environment, vrfCoordinatorAddr string) *big.I return subscriptionIterator.Event.SubId } -func registerMigratableCoordinator(e helpers.Environment, coordinatorAddress, migratableCoordinatorAddress string) { - coordinator := newVRFCoordinator(common.HexToAddress(coordinatorAddress), e.Ec) - - tx, err := coordinator.RegisterMigratableCoordinator(e.Owner, common.HexToAddress(migratableCoordinatorAddress)) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) -} - func addConsumer(e helpers.Environment, vrfCoordinatorAddr, consumerAddr string, subId *big.Int) { coordinator := newVRFCoordinator(common.HexToAddress(vrfCoordinatorAddr), e.Ec) @@ -330,34 +322,6 @@ func setPayees(e helpers.Environment, vrfBeaconAddr string, transmitters, payees helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) } -func setBeaconBilling(e helpers.Environment, vrfBeaconAddr string, maximumGasPrice, reasonableGasPrice, observationPayment, - transmissionPayment, accountingGas uint64) { - beacon := newVRFBeacon(common.HexToAddress(vrfBeaconAddr), e.Ec) - - tx, err := beacon.SetBilling(e.Owner, maximumGasPrice, reasonableGasPrice, observationPayment, transmissionPayment, big.NewInt(0).SetUint64(accountingGas)) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) -} - -func setCoordinatorBilling(e helpers.Environment, vrfCoordinatorAddr string, useReasonableGasPrice bool, unusedGasPenaltyPercent uint8, - stalenessSeconds, redeemableRequestGasOverhead, callbackRequestGasOverhead, premiumPercentage, reasonableGasPriceStalenessBlocks uint32, - fallbackWeiPerUnitLink *big.Int) { - coordinator := newVRFCoordinator(common.HexToAddress(vrfCoordinatorAddr), e.Ec) - - tx, err := coordinator.SetCoordinatorConfig(e.Owner, vrf_coordinator.VRFBeaconTypesCoordinatorConfig{ - UseReasonableGasPrice: useReasonableGasPrice, - UnusedGasPenaltyPercent: unusedGasPenaltyPercent, - StalenessSeconds: stalenessSeconds, - RedeemableRequestGasOverhead: redeemableRequestGasOverhead, - CallbackRequestGasOverhead: callbackRequestGasOverhead, - PremiumPercentage: uint8(premiumPercentage), - ReasonableGasPriceStalenessBlocks: reasonableGasPriceStalenessBlocks, - FallbackWeiPerUnitLink: fallbackWeiPerUnitLink, - }) - helpers.PanicErr(err) - helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) -} - func eoaFundSubscription(e helpers.Environment, coordinatorAddress, linkAddress string, amount, subID *big.Int) { linkToken, err := link_token_interface.NewLinkToken(common.HexToAddress(linkAddress), e.Ec) helpers.PanicErr(err) diff --git a/core/scripts/vrfv1/main.go b/core/scripts/vrfv1/main.go index 11af7a0efb2..a281a922a32 100644 --- a/core/scripts/vrfv1/main.go +++ b/core/scripts/vrfv1/main.go @@ -15,6 +15,7 @@ import ( "github.com/shopspring/decimal" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" linktoken "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" @@ -203,7 +204,7 @@ func main() { } link, err := linktoken.NewLinkToken(common.HexToAddress(*linkAddr), e.Ec) helpers.PanicErr(err) - data, err := utils.ABIEncode(`[{"type":"bytes32"}]`, common.HexToHash(*keyHash)) + data, err := evmutils.ABIEncode(`[{"type":"bytes32"}]`, common.HexToHash(*keyHash)) helpers.PanicErr(err) tx, err := link.TransferAndCall(e.Owner, common.HexToAddress(*consumerAddr), payment, data) helpers.PanicErr(err) diff --git a/core/scripts/vrfv2/genvrfnum/main.go b/core/scripts/vrfv2/genvrfnum/main.go index cdd120167f7..606ac7f3443 100644 --- a/core/scripts/vrfv2/genvrfnum/main.go +++ b/core/scripts/vrfv2/genvrfnum/main.go @@ -16,6 +16,7 @@ import ( "github.com/shopspring/decimal" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof" @@ -227,7 +228,7 @@ func main() { } func preseed(keyHash common.Hash, sender common.Address, subID, nonce uint64) [32]byte { - encoded, err := utils.ABIEncode( + encoded, err := evmutils.ABIEncode( `[{"type":"bytes32"}, {"type":"address"}, {"type":"uint64"}, {"type", "uint64"}]`, keyHash, sender, diff --git a/core/scripts/vrfv2/testnet/main.go b/core/scripts/vrfv2/testnet/main.go index 5856256504b..151549cc587 100644 --- a/core/scripts/vrfv2/testnet/main.go +++ b/core/scripts/vrfv2/testnet/main.go @@ -26,6 +26,7 @@ import ( helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" @@ -773,7 +774,7 @@ func main() { bal, err := linkToken.BalanceOf(nil, e.Owner.From) helpers.PanicErr(err) fmt.Println("OWNER BALANCE", bal, e.Owner.From.String(), amount.String()) - b, err := utils.ABIEncode(`[{"type":"uint64"}]`, created.SubId) + b, err := evmutils.ABIEncode(`[{"type":"uint64"}]`, created.SubId) helpers.PanicErr(err) e.Owner.GasLimit = 500000 tx, err := linkToken.TransferAndCall(e.Owner, coordinator.Address(), amount, b) @@ -1088,9 +1089,8 @@ func main() { return true } else if strings.Contains(err.Error(), "execution reverted") { return false - } else { - panic(err) } + panic(err) } result := helpers.BinarySearch(assets.Ether(int64(*start*2)).ToInt(), big.NewInt(0), isWithdrawable) diff --git a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go index 4a1c1fcec41..2608873fcfd 100644 --- a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go +++ b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/util" evmtypes "github.com/ethereum/go-ethereum/core/types" + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" @@ -297,7 +298,7 @@ func VRFV2DeployUniverse( tx, err := vrfOwner.SetAuthorizedSenders(e.Owner, authorizedSendersSlice) helpers.PanicErr(err) helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID, "vrf owner set authorized senders") - fmt.Printf("\nTransfering ownership of coordinator: %v, VRF Owner %v\n", contractAddresses.CoordinatorAddress, vrfOwnerAddress.String()) + fmt.Printf("\nTransferring ownership of coordinator: %v, VRF Owner %v\n", contractAddresses.CoordinatorAddress, vrfOwnerAddress.String()) tx, err = coordinator.TransferOwnership(e.Owner, vrfOwnerAddress) helpers.PanicErr(err) helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID, "transfer ownership to", vrfOwnerAddress.String()) @@ -320,9 +321,8 @@ func VRFV2DeployUniverse( func() string { if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 { return keys[0].Address - } else { - return common.HexToAddress("0x0").String() } + return common.HexToAddress("0x0").String() }(), contractAddresses.CoordinatorAddress, contractAddresses.CoordinatorAddress, @@ -347,9 +347,8 @@ func VRFV2DeployUniverse( func() string { if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 { return keys[0].Address - } else { - return common.HexToAddress("0x0").String() } + return common.HexToAddress("0x0").String() }(), contractAddresses.CoordinatorAddress, contractAddresses.CoordinatorAddress, diff --git a/core/scripts/vrfv2/testnet/v2scripts/util.go b/core/scripts/vrfv2/testnet/v2scripts/util.go index 94e381378bb..45cda3d2aa9 100644 --- a/core/scripts/vrfv2/testnet/v2scripts/util.go +++ b/core/scripts/vrfv2/testnet/v2scripts/util.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" @@ -22,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_external_sub_owner_example" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_wrapper_consumer_example" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func DeployBHS(e helpers.Environment) (blockhashStoreAddress common.Address) { diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go index 6b1ef585a5a..97d987dac29 100644 --- a/core/scripts/vrfv2plus/testnet/main.go +++ b/core/scripts/vrfv2plus/testnet/main.go @@ -31,6 +31,7 @@ import ( helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2plus" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" @@ -784,7 +785,7 @@ func main() { bal, err := linkToken.BalanceOf(nil, e.Owner.From) helpers.PanicErr(err) fmt.Println("OWNER BALANCE", bal, e.Owner.From.String(), amount.String()) - b, err := utils.ABIEncode(`[{"type":"uint64"}]`, created.SubId) + b, err := evmutils.ABIEncode(`[{"type":"uint64"}]`, created.SubId) helpers.PanicErr(err) e.Owner.GasLimit = 500000 tx, err := linkToken.TransferAndCall(e.Owner, coordinator.Address(), amount, b) @@ -1046,9 +1047,8 @@ func main() { return true } else if strings.Contains(err.Error(), "execution reverted") { return false - } else { - panic(err) } + panic(err) } result := helpers.BinarySearch(assets.Ether(int64(*start*2)).ToInt(), big.NewInt(0), isWithdrawable) @@ -1071,7 +1071,6 @@ func main() { coordinatorReregisterKey := flag.NewFlagSet("coordinator-register-key", flag.ExitOnError) coordinatorAddress := coordinatorReregisterKey.String("coordinator-address", "", "coordinator address") uncompressedPubKey := coordinatorReregisterKey.String("pubkey", "", "uncompressed pubkey") - newOracleAddress := coordinatorReregisterKey.String("new-oracle-address", "", "oracle address") skipDeregister := coordinatorReregisterKey.Bool("skip-deregister", false, "if true, key will not be deregistered") helpers.ParseArgs(coordinatorReregisterKey, os.Args[2:], "coordinator-address", "pubkey", "new-oracle-address") @@ -1097,7 +1096,6 @@ func main() { // Use a higher gas price for the register call e.Owner.GasPrice.Mul(e.Owner.GasPrice, big.NewInt(2)) registerTx, err := coordinator.RegisterProvingKey(e.Owner, - common.HexToAddress(*newOracleAddress), [2]*big.Int{pk.X, pk.Y}) helpers.PanicErr(err) fmt.Println("Register transaction", helpers.ExplorerLink(e.ChainID, registerTx.Hash())) diff --git a/core/scripts/vrfv2plus/testnet/proofs.go b/core/scripts/vrfv2plus/testnet/proofs.go index 126ac2d6c5a..306d237caf4 100644 --- a/core/scripts/vrfv2plus/testnet/proofs.go +++ b/core/scripts/vrfv2plus/testnet/proofs.go @@ -11,13 +11,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/shopspring/decimal" + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/extraargs" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof" ) -var vrfProofTemplate string = `{ +var vrfProofTemplate = `{ pk: [ %s, %s @@ -42,7 +43,7 @@ var vrfProofTemplate string = `{ } ` -var rcTemplate string = `{ +var rcTemplate = `{ blockNum: %d, subId: %d, callbackGasLimit: %d, diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go index 50584d885a2..65e4cca2abf 100644 --- a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go +++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go @@ -196,15 +196,15 @@ func SmokeTestVRF(e helpers.Environment) { x, y := secp256k1.Coordinates(point) fmt.Println("proving key points x:", x, ", y:", y) fmt.Println("proving key points from unmarshal:", pk.X, pk.Y) - tx, err := coordinator.RegisterProvingKey(e.Owner, e.Owner.From, [2]*big.Int{x, y}) + tx, err := coordinator.RegisterProvingKey(e.Owner, [2]*big.Int{x, y}) helpers.PanicErr(err) registerReceipt := helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID, "register proving key on", coordinatorAddress.String()) var provingKeyRegisteredLog *vrf_coordinator_v2_5.VRFCoordinatorV25ProvingKeyRegistered for _, log := range registerReceipt.Logs { if log.Address == coordinatorAddress { - var err error - provingKeyRegisteredLog, err = coordinator.ParseProvingKeyRegistered(*log) - if err != nil { + var err2 error + provingKeyRegisteredLog, err2 = coordinator.ParseProvingKeyRegistered(*log) + if err2 != nil { continue } } @@ -214,9 +214,8 @@ func SmokeTestVRF(e helpers.Environment) { } if !bytes.Equal(provingKeyRegisteredLog.KeyHash[:], keyHash[:]) { panic(fmt.Sprintf("unexpected key hash registered %s, expected %s", hexutil.Encode(provingKeyRegisteredLog.KeyHash[:]), hexutil.Encode(keyHash[:]))) - } else { - fmt.Println("key hash registered:", hexutil.Encode(provingKeyRegisteredLog.KeyHash[:])) } + fmt.Println("key hash registered:", hexutil.Encode(provingKeyRegisteredLog.KeyHash[:])) fmt.Println("\nProving key registered, getting proving key hashes from deployed contract...") _, _, provingKeyHashes, configErr := coordinator.GetRequestConfig(nil) @@ -268,6 +267,7 @@ func SmokeTestVRF(e helpers.Environment) { consumer, err := vrf_v2plus_sub_owner.NewVRFV2PlusExternalSubOwnerExample(consumerAddress, e.Ec) helpers.PanicErr(err) tx, err = consumer.RequestRandomWords(e.Owner, subID, 100_000, 3, 3, provingKeyRegisteredLog.KeyHash, false) + helpers.PanicErr(err) receipt := helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID, "request random words from", consumerAddress.String()) fmt.Println("request blockhash:", receipt.BlockHash) @@ -275,9 +275,9 @@ func SmokeTestVRF(e helpers.Environment) { var rwrLog *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested for _, log := range receipt.Logs { if log.Address == coordinatorAddress { - var err error - rwrLog, err = coordinator.ParseRandomWordsRequested(*log) - if err != nil { + var err2 error + rwrLog, err2 = coordinator.ParseRandomWordsRequested(*log) + if err2 != nil { continue } } @@ -396,13 +396,13 @@ func SmokeTestBHS(e helpers.Environment) { if seReceipt.Status != 1 { fmt.Println("storeEarliest failed") os.Exit(1) - } else { - fmt.Println("storeEarliest succeeded, checking BH is there") - bh, err := bhs.GetBlockhash(nil, seReceipt.BlockNumber.Sub(seReceipt.BlockNumber, big.NewInt(256))) - helpers.PanicErr(err) - fmt.Println("blockhash stored by storeEarliest:", hexutil.Encode(bh[:])) - anchorBlockNumber = seReceipt.BlockNumber } + fmt.Println("storeEarliest succeeded, checking BH is there") + bh, err := bhs.GetBlockhash(nil, seReceipt.BlockNumber.Sub(seReceipt.BlockNumber, big.NewInt(256))) + helpers.PanicErr(err) + fmt.Println("blockhash stored by storeEarliest:", hexutil.Encode(bh[:])) + anchorBlockNumber = seReceipt.BlockNumber + if anchorBlockNumber == nil { panic("no anchor block number") } @@ -417,12 +417,11 @@ func SmokeTestBHS(e helpers.Environment) { if sReceipt.Status != 1 { fmt.Println("store failed") os.Exit(1) - } else { - fmt.Println("store succeeded, checking BH is there") - bh, err := bhs.GetBlockhash(nil, toStore) - helpers.PanicErr(err) - fmt.Println("blockhash stored by store:", hexutil.Encode(bh[:])) } + fmt.Println("store succeeded, checking BH is there") + bh, err = bhs.GetBlockhash(nil, toStore) + helpers.PanicErr(err) + fmt.Println("blockhash stored by store:", hexutil.Encode(bh[:])) fmt.Println("\nexecuting storeVerifyHeader") headers, _, err := helpers.GetRlpHeaders(e, []*big.Int{anchorBlockNumber}, false) @@ -435,12 +434,11 @@ func SmokeTestBHS(e helpers.Environment) { if svhReceipt.Status != 1 { fmt.Println("storeVerifyHeader failed") os.Exit(1) - } else { - fmt.Println("storeVerifyHeader succeeded, checking BH is there") - bh, err := bhs.GetBlockhash(nil, toStore) - helpers.PanicErr(err) - fmt.Println("blockhash stored by storeVerifyHeader:", hexutil.Encode(bh[:])) } + fmt.Println("storeVerifyHeader succeeded, checking BH is there") + bh, err = bhs.GetBlockhash(nil, toStore) + helpers.PanicErr(err) + fmt.Println("blockhash stored by storeVerifyHeader:", hexutil.Encode(bh[:])) } func sendTx(e helpers.Environment, to common.Address, data []byte) (*types.Receipt, common.Hash) { @@ -501,7 +499,6 @@ func DeployUniverseViaCLI(e helpers.Environment) { fallbackWeiPerUnitLink := decimal.RequireFromString(*fallbackWeiPerUnitLinkString).BigInt() subscriptionBalanceJuels := decimal.RequireFromString(*subscriptionBalanceJuelsString).BigInt() subscriptionBalanceNativeWei := decimal.RequireFromString(*subscriptionBalanceNativeWeiString).BigInt() - fundingAmount := decimal.RequireFromString(*nodeSendingKeyFundingAmount).BigInt() feeConfig := vrf_coordinator_v2_5.VRFCoordinatorV25FeeConfig{ FulfillmentFlatFeeLinkPPM: uint32(*flatFeeLinkPPM), @@ -712,9 +709,8 @@ func VRFV2PlusDeployUniverse(e helpers.Environment, func() string { if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 { return keys[0].Address - } else { - return common.HexToAddress("0x0").String() } + return common.HexToAddress("0x0").String() }(), contractAddresses.CoordinatorAddress, contractAddresses.CoordinatorAddress, @@ -733,9 +729,8 @@ func VRFV2PlusDeployUniverse(e helpers.Environment, func() string { if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 { return keys[0].Address - } else { - return common.HexToAddress("0x0").String() } + return common.HexToAddress("0x0").String() }(), contractAddresses.CoordinatorAddress, contractAddresses.CoordinatorAddress, diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go index ebe881a9951..48b196b409f 100644 --- a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go +++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go @@ -4,14 +4,16 @@ import ( "context" "encoding/hex" "fmt" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" "math/big" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2plus" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" @@ -20,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_sub_owner" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_consumer_example" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func DeployBHS(e helpers.Environment) (blockhashStoreAddress common.Address) { @@ -181,7 +182,6 @@ func RegisterCoordinatorProvingKey(e helpers.Environment, pk, err := crypto.UnmarshalPubkey(pubBytes) helpers.PanicErr(err) tx, err := coordinator.RegisterProvingKey(e.Owner, - common.HexToAddress(oracleAddress), [2]*big.Int{pk.X, pk.Y}) helpers.PanicErr(err) helpers.ConfirmTXMined( diff --git a/core/services/blockhashstore/validate.go b/core/services/blockhashstore/validate.go index 82b813a37f4..62f90d326eb 100644 --- a/core/services/blockhashstore/validate.go +++ b/core/services/blockhashstore/validate.go @@ -7,8 +7,8 @@ import ( "github.com/pelletier/go-toml" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var EmptyAddress = utils.ZeroAddress.Hex() diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index ed043086586..fae938c0db6 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/static" @@ -27,6 +28,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" @@ -57,7 +59,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/sessions/ldapauth" "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/plugins" ) @@ -115,7 +116,6 @@ type Application interface { // in the services package, but the Store has its own package. type ChainlinkApplication struct { relayers *CoreRelayerChainInteroperators - EventBroadcaster pg.EventBroadcaster jobORM job.ORM jobSpawner job.Spawner pipelineORM pipeline.ORM @@ -129,7 +129,7 @@ type ChainlinkApplication struct { Config GeneralConfig KeyStore keystore.Master ExternalInitiatorManager webhook.ExternalInitiatorManager - SessionReaper utils.SleeperTask + SessionReaper *utils.SleeperTask shutdownOnce sync.Once srvcs []services.ServiceCtx HealthChecker services.Checker @@ -149,7 +149,6 @@ type ChainlinkApplication struct { type ApplicationOpts struct { Config GeneralConfig Logger logger.Logger - EventBroadcaster pg.EventBroadcaster MailMon *mailbox.Monitor SqlxDB *sqlx.DB KeyStore keystore.Master @@ -177,7 +176,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { db := opts.SqlxDB cfg := opts.Config relayerChainInterops := opts.RelayerChainInteroperators - eventBroadcaster := opts.EventBroadcaster mailMon := opts.MailMon externalInitiatorManager := opts.ExternalInitiatorManager globalLogger := logger.Sugared(opts.Logger) @@ -241,7 +239,9 @@ func NewApplication(opts ApplicationOpts) (Application, error) { } // pool must be started before all relayers and stopped after them - srvcs = append(srvcs, opts.MercuryPool) + if opts.MercuryPool != nil { + srvcs = append(srvcs, opts.MercuryPool) + } // EVM chains are used all over the place. This will need to change for fully EVM extraction // TODO: BCF-2510, BCF-2511 @@ -251,7 +251,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("no evm chains found") } - srvcs = append(srvcs, eventBroadcaster, mailMon) + srvcs = append(srvcs, mailMon) srvcs = append(srvcs, relayerChainInterops.Services()...) promReporter := promreporter.NewPromReporter(db.DB, legacyEVMChains, globalLogger) srvcs = append(srvcs, promReporter) @@ -264,7 +264,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { // localDB auth or remote LDAP auth authMethod := cfg.WebServer().AuthenticationMethod() var authenticationProvider sessions.AuthenticationProvider - var sessionReaper utils.SleeperTask + var sessionReaper *utils.SleeperTask switch sessions.AuthenticationProviderName(authMethod) { case sessions.LDAPAuth: @@ -341,6 +341,8 @@ func NewApplication(opts ApplicationOpts) (Application, error) { job.Gateway: gateway.NewDelegate( legacyEVMChains, keyStore.Eth(), + db, + cfg.Database(), globalLogger), } webhookJobRunner = delegates[job.Webhook].(*webhook.Delegate).WebhookJobRunner() @@ -411,7 +413,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { keyStore.Eth(), opts.RelayerChainInteroperators, mailMon, - eventBroadcaster, ) delegates[job.Bootstrap] = ocrbootstrap.NewDelegateBootstrap( db, @@ -476,7 +477,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return &ChainlinkApplication{ relayers: opts.RelayerChainInteroperators, - EventBroadcaster: eventBroadcaster, jobORM: jobORM, jobSpawner: jobSpawner, pipelineRunner: pipelineRunner, @@ -738,14 +738,14 @@ func (app *ChainlinkApplication) RunJobV2( Data: bytes.Join([][]byte{ jb.VRFSpec.PublicKey.MustHash().Bytes(), // key hash common.BigToHash(big.NewInt(42)).Bytes(), // seed - utils.NewHash().Bytes(), // sender - utils.NewHash().Bytes(), // fee - utils.NewHash().Bytes()}, // requestID + evmutils.NewHash().Bytes(), // sender + evmutils.NewHash().Bytes(), // fee + evmutils.NewHash().Bytes()}, // requestID []byte{}), Topics: []common.Hash{{}, jb.ExternalIDEncodeBytesToTopic()}, // jobID BYTES - TxHash: utils.NewHash(), + TxHash: evmutils.NewHash(), BlockNumber: 10, - BlockHash: utils.NewHash(), + BlockHash: evmutils.NewHash(), } vars = map[string]interface{}{ "jobSpec": map[string]interface{}{ @@ -805,10 +805,6 @@ func (app *ChainlinkApplication) GetRelayers() RelayerChainInteroperators { return app.relayers } -func (app *ChainlinkApplication) GetEventBroadcaster() pg.EventBroadcaster { - return app.EventBroadcaster -} - func (app *ChainlinkApplication) GetSqlxDB() *sqlx.DB { return app.sqlxDB } diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go index 5df2b177bdd..cb68ed0e72d 100644 --- a/core/services/chainlink/config_general.go +++ b/core/services/chainlink/config_general.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-solana/pkg/solana" starknet "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/config" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" @@ -26,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" - configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) // generalConfig is a wrapper to adapt Config to the config.GeneralConfig interface. @@ -97,7 +97,7 @@ func (o *GeneralConfigOpts) Setup(configFiles []string, secretsFiles []string) e // parseConfig sets Config from the given TOML string, overriding any existing duplicate Config fields. func (o *GeneralConfigOpts) parseConfig(config string) error { var c Config - if err2 := configutils.DecodeTOML(strings.NewReader(config), &c); err2 != nil { + if err2 := commonconfig.DecodeTOML(strings.NewReader(config), &c); err2 != nil { return fmt.Errorf("failed to decode config TOML: %w", err2) } @@ -111,7 +111,7 @@ func (o *GeneralConfigOpts) parseConfig(config string) error { // parseSecrets sets Secrets from the given TOML string. Errors on overrides func (o *GeneralConfigOpts) parseSecrets(secrets string) error { var s Secrets - if err2 := configutils.DecodeTOML(strings.NewReader(secrets), &s); err2 != nil { + if err2 := commonconfig.DecodeTOML(strings.NewReader(secrets), &s); err2 != nil { return fmt.Errorf("failed to decode secrets TOML: %w", err2) } diff --git a/core/services/chainlink/config_general_test.go b/core/services/chainlink/config_general_test.go index c122f8f968c..444f34abcbb 100644 --- a/core/services/chainlink/config_general_test.go +++ b/core/services/chainlink/config_general_test.go @@ -14,9 +14,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) func TestTOMLGeneralConfig_Defaults(t *testing.T) { diff --git a/core/services/chainlink/config_mercury.go b/core/services/chainlink/config_mercury.go index 61e48d340e4..49f1cf0a5f4 100644 --- a/core/services/chainlink/config_mercury.go +++ b/core/services/chainlink/config_mercury.go @@ -24,6 +24,14 @@ func (m *mercuryCacheConfig) LatestReportDeadline() time.Duration { return m.c.LatestReportDeadline.Duration() } +type mercuryTLSConfig struct { + c toml.MercuryTLS +} + +func (m *mercuryTLSConfig) CertFile() string { + return *m.c.CertFile +} + type mercuryConfig struct { c toml.Mercury s toml.MercurySecrets @@ -47,3 +55,7 @@ func (m *mercuryConfig) Credentials(credName string) *models.MercuryCredentials func (m *mercuryConfig) Cache() config.MercuryCache { return &mercuryCacheConfig{c: m.c.Cache} } + +func (m *mercuryConfig) TLS() config.MercuryTLS { + return &mercuryTLSConfig{c: m.c.TLS} +} diff --git a/core/services/chainlink/config_mercury_test.go b/core/services/chainlink/config_mercury_test.go index 58019a91557..71dfb2a01ce 100644 --- a/core/services/chainlink/config_mercury_test.go +++ b/core/services/chainlink/config_mercury_test.go @@ -7,6 +7,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" + + "github.com/smartcontractkit/chainlink/v2/core/config/toml" ) const ( @@ -34,3 +36,15 @@ func TestMercuryConfig(t *testing.T) { assert.Equal(t, &models.MercuryCredentials{URL: "https://chain1.link", Username: "username1", Password: "password1"}, m.Credentials("cred1")) assert.Equal(t, &models.MercuryCredentials{URL: "https://chain2.link", Username: "username2", Password: "password2"}, m.Credentials("cred2")) } + +func TestMercuryTLS(t *testing.T) { + certPath := "/path/to/cert.pem" + transmission := toml.Mercury{ + TLS: toml.MercuryTLS{ + CertFile: &certPath, + }, + } + cfg := mercuryConfig{c: transmission} + + assert.Equal(t, certPath, cfg.TLS().CertFile()) +} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 85a4c99b862..10ab00e8bd0 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -3,6 +3,7 @@ package chainlink import ( _ "embed" "math" + "math/big" "net" "strings" "testing" @@ -17,7 +18,9 @@ import ( ocrcommontypes "github.com/smartcontractkit/libocr/commontypes" commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink-common/pkg/config" commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" @@ -26,7 +29,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" legacy "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/toml" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -35,7 +38,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) var ( @@ -96,7 +98,7 @@ var ( }, EVM: []*evmcfg.EVMConfig{ { - ChainID: big.NewI(1), + ChainID: ubig.NewI(1), Chain: evmcfg.Chain{ FinalityDepth: ptr[uint32](26), FinalityTagEnabled: ptr[bool](false), @@ -113,7 +115,7 @@ var ( }, }}, { - ChainID: big.NewI(42), + ChainID: ubig.NewI(42), Chain: evmcfg.Chain{ GasEstimator: evmcfg.GasEstimator{ PriceDefault: assets.NewWeiI(math.MaxInt64), @@ -126,7 +128,7 @@ var ( }, }}, { - ChainID: big.NewI(137), + ChainID: ubig.NewI(137), Chain: evmcfg.Chain{ GasEstimator: evmcfg.GasEstimator{ Mode: ptr("FixedPrice"), @@ -464,7 +466,7 @@ func TestConfig_Marshal(t *testing.T) { } full.EVM = []*evmcfg.EVMConfig{ { - ChainID: big.NewI(1), + ChainID: ubig.NewI(1), Enabled: ptr(false), Chain: evmcfg.Chain{ AutoCreateKey: ptr(false), @@ -493,7 +495,7 @@ func TestConfig_Marshal(t *testing.T) { TipCapDefault: assets.NewWeiI(2), TipCapMin: assets.NewWeiI(1), PriceDefault: assets.NewWeiI(math.MaxInt64), - PriceMax: assets.NewWei(utils.HexToBig("FFFFFFFFFFFF")), + PriceMax: assets.NewWei(mustHexToBig(t, "FFFFFFFFFFFF")), PriceMin: assets.NewWeiI(13), LimitJobType: evmcfg.GasLimitJobType{ @@ -519,7 +521,7 @@ func TestConfig_Marshal(t *testing.T) { { Key: mustAddress("0x2a3e23c6f242F5345320814aC8a1b4E58707D292"), GasEstimator: evmcfg.KeySpecificGasEstimator{ - PriceMax: assets.NewWei(utils.HexToBig("FFFFFFFFFFFFFFFFFFFFFFFF")), + PriceMax: assets.NewWei(mustHexToBig(t, "FFFFFFFFFFFFFFFFFFFFFFFF")), }, }, }, @@ -664,6 +666,9 @@ func TestConfig_Marshal(t *testing.T) { MaxStaleAge: models.MustNewDuration(101 * time.Second), LatestReportDeadline: models.MustNewDuration(102 * time.Second), }, + TLS: toml.MercuryTLS{ + CertFile: ptr("/path/to/cert.pem"), + }, } for _, tt := range []struct { @@ -1095,6 +1100,9 @@ URL = 'http://stark.node' LatestReportTTL = '1m40s' MaxStaleAge = '1m41s' LatestReportDeadline = '1m42s' + +[Mercury.TLS] +CertFile = '/path/to/cert.pem' `}, {"full", full, fullTOML}, {"multi-chain", multiChain, multiChainTOML}, @@ -1467,7 +1475,7 @@ func assertValidationError(t *testing.T, invalid interface{ Validate() error }, func TestConfig_setDefaults(t *testing.T) { var c Config - c.EVM = evmcfg.EVMConfigs{{ChainID: big.NewI(99999133712345)}} + c.EVM = evmcfg.EVMConfigs{{ChainID: ubig.NewI(99999133712345)}} c.Cosmos = coscfg.TOMLConfigs{{ChainID: ptr("unknown cosmos chain")}} c.Solana = solana.TOMLConfigs{{ChainID: ptr("unknown solana chain")}} c.Starknet = stkcfg.TOMLConfigs{{ChainID: ptr("unknown starknet chain")}} @@ -1562,3 +1570,9 @@ func TestConfig_warnings(t *testing.T) { } func ptr[T any](t T) *T { return &t } + +func mustHexToBig(t *testing.T, hx string) *big.Int { + n, err := hex.ParseBig(hx) + require.NoError(t, err) + return n +} diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index d89fbce12db..6f6e3afce31 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -25,7 +25,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/relay" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/plugins" @@ -206,10 +205,9 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { initFuncs: []chainlink.CoreRelayerChainInitFunc{ chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{ ChainOpts: legacyevm.ChainOpts{ - AppConfig: cfg, - EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &mailbox.Monitor{}, - DB: db, + AppConfig: cfg, + MailMon: &mailbox.Monitor{}, + DB: db, }, CSAETHKeystore: keyStore, }), @@ -280,10 +278,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { TOMLConfigs: cfg.SolanaConfigs()}), chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{ ChainOpts: legacyevm.ChainOpts{ - AppConfig: cfg, - EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &mailbox.Monitor{}, - DB: db, + AppConfig: cfg, + + MailMon: &mailbox.Monitor{}, + DB: db, }, CSAETHKeystore: keyStore, }), diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index b4bd530d080..49582e2d52a 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -67,11 +67,10 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m } relayerOpts := evmrelay.RelayerOpts{ - DB: ccOpts.DB, - QConfig: ccOpts.AppConfig.Database(), - CSAETHKeystore: config.CSAETHKeystore, - EventBroadcaster: ccOpts.EventBroadcaster, - MercuryPool: r.MercuryPool, + DB: ccOpts.DB, + QConfig: ccOpts.AppConfig.Database(), + CSAETHKeystore: config.CSAETHKeystore, + MercuryPool: r.MercuryPool, } relayer, err2 := evmrelay.NewRelayer(lggr.Named(relayID.ChainID), chain, relayerOpts) if err2 != nil { diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index 9efad05c03a..cc4dddcf8af 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -227,3 +227,6 @@ TLSCertPath = '' LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' + +[Mercury.TLS] +CertFile = '' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index c6387e4ef67..da8b68cfdb1 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -238,6 +238,9 @@ LatestReportTTL = '1m40s' MaxStaleAge = '1m41s' LatestReportDeadline = '1m42s' +[Mercury.TLS] +CertFile = '/path/to/cert.pem' + [[EVM]] ChainID = '1' Enabled = false diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 40c18f28eb9..d5352a685c4 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -228,6 +228,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index be61cde4d60..3b80ba2f915 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -15,7 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -45,7 +45,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { c.EVM[0].MinIncomingConfirmations = ptr[uint32](1) }) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, MailMon: mailMon, KeyStore: keyStore.Eth()}) lggr := logger.TestLogger(t) @@ -82,7 +82,7 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi runner := pipeline_mocks.NewRunner(t) broadcaster.On("AddDependents", 1) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go index 02b9e24739c..88d3b132beb 100644 --- a/core/services/feeds/orm_test.go +++ b/core/services/feeds/orm_test.go @@ -12,6 +12,7 @@ import ( "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" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -24,7 +25,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) diff --git a/core/services/fluxmonitorv2/flags.go b/core/services/fluxmonitorv2/flags.go index bad5a1f2752..c50a767ae1c 100644 --- a/core/services/fluxmonitorv2/flags.go +++ b/core/services/fluxmonitorv2/flags.go @@ -7,9 +7,9 @@ import ( "github.com/ethereum/go-ethereum/core/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name Flags --output ./mocks/ --case=underscore --structname Flags --filename flags.go diff --git a/core/services/fluxmonitorv2/flags_test.go b/core/services/fluxmonitorv2/flags_test.go index 99d182a9671..c00c439d859 100644 --- a/core/services/fluxmonitorv2/flags_test.go +++ b/core/services/fluxmonitorv2/flags_test.go @@ -7,10 +7,10 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestFlags_IsLowered(t *testing.T) { diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go index 79dd44c8014..8fe0fc7c70e 100644 --- a/core/services/fluxmonitorv2/flux_monitor.go +++ b/core/services/fluxmonitorv2/flux_monitor.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -338,12 +339,12 @@ func (fm *FluxMonitor) HandleLog(broadcast log.Broadcast) { fm.backlog.Add(PriorityAnswerUpdatedLog, broadcast) case *flags_wrapper.FlagsFlagRaised: - if log.Subject == utils.ZeroAddress || log.Subject == fm.contractAddress { + if log.Subject == evmutils.ZeroAddress || log.Subject == fm.contractAddress { fm.backlog.Add(PriorityFlagChangedLog, broadcast) } case *flags_wrapper.FlagsFlagLowered: - if log.Subject == utils.ZeroAddress || log.Subject == fm.contractAddress { + if log.Subject == evmutils.ZeroAddress || log.Subject == fm.contractAddress { fm.backlog.Add(PriorityFlagChangedLog, broadcast) } diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index 729bcd76eba..48c9ca24ac3 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -29,6 +29,7 @@ import ( "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" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" faw "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" @@ -667,7 +668,7 @@ ds1 -> ds1_parse s = fmt.Sprintf(s, fa.aggregatorContractAddress, testutils.SimulatedChainID.String(), pollTimerPeriod, mockServer.URL) // raise flags to disable polling - _, err = fa.flagsContract.RaiseFlag(fa.sergey, utils.ZeroAddress) // global kill switch + _, err = fa.flagsContract.RaiseFlag(fa.sergey, evmutils.ZeroAddress) // global kill switch require.NoError(t, err) _, err = fa.flagsContract.RaiseFlag(fa.sergey, fa.aggregatorContractAddress) require.NoError(t, err) @@ -776,7 +777,7 @@ ds1 -> ds1_parse s = fmt.Sprintf(s, fa.aggregatorContractAddress, testutils.SimulatedChainID.String(), "1000ms", mockServer.URL) // raise flags - _, err = fa.flagsContract.RaiseFlag(fa.sergey, utils.ZeroAddress) // global kill switch + _, err = fa.flagsContract.RaiseFlag(fa.sergey, evmutils.ZeroAddress) // global kill switch require.NoError(t, err) _, err = fa.flagsContract.RaiseFlag(fa.sergey, fa.aggregatorContractAddress) @@ -795,7 +796,7 @@ ds1 -> ds1_parse cltest.AssertPipelineRunsStays(t, j.PipelineSpec.ID, app.GetSqlxDB(), 0) // lower global kill switch flag - should trigger job run - _, err = fa.flagsContract.LowerFlags(fa.sergey, []common.Address{utils.ZeroAddress}) + _, err = fa.flagsContract.LowerFlags(fa.sergey, []common.Address{evmutils.ZeroAddress}) require.NoError(t, err) fa.backend.Commit() awaitSubmission(t, fa.backend, submissionReceived) @@ -816,7 +817,7 @@ ds1 -> ds1_parse // raise both flags _, err = fa.flagsContract.RaiseFlag(fa.sergey, fa.aggregatorContractAddress) require.NoError(t, err) - _, err = fa.flagsContract.RaiseFlag(fa.sergey, utils.ZeroAddress) + _, err = fa.flagsContract.RaiseFlag(fa.sergey, evmutils.ZeroAddress) require.NoError(t, err) fa.backend.Commit() @@ -887,7 +888,7 @@ ds1 -> ds1_parse s := fmt.Sprintf(toml, fa.aggregatorContractAddress, testutils.SimulatedChainID.String(), "100ms", mockServer.URL) // raise flags - _, err = fa.flagsContract.RaiseFlag(fa.sergey, utils.ZeroAddress) // global kill switch + _, err = fa.flagsContract.RaiseFlag(fa.sergey, evmutils.ZeroAddress) // global kill switch require.NoError(t, err) _, err = fa.flagsContract.RaiseFlag(fa.sergey, fa.aggregatorContractAddress) require.NoError(t, err) diff --git a/core/services/functions/external_adapter_client.go b/core/services/functions/external_adapter_client.go index db4fed30e5f..fb64924a922 100644 --- a/core/services/functions/external_adapter_client.go +++ b/core/services/functions/external_adapter_client.go @@ -14,8 +14,8 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ExternalAdapterClient supports two endpoints: @@ -228,13 +228,13 @@ func (ea *externalAdapterClient) request( switch eaResp.Result { case "error": - userError, err = utils.TryParseHex(eaResp.Data.Error) + userError, err = hex.DecodeString(eaResp.Data.Error) if err != nil { return nil, nil, nil, errors.Wrap(err, "error decoding userError hex string") } return nil, userError, eaResp.Data.Domains, nil case "success": - userResult, err = utils.TryParseHex(eaResp.Data.Result) + userResult, err = hex.DecodeString(eaResp.Data.Result) if err != nil { return nil, nil, nil, errors.Wrap(err, "error decoding result hex string") } diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go index 07bd82ed288..5d26f9a4f57 100644 --- a/core/services/functions/listener_test.go +++ b/core/services/functions/listener_test.go @@ -20,7 +20,7 @@ import ( decryptionPlugin "github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -82,7 +82,7 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe ethClient := evmtest.NewEthClientMockWithDefaultChain(t) broadcaster := log_mocks.NewBroadcaster(t) broadcaster.On("AddDependents", 1) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) db := pgtest.NewSqlxDB(t) kst := cltest.NewKeyStore(t, db, cfg.Database()) diff --git a/core/services/gateway/api/message.go b/core/services/gateway/api/message.go index d0a116675ae..c01d3bb9f2e 100644 --- a/core/services/gateway/api/message.go +++ b/core/services/gateway/api/message.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" gw_common "github.com/smartcontractkit/chainlink/v2/core/services/gateway/common" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -97,7 +98,7 @@ func (m *Message) ExtractSigner() (signerAddress []byte, err error) { return nil, errors.New("nil message") } rawData := getRawMessageBody(&m.Body) - signatureBytes, err := utils.TryParseHex(m.Signature) + signatureBytes, err := hex.DecodeString(m.Signature) if err != nil { return nil, err } diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go index 27db8fd44b6..6b399733a58 100644 --- a/core/services/gateway/connector/connector.go +++ b/core/services/gateway/connector/connector.go @@ -11,6 +11,7 @@ import ( "github.com/gorilla/websocket" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" @@ -85,7 +86,7 @@ func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler Gateway if len(config.DonId) == 0 || len(config.DonId) > int(network.HandshakeDonIdLen) { return nil, errors.New("invalid DON ID") } - addressBytes, err := utils.TryParseHex(config.NodeAddress) + addressBytes, err := hex.DecodeString(config.NodeAddress) if err != nil { return nil, err } diff --git a/core/services/gateway/delegate.go b/core/services/gateway/delegate.go index d4180184aca..8a97f68d1ea 100644 --- a/core/services/gateway/delegate.go +++ b/core/services/gateway/delegate.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/google/uuid" + "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml" "github.com/pkg/errors" @@ -18,13 +19,21 @@ import ( type Delegate struct { legacyChains legacyevm.LegacyChainContainer ks keystore.Eth + db *sqlx.DB + cfg pg.QConfig lggr logger.Logger } var _ job.Delegate = (*Delegate)(nil) -func NewDelegate(legacyChains legacyevm.LegacyChainContainer, ks keystore.Eth, lggr logger.Logger) *Delegate { - return &Delegate{legacyChains: legacyChains, ks: ks, lggr: lggr} +func NewDelegate(legacyChains legacyevm.LegacyChainContainer, ks keystore.Eth, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) *Delegate { + return &Delegate{ + legacyChains: legacyChains, + ks: ks, + db: db, + cfg: cfg, + lggr: lggr, + } } func (d *Delegate) JobType() job.Type { @@ -47,7 +56,7 @@ func (d *Delegate) ServicesForSpec(spec job.Job) (services []job.ServiceCtx, err if err2 != nil { return nil, errors.Wrap(err2, "unmarshal gateway config") } - handlerFactory := NewHandlerFactory(d.legacyChains, d.lggr) + handlerFactory := NewHandlerFactory(d.legacyChains, d.db, d.cfg, 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 74d689fffe1..1c31a643c80 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, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, 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, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, 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, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, 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, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, 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, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, 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, lggr), lggr) + gateway, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, buildConfig("")), gateway.NewHandlerFactory(nil, 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 368bc64c872..8ccae8c7c4b 100644 --- a/core/services/gateway/handler_factory.go +++ b/core/services/gateway/handler_factory.go @@ -4,11 +4,14 @@ import ( "encoding/json" "fmt" + "github.com/jmoiron/sqlx" + "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 ( @@ -18,19 +21,21 @@ const ( type handlerFactory struct { legacyChains legacyevm.LegacyChainContainer + db *sqlx.DB + cfg pg.QConfig lggr logger.Logger } var _ HandlerFactory = (*handlerFactory)(nil) -func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger) HandlerFactory { - return &handlerFactory{legacyChains, lggr} +func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) HandlerFactory { + return &handlerFactory{legacyChains, db, cfg, 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.lggr) + return functions.NewFunctionsHandlerFromConfig(handlerConfig, donConfig, don, hf.legacyChains, hf.db, hf.cfg, hf.lggr) case DummyHandlerType: return handlers.NewDummyHandler(donConfig, don, hf.lggr) default: diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go index 5277f9789d6..2872c72f761 100644 --- a/core/services/gateway/handlers/functions/handler.functions.go +++ b/core/services/gateway/handlers/functions/handler.functions.go @@ -10,6 +10,7 @@ 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" @@ -22,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers" hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" + "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) var ( @@ -96,7 +98,7 @@ type PendingRequest struct { var _ handlers.Handler = (*functionsHandler)(nil) -func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON, legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger) (handlers.Handler, error) { +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) { var cfg FunctionsHandlerConfig err := json.Unmarshal(handlerConfig, &cfg) if err != nil { @@ -133,7 +135,13 @@ func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *con if err2 != nil { return nil, err2 } - subscriptions, err2 = NewOnchainSubscriptions(chain.Client(), *cfg.OnchainSubscriptions, lggr) + + orm, err2 := NewORM(db, lggr, qcfg, cfg.OnchainSubscriptions.ContractAddress) + if err2 != nil { + return nil, err2 + } + + subscriptions, err2 = NewOnchainSubscriptions(chain.Client(), *cfg.OnchainSubscriptions, orm, lggr) 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 1d6dd109625..7e055815c88 100644 --- a/core/services/gateway/handlers/functions/handler.functions_test.go +++ b/core/services/gateway/handlers/functions/handler.functions_test.go @@ -83,7 +83,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, logger.TestLogger(t)) + handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, nil, logger.TestLogger(t)) require.NoError(t, err) // empty message should always error out @@ -95,7 +95,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, logger.TestLogger(t)) + handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, nil, logger.TestLogger(t)) require.NoError(t, err) servicetest.Run(t, handler) diff --git a/core/services/gateway/handlers/functions/mocks/orm.go b/core/services/gateway/handlers/functions/mocks/orm.go new file mode 100644 index 00000000000..110675c8b55 --- /dev/null +++ b/core/services/gateway/handlers/functions/mocks/orm.go @@ -0,0 +1,91 @@ +// Code generated by mockery v2.38.0. DO NOT EDIT. + +package mocks + +import ( + functions "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" + mock "github.com/stretchr/testify/mock" + + pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" +) + +// ORM is an autogenerated mock type for the ORM type +type ORM struct { + mock.Mock +} + +// GetSubscriptions provides a mock function with given fields: offset, limit, qopts +func (_m *ORM) GetSubscriptions(offset uint, limit uint, qopts ...pg.QOpt) ([]functions.CachedSubscription, error) { + _va := make([]interface{}, len(qopts)) + for _i := range qopts { + _va[_i] = qopts[_i] + } + var _ca []interface{} + _ca = append(_ca, offset, limit) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetSubscriptions") + } + + var r0 []functions.CachedSubscription + var r1 error + if rf, ok := ret.Get(0).(func(uint, uint, ...pg.QOpt) ([]functions.CachedSubscription, error)); ok { + return rf(offset, limit, qopts...) + } + if rf, ok := ret.Get(0).(func(uint, uint, ...pg.QOpt) []functions.CachedSubscription); ok { + r0 = rf(offset, limit, qopts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]functions.CachedSubscription) + } + } + + if rf, ok := ret.Get(1).(func(uint, uint, ...pg.QOpt) error); ok { + r1 = rf(offset, limit, qopts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpsertSubscription provides a mock function with given fields: subscription, qopts +func (_m *ORM) UpsertSubscription(subscription functions.CachedSubscription, qopts ...pg.QOpt) error { + _va := make([]interface{}, len(qopts)) + for _i := range qopts { + _va[_i] = qopts[_i] + } + var _ca []interface{} + _ca = append(_ca, subscription) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for UpsertSubscription") + } + + var r0 error + if rf, ok := ret.Get(0).(func(functions.CachedSubscription, ...pg.QOpt) error); ok { + r0 = rf(subscription, qopts...) + } else { + r0 = ret.Error(0) + } + + 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. +// The first argument is typically a *testing.T value. +func NewORM(t interface { + mock.TestingT + Cleanup(func()) +}) *ORM { + mock := &ORM{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/gateway/handlers/functions/orm.go b/core/services/gateway/handlers/functions/orm.go new file mode 100644 index 00000000000..b7ec8d865d1 --- /dev/null +++ b/core/services/gateway/handlers/functions/orm.go @@ -0,0 +1,132 @@ +package functions + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/lib/pq" + "github.com/pkg/errors" + + "github.com/jmoiron/sqlx" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/pg" +) + +//go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore + +type ORM interface { + GetSubscriptions(offset, limit uint, qopts ...pg.QOpt) ([]CachedSubscription, error) + UpsertSubscription(subscription CachedSubscription, qopts ...pg.QOpt) error +} + +type orm struct { + q pg.Q + routerContractAddress common.Address +} + +var _ ORM = (*orm)(nil) +var ( + ErrInvalidParameters = errors.New("invalid parameters provided to create a subscription cache ORM") +) + +const ( + tableName = "functions_subscriptions" +) + +type cachedSubscriptionRow struct { + SubscriptionID uint64 + Owner common.Address + Balance int64 + BlockedBalance int64 + ProposedOwner common.Address + Consumers pq.ByteaArray + Flags []uint8 + RouterContractAddress common.Address +} + +func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, routerContractAddress common.Address) (ORM, error) { + if db == nil || cfg == nil || lggr == nil || routerContractAddress == (common.Address{}) { + return nil, ErrInvalidParameters + } + + return &orm{ + q: pg.NewQ(db, lggr, cfg), + routerContractAddress: routerContractAddress, + }, nil +} + +func (o *orm) GetSubscriptions(offset, limit uint, qopts ...pg.QOpt) ([]CachedSubscription, error) { + var cacheSubscriptions []CachedSubscription + var cacheSubscriptionRows []cachedSubscriptionRow + stmt := fmt.Sprintf(` + SELECT subscription_id, owner, balance, blocked_balance, proposed_owner, consumers, flags, router_contract_address + FROM %s + WHERE router_contract_address = $1 + ORDER BY subscription_id ASC + OFFSET $2 + LIMIT $3; + `, tableName) + err := o.q.WithOpts(qopts...).Select(&cacheSubscriptionRows, stmt, o.routerContractAddress, offset, limit) + if err != nil { + return cacheSubscriptions, err + } + + for _, cs := range cacheSubscriptionRows { + cacheSubscriptions = append(cacheSubscriptions, cs.encode()) + } + + return cacheSubscriptions, nil +} + +// UpsertSubscription will update if a subscription exists or create if it does not. +// In case a subscription gets deleted we will update it with an owner address equal to 0x0. +func (o *orm) UpsertSubscription(subscription CachedSubscription, qopts ...pg.QOpt) error { + stmt := fmt.Sprintf(` + INSERT INTO %s (subscription_id, owner, balance, blocked_balance, proposed_owner, consumers, flags, router_contract_address) + VALUES ($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT (subscription_id, router_contract_address) DO UPDATE + SET owner=$2, balance=$3, blocked_balance=$4, proposed_owner=$5, consumers=$6, flags=$7, router_contract_address=$8;`, tableName) + + if subscription.Balance == nil { + subscription.Balance = big.NewInt(0) + } + + if subscription.BlockedBalance == nil { + subscription.BlockedBalance = big.NewInt(0) + } + + _, err := o.q.WithOpts(qopts...).Exec( + stmt, + subscription.SubscriptionID, + subscription.Owner, + subscription.Balance.Int64(), + subscription.BlockedBalance.Int64(), + subscription.ProposedOwner, + subscription.Consumers, + subscription.Flags[:], + o.routerContractAddress, + ) + + return err +} + +func (cs *cachedSubscriptionRow) encode() CachedSubscription { + consumers := make([]common.Address, 0) + for _, csc := range cs.Consumers { + consumers = append(consumers, common.BytesToAddress(csc)) + } + + return CachedSubscription{ + SubscriptionID: cs.SubscriptionID, + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: big.NewInt(cs.Balance), + Owner: cs.Owner, + BlockedBalance: big.NewInt(cs.BlockedBalance), + ProposedOwner: cs.ProposedOwner, + Consumers: consumers, + Flags: [32]byte(cs.Flags), + }, + } +} diff --git a/core/services/gateway/handlers/functions/orm_test.go b/core/services/gateway/handlers/functions/orm_test.go new file mode 100644 index 00000000000..37ec24ea0b1 --- /dev/null +++ b/core/services/gateway/handlers/functions/orm_test.go @@ -0,0 +1,246 @@ +package functions_test + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" + "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/gateway/handlers/functions" +) + +var ( + defaultFlags = [32]byte{0x1, 0x2, 0x3} +) + +func setupORM(t *testing.T) (functions.ORM, error) { + t.Helper() + + var ( + db = pgtest.NewSqlxDB(t) + lggr = logger.TestLogger(t) + ) + + return functions.NewORM(db, lggr, pgtest.NewQConfig(true), testutils.NewAddress()) +} + +func createSubscriptions(t *testing.T, orm functions.ORM, amount int) []functions.CachedSubscription { + cachedSubscriptions := make([]functions.CachedSubscription, 0) + for i := amount; i > 0; i-- { + cs := functions.CachedSubscription{ + SubscriptionID: uint64(i), + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: big.NewInt(10), + Owner: testutils.NewAddress(), + BlockedBalance: big.NewInt(20), + ProposedOwner: common.Address{}, + Consumers: []common.Address{}, + Flags: defaultFlags, + }, + } + cachedSubscriptions = append(cachedSubscriptions, cs) + err := orm.UpsertSubscription(cs) + require.NoError(t, err) + } + return cachedSubscriptions +} + +func TestORM_GetSubscriptions(t *testing.T) { + t.Parallel() + t.Run("fetch first page", func(t *testing.T) { + orm, err := setupORM(t) + require.NoError(t, err) + cachedSubscriptions := createSubscriptions(t, orm, 2) + results, err := orm.GetSubscriptions(0, 1) + require.NoError(t, err) + require.Equal(t, 1, len(results), "incorrect results length") + require.Equal(t, cachedSubscriptions[1], results[0]) + }) + + t.Run("fetch second page", func(t *testing.T) { + orm, err := setupORM(t) + require.NoError(t, err) + cachedSubscriptions := createSubscriptions(t, orm, 2) + results, err := orm.GetSubscriptions(1, 5) + require.NoError(t, err) + require.Equal(t, 1, len(results), "incorrect results length") + require.Equal(t, cachedSubscriptions[0], results[0]) + }) +} + +func TestORM_UpsertSubscription(t *testing.T) { + t.Parallel() + + t.Run("create a subscription", func(t *testing.T) { + orm, err := setupORM(t) + require.NoError(t, err) + expected := functions.CachedSubscription{ + SubscriptionID: uint64(1), + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: big.NewInt(10), + Owner: testutils.NewAddress(), + BlockedBalance: big.NewInt(20), + ProposedOwner: common.Address{}, + Consumers: []common.Address{}, + Flags: defaultFlags, + }, + } + err = orm.UpsertSubscription(expected) + require.NoError(t, err) + + results, err := orm.GetSubscriptions(0, 1) + require.NoError(t, err) + require.Equal(t, 1, len(results), "incorrect results length") + require.Equal(t, expected, results[0]) + }) + + t.Run("update a subscription", func(t *testing.T) { + orm, err := setupORM(t) + require.NoError(t, err) + + expectedUpdated := functions.CachedSubscription{ + SubscriptionID: uint64(1), + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: big.NewInt(10), + Owner: testutils.NewAddress(), + BlockedBalance: big.NewInt(20), + ProposedOwner: common.Address{}, + Consumers: []common.Address{}, + Flags: defaultFlags, + }, + } + err = orm.UpsertSubscription(expectedUpdated) + require.NoError(t, err) + + expectedNotUpdated := functions.CachedSubscription{ + SubscriptionID: uint64(2), + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: big.NewInt(10), + Owner: testutils.NewAddress(), + BlockedBalance: big.NewInt(20), + ProposedOwner: common.Address{}, + Consumers: []common.Address{}, + Flags: defaultFlags, + }, + } + err = orm.UpsertSubscription(expectedNotUpdated) + require.NoError(t, err) + + // update the balance value + expectedUpdated.Balance = big.NewInt(20) + err = orm.UpsertSubscription(expectedUpdated) + require.NoError(t, err) + + results, err := orm.GetSubscriptions(0, 5) + require.NoError(t, err) + require.Equal(t, 2, len(results), "incorrect results length") + require.Equal(t, expectedNotUpdated, results[1]) + require.Equal(t, expectedUpdated, results[0]) + }) + + t.Run("update a deleted subscription", func(t *testing.T) { + orm, err := setupORM(t) + require.NoError(t, err) + + subscription := functions.CachedSubscription{ + SubscriptionID: uint64(1), + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: big.NewInt(10), + Owner: testutils.NewAddress(), + BlockedBalance: big.NewInt(20), + ProposedOwner: common.Address{}, + Consumers: []common.Address{}, + Flags: defaultFlags, + }, + } + err = orm.UpsertSubscription(subscription) + require.NoError(t, err) + + // empty subscription + subscription.IFunctionsSubscriptionsSubscription = functions_router.IFunctionsSubscriptionsSubscription{ + Balance: big.NewInt(0), + Owner: common.Address{}, + BlockedBalance: big.NewInt(0), + ProposedOwner: common.Address{}, + Consumers: []common.Address{}, + Flags: [32]byte{}, + } + + err = orm.UpsertSubscription(subscription) + require.NoError(t, err) + + results, err := orm.GetSubscriptions(0, 5) + require.NoError(t, err) + require.Equal(t, 1, len(results), "incorrect results length") + require.Equal(t, subscription, results[0]) + }) + + t.Run("create a subscription with same id but different router address", func(t *testing.T) { + var ( + db = pgtest.NewSqlxDB(t) + lggr = logger.TestLogger(t) + ) + + orm1, err := functions.NewORM(db, lggr, pgtest.NewQConfig(true), testutils.NewAddress()) + require.NoError(t, err) + orm2, err := functions.NewORM(db, lggr, pgtest.NewQConfig(true), testutils.NewAddress()) + require.NoError(t, err) + + subscription := functions.CachedSubscription{ + SubscriptionID: uint64(1), + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: assets.Ether(10).ToInt(), + Owner: testutils.NewAddress(), + BlockedBalance: assets.Ether(20).ToInt(), + ProposedOwner: common.Address{}, + Consumers: []common.Address{}, + Flags: defaultFlags, + }, + } + + err = orm1.UpsertSubscription(subscription) + require.NoError(t, err) + + // should update the existing subscription + subscription.Balance = assets.Ether(12).ToInt() + err = orm1.UpsertSubscription(subscription) + require.NoError(t, err) + + results, err := orm1.GetSubscriptions(0, 10) + require.NoError(t, err) + require.Equal(t, 1, len(results), "incorrect results length") + + // should create a new subscription because it comes from a different router contract + err = orm2.UpsertSubscription(subscription) + require.NoError(t, err) + + results, err = orm1.GetSubscriptions(0, 10) + require.NoError(t, err) + require.Equal(t, 1, len(results), "incorrect results length") + + results, err = orm2.GetSubscriptions(0, 10) + require.NoError(t, err) + require.Equal(t, 1, len(results), "incorrect results length") + }) +} + +func Test_NewORM(t *testing.T) { + t.Run("OK-create_ORM", func(t *testing.T) { + _, err := functions.NewORM(pgtest.NewSqlxDB(t), logger.TestLogger(t), pgtest.NewQConfig(true), testutils.NewAddress()) + require.NoError(t, err) + }) + t.Run("NOK-create_ORM_with_nil_fields", func(t *testing.T) { + _, err := functions.NewORM(nil, nil, nil, common.Address{}) + require.Error(t, err) + }) + t.Run("NOK-create_ORM_with_empty_address", func(t *testing.T) { + _, err := functions.NewORM(pgtest.NewSqlxDB(t), logger.TestLogger(t), pgtest.NewQConfig(true), common.Address{}) + require.Error(t, err) + }) +} diff --git a/core/services/gateway/handlers/functions/subscriptions.go b/core/services/gateway/handlers/functions/subscriptions.go index ebffbbdd206..8bc9cf09e7b 100644 --- a/core/services/gateway/handlers/functions/subscriptions.go +++ b/core/services/gateway/handlers/functions/subscriptions.go @@ -19,12 +19,15 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils" ) +const defaultCacheBatchSize = 100 + type OnchainSubscriptionsConfig struct { ContractAddress common.Address `json:"contractAddress"` BlockConfirmations uint `json:"blockConfirmations"` UpdateFrequencySec uint `json:"updateFrequencySec"` UpdateTimeoutSec uint `json:"updateTimeoutSec"` UpdateRangeSize uint `json:"updateRangeSize"` + CacheBatchSize uint `json:"cacheBatchSize"` } // OnchainSubscriptions maintains a mirror of all subscriptions fetched from the blockchain (EVM-only). @@ -43,6 +46,7 @@ type onchainSubscriptions struct { config OnchainSubscriptionsConfig subscriptions UserSubscriptions + orm ORM client evmclient.Client router *functions_router.FunctionsRouter blockConfirmations *big.Int @@ -52,7 +56,7 @@ type onchainSubscriptions struct { stopCh services.StopChan } -func NewOnchainSubscriptions(client evmclient.Client, config OnchainSubscriptionsConfig, lggr logger.Logger) (OnchainSubscriptions, error) { +func NewOnchainSubscriptions(client evmclient.Client, config OnchainSubscriptionsConfig, orm ORM, lggr logger.Logger) (OnchainSubscriptions, error) { if client == nil { return nil, errors.New("client is nil") } @@ -63,9 +67,17 @@ func NewOnchainSubscriptions(client evmclient.Client, config OnchainSubscription if err != nil { return nil, fmt.Errorf("unexpected error during functions_router.NewFunctionsRouter: %s", err) } + + // if CacheBatchSize is not specified use the default value + if config.CacheBatchSize == 0 { + lggr.Info("CacheBatchSize not specified, using default size: ", defaultCacheBatchSize) + config.CacheBatchSize = defaultCacheBatchSize + } + return &onchainSubscriptions{ config: config, subscriptions: NewUserSubscriptions(), + orm: orm, client: client, router: router, blockConfirmations: big.NewInt(int64(config.BlockConfirmations)), @@ -87,6 +99,8 @@ func (s *onchainSubscriptions) Start(ctx context.Context) error { return errors.New("OnchainSubscriptionsConfig.UpdateRangeSize must be greater than 0") } + s.loadCachedSubscriptions() + s.closeWait.Add(1) go s.queryLoop() @@ -190,7 +204,15 @@ func (s *onchainSubscriptions) querySubscriptionsRange(ctx context.Context, bloc for i, subscription := range subscriptions { subscriptionId := start + uint64(i) subscription := subscription - s.subscriptions.UpdateSubscription(subscriptionId, &subscription) + updated := s.subscriptions.UpdateSubscription(subscriptionId, &subscription) + if updated { + if err = s.orm.UpsertSubscription(CachedSubscription{ + SubscriptionID: subscriptionId, + IFunctionsSubscriptionsSubscription: subscription, + }); err != nil { + s.lggr.Errorf("unexpected error updating subscription in the cache: %w", err) + } + } } return nil @@ -203,3 +225,30 @@ func (s *onchainSubscriptions) getSubscriptionsCount(ctx context.Context, blockN Context: ctx, }) } + +func (s *onchainSubscriptions) loadCachedSubscriptions() { + offset := uint(0) + for { + csBatch, err := s.orm.GetSubscriptions(offset, s.config.CacheBatchSize) + if err != nil { + break + } + + for _, cs := range csBatch { + _ = s.subscriptions.UpdateSubscription(cs.SubscriptionID, &functions_router.IFunctionsSubscriptionsSubscription{ + Balance: cs.Balance, + Owner: cs.Owner, + BlockedBalance: cs.BlockedBalance, + ProposedOwner: cs.ProposedOwner, + Consumers: cs.Consumers, + Flags: cs.Flags, + }) + } + s.lggr.Debugw("Loading cached subscriptions", "offset", offset, "batch_length", len(csBatch)) + + if len(csBatch) != int(s.config.CacheBatchSize) { + break + } + offset += s.config.CacheBatchSize + } +} diff --git a/core/services/gateway/handlers/functions/subscriptions_test.go b/core/services/gateway/handlers/functions/subscriptions_test.go index adbf637ad73..782dcc2332d 100644 --- a/core/services/gateway/handlers/functions/subscriptions_test.go +++ b/core/services/gateway/handlers/functions/subscriptions_test.go @@ -15,14 +15,17 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" + fmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/mocks" ) const ( validUser = "0x9ED925d8206a4f88a2f643b28B3035B315753Cd6" invalidUser = "0x6E2dc0F9DB014aE19888F539E59285D2Ea04244C" + cachedUser = "0x3E2dc0F9DB014aE19888F539E59285D2Ea04233G" ) func TestSubscriptions_OnePass(t *testing.T) { @@ -47,7 +50,10 @@ func TestSubscriptions_OnePass(t *testing.T) { UpdateTimeoutSec: 1, UpdateRangeSize: 3, } - subscriptions, err := functions.NewOnchainSubscriptions(client, config, logger.TestLogger(t)) + orm := fmocks.NewORM(t) + orm.On("GetSubscriptions", uint(0), uint(100)).Return([]functions.CachedSubscription{}, nil) + orm.On("UpsertSubscription", mock.Anything).Return(nil) + subscriptions, err := functions.NewOnchainSubscriptions(client, config, orm, logger.TestLogger(t)) require.NoError(t, err) err = subscriptions.Start(ctx) @@ -95,7 +101,10 @@ func TestSubscriptions_MultiPass(t *testing.T) { UpdateTimeoutSec: 1, UpdateRangeSize: 3, } - subscriptions, err := functions.NewOnchainSubscriptions(client, config, logger.TestLogger(t)) + orm := fmocks.NewORM(t) + orm.On("GetSubscriptions", uint(0), uint(100)).Return([]functions.CachedSubscription{}, nil) + orm.On("UpsertSubscription", mock.Anything).Return(nil) + subscriptions, err := functions.NewOnchainSubscriptions(client, config, orm, logger.TestLogger(t)) require.NoError(t, err) err = subscriptions.Start(ctx) @@ -108,3 +117,57 @@ func TestSubscriptions_MultiPass(t *testing.T) { return currentCycle.Load() == ncycles }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) } + +func TestSubscriptions_Cached(t *testing.T) { + getSubscriptionCount := hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000003") + getSubscriptionsInRange := hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000109e6e1b12098cc8f3a1e9719a817ec53ab9b35c000000000000000000000000000000000000000000000000000034e23f515cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f5340f0968ee8b7dfd97e3327a6139273cc2c4fa000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001bc14b92364c75e20000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005439e5881a529f3ccbffc0e82d49f9db3950aefe") + + ctx := testutils.Context(t) + client := mocks.NewClient(t) + client.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(42), nil) + client.On("CallContract", mock.Anything, ethereum.CallMsg{ // getSubscriptionCount + To: &common.Address{}, + Data: hexutil.MustDecode("0x66419970"), + }, mock.Anything).Return(getSubscriptionCount, nil) + client.On("CallContract", mock.Anything, ethereum.CallMsg{ // GetSubscriptionsInRange + To: &common.Address{}, + Data: hexutil.MustDecode("0xec2454e500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003"), + }, mock.Anything).Return(getSubscriptionsInRange, nil) + config := functions.OnchainSubscriptionsConfig{ + ContractAddress: common.Address{}, + BlockConfirmations: 1, + UpdateFrequencySec: 1, + UpdateTimeoutSec: 1, + UpdateRangeSize: 3, + CacheBatchSize: 1, + } + + expectedBalance := big.NewInt(5) + orm := fmocks.NewORM(t) + orm.On("GetSubscriptions", uint(0), uint(1)).Return([]functions.CachedSubscription{ + { + SubscriptionID: 1, + IFunctionsSubscriptionsSubscription: functions_router.IFunctionsSubscriptionsSubscription{ + Balance: expectedBalance, + Owner: common.HexToAddress(cachedUser), + BlockedBalance: big.NewInt(10), + }, + }, + }, nil) + orm.On("GetSubscriptions", uint(1), uint(1)).Return([]functions.CachedSubscription{}, nil) + orm.On("UpsertSubscription", mock.Anything).Return(nil) + + subscriptions, err := functions.NewOnchainSubscriptions(client, config, orm, logger.TestLogger(t)) + require.NoError(t, err) + + err = subscriptions.Start(ctx) + require.NoError(t, err) + t.Cleanup(func() { + assert.NoError(t, subscriptions.Close()) + }) + + gomega.NewGomegaWithT(t).Eventually(func() bool { + actualBalance, err := subscriptions.GetMaxUserBalance(common.HexToAddress(cachedUser)) + return err == nil && assert.Equal(t, expectedBalance, actualBalance) + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) +} diff --git a/core/services/gateway/handlers/functions/user_subscriptions.go b/core/services/gateway/handlers/functions/user_subscriptions.go index c47ac8a4c90..7e63720da71 100644 --- a/core/services/gateway/handlers/functions/user_subscriptions.go +++ b/core/services/gateway/handlers/functions/user_subscriptions.go @@ -6,14 +6,16 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Methods are NOT thread-safe. +var ErrUserHasNoSubscription = errors.New("user has no subscriptions") + type UserSubscriptions interface { - UpdateSubscription(subscriptionId uint64, subscription *functions_router.IFunctionsSubscriptionsSubscription) + UpdateSubscription(subscriptionId uint64, subscription *functions_router.IFunctionsSubscriptionsSubscription) bool GetMaxUserBalance(user common.Address) (*big.Int, error) } @@ -29,29 +31,45 @@ func NewUserSubscriptions() UserSubscriptions { } } -func (us *userSubscriptions) UpdateSubscription(subscriptionId uint64, subscription *functions_router.IFunctionsSubscriptionsSubscription) { +// CachedSubscription is used to populate the user subscription maps from a persistent layer like postgres. +type CachedSubscription struct { + SubscriptionID uint64 + functions_router.IFunctionsSubscriptionsSubscription +} + +// UpdateSubscription updates a subscription returning false in case there was no variation to the current state. +func (us *userSubscriptions) UpdateSubscription(subscriptionId uint64, subscription *functions_router.IFunctionsSubscriptionsSubscription) bool { if subscription == nil || subscription.Owner == utils.ZeroAddress { user, ok := us.subscriptionIdsMap[subscriptionId] - if ok { - delete(us.userSubscriptionsMap[user], subscriptionId) - if len(us.userSubscriptionsMap[user]) == 0 { - delete(us.userSubscriptionsMap, user) - } + if !ok { + return false } + + delete(us.userSubscriptionsMap[user], subscriptionId) delete(us.subscriptionIdsMap, subscriptionId) - } else { - us.subscriptionIdsMap[subscriptionId] = subscription.Owner - if _, ok := us.userSubscriptionsMap[subscription.Owner]; !ok { - us.userSubscriptionsMap[subscription.Owner] = make(map[uint64]*functions_router.IFunctionsSubscriptionsSubscription) + if len(us.userSubscriptionsMap[user]) == 0 { + delete(us.userSubscriptionsMap, user) } - us.userSubscriptionsMap[subscription.Owner][subscriptionId] = subscription + return true + } + + // there is no change to the subscription + if us.userSubscriptionsMap[subscription.Owner][subscriptionId] == subscription { + return false + } + + us.subscriptionIdsMap[subscriptionId] = subscription.Owner + if _, ok := us.userSubscriptionsMap[subscription.Owner]; !ok { + us.userSubscriptionsMap[subscription.Owner] = make(map[uint64]*functions_router.IFunctionsSubscriptionsSubscription) } + us.userSubscriptionsMap[subscription.Owner][subscriptionId] = subscription + return true } func (us *userSubscriptions) GetMaxUserBalance(user common.Address) (*big.Int, error) { subs, exists := us.userSubscriptionsMap[user] if !exists { - return nil, errors.New("user has no subscriptions") + return nil, ErrUserHasNoSubscription } maxBalance := big.NewInt(0) diff --git a/core/services/gateway/handlers/functions/user_subscriptions_test.go b/core/services/gateway/handlers/functions/user_subscriptions_test.go index 9e6a660adad..53827e07e1b 100644 --- a/core/services/gateway/handlers/functions/user_subscriptions_test.go +++ b/core/services/gateway/handlers/functions/user_subscriptions_test.go @@ -4,9 +4,9 @@ import ( "math/big" "testing" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" ) @@ -28,18 +28,23 @@ func TestUserSubscriptions(t *testing.T) { user2Balance1 := big.NewInt(50) user2Balance2 := big.NewInt(70) - us.UpdateSubscription(5, &functions_router.IFunctionsSubscriptionsSubscription{ + updated := us.UpdateSubscription(5, &functions_router.IFunctionsSubscriptionsSubscription{ Owner: user1, Balance: user1Balance, }) - us.UpdateSubscription(3, &functions_router.IFunctionsSubscriptionsSubscription{ + assert.True(t, updated) + + updated = us.UpdateSubscription(3, &functions_router.IFunctionsSubscriptionsSubscription{ Owner: user2, Balance: user2Balance1, }) - us.UpdateSubscription(10, &functions_router.IFunctionsSubscriptionsSubscription{ + assert.True(t, updated) + + updated = us.UpdateSubscription(10, &functions_router.IFunctionsSubscriptionsSubscription{ Owner: user2, Balance: user2Balance2, }) + assert.True(t, updated) balance, err := us.GetMaxUserBalance(user1) assert.NoError(t, err) @@ -49,29 +54,96 @@ func TestUserSubscriptions(t *testing.T) { assert.NoError(t, err) assert.Zero(t, balance.Cmp(user2Balance2)) }) +} - t.Run("UpdateSubscription to remove subscriptions", func(t *testing.T) { +func TestUserSubscriptions_UpdateSubscription(t *testing.T) { + t.Parallel() + + t.Run("update balance", func(t *testing.T) { + us := functions.NewUserSubscriptions() + owner := utils.RandomAddress() + + updated := us.UpdateSubscription(1, &functions_router.IFunctionsSubscriptionsSubscription{ + Owner: owner, + Balance: big.NewInt(10), + }) + assert.True(t, updated) + + updated = us.UpdateSubscription(1, &functions_router.IFunctionsSubscriptionsSubscription{ + Owner: owner, + Balance: big.NewInt(100), + }) + assert.True(t, updated) + }) + + t.Run("updated proposed owner", func(t *testing.T) { + us := functions.NewUserSubscriptions() + owner := utils.RandomAddress() + + updated := us.UpdateSubscription(1, &functions_router.IFunctionsSubscriptionsSubscription{ + Owner: owner, + Balance: big.NewInt(10), + }) + assert.True(t, updated) + + updated = us.UpdateSubscription(1, &functions_router.IFunctionsSubscriptionsSubscription{ + Owner: owner, + Balance: big.NewInt(10), + ProposedOwner: utils.RandomAddress(), + }) + assert.True(t, updated) + }) + t.Run("remove subscriptions", func(t *testing.T) { + us := functions.NewUserSubscriptions() user2 := utils.RandomAddress() user2Balance1 := big.NewInt(50) user2Balance2 := big.NewInt(70) - us.UpdateSubscription(3, &functions_router.IFunctionsSubscriptionsSubscription{ + updated := us.UpdateSubscription(3, &functions_router.IFunctionsSubscriptionsSubscription{ Owner: user2, Balance: user2Balance1, }) - us.UpdateSubscription(10, &functions_router.IFunctionsSubscriptionsSubscription{ + assert.True(t, updated) + + updated = us.UpdateSubscription(10, &functions_router.IFunctionsSubscriptionsSubscription{ Owner: user2, Balance: user2Balance2, }) + assert.True(t, updated) - us.UpdateSubscription(3, &functions_router.IFunctionsSubscriptionsSubscription{ + updated = us.UpdateSubscription(3, &functions_router.IFunctionsSubscriptionsSubscription{ Owner: utils.ZeroAddress, }) - us.UpdateSubscription(10, &functions_router.IFunctionsSubscriptionsSubscription{ + assert.True(t, updated) + + updated = us.UpdateSubscription(10, &functions_router.IFunctionsSubscriptionsSubscription{ Owner: utils.ZeroAddress, }) + assert.True(t, updated) _, err := us.GetMaxUserBalance(user2) assert.Error(t, err) }) + + t.Run("remove a non existing subscription", func(t *testing.T) { + us := functions.NewUserSubscriptions() + updated := us.UpdateSubscription(3, &functions_router.IFunctionsSubscriptionsSubscription{ + Owner: utils.ZeroAddress, + }) + assert.False(t, updated) + }) + + t.Run("no actual changes", func(t *testing.T) { + us := functions.NewUserSubscriptions() + subscription := &functions_router.IFunctionsSubscriptionsSubscription{ + Owner: utils.RandomAddress(), + Balance: big.NewInt(25), + BlockedBalance: big.NewInt(25), + } + updated := us.UpdateSubscription(5, subscription) + assert.True(t, updated) + + updated = us.UpdateSubscription(5, subscription) + assert.False(t, updated) + }) } diff --git a/core/services/gateway/integration_tests/gateway_integration_test.go b/core/services/gateway/integration_tests/gateway_integration_test.go index 415a8f67cf8..9e4900efeee 100644 --- a/core/services/gateway/integration_tests/gateway_integration_test.go +++ b/core/services/gateway/integration_tests/gateway_integration_test.go @@ -118,7 +118,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, lggr), lggr) + gateway, err := gateway.NewGatewayFromConfig(parseGatewayConfig(t, gatewayConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) require.NoError(t, err) servicetest.Run(t, gateway) userPort, nodePort := gateway.GetUserPort(), gateway.GetNodePort() diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 768d16ddeb7..3590b526022 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -21,6 +21,7 @@ import ( evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "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" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -1386,7 +1387,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { var jb job.Job config := configtest.NewTestGeneralConfig(t) - db := pgtest.NewSqlxDB(t) + _, db := heavyweight.FullTestDBV2(t, nil) keyStore := cltest.NewKeyStore(t, db, config.Database()) require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) diff --git a/core/services/job/models.go b/core/services/job/models.go index f60e0a12981..50e986d8db1 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -27,7 +28,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/stringutils" "github.com/smartcontractkit/chainlink/v2/core/utils/tomlutils" ) diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index 14a5c41b396..27c0e0e8515 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -24,7 +24,7 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -462,7 +462,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, mailbox.NewMonitor(t.Name())), + servicetest.Run(t, mailboxtest.NewMonitor(t)), ) _, err = sd.ServicesForSpec(jb) require.NoError(t, err) @@ -496,7 +496,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, mailbox.NewMonitor(t.Name())), + servicetest.Run(t, mailboxtest.NewMonitor(t)), ) _, err = sd.ServicesForSpec(jb) require.NoError(t, err) @@ -524,7 +524,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, mailbox.NewMonitor(t.Name())), + servicetest.Run(t, mailboxtest.NewMonitor(t)), ) _, err = sd.ServicesForSpec(jb) require.NoError(t, err) @@ -579,7 +579,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, mailbox.NewMonitor(t.Name())), + servicetest.Run(t, mailboxtest.NewMonitor(t)), ) jb.OCROracleSpec.CaptureEATelemetry = tc.jbCaptureEATelemetry @@ -623,7 +623,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, mailbox.NewMonitor(t.Name())), + servicetest.Run(t, mailboxtest.NewMonitor(t)), ) services, err := sd.ServicesForSpec(*jb) require.NoError(t, err) diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go index 5ed017b8743..1d44cedaad9 100644 --- a/core/services/job/spawner.go +++ b/core/services/job/spawner.go @@ -12,10 +12,10 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name Spawner --output ./mocks/ --case=underscore diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index b82aa73c0b5..3e8ccbab848 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -14,7 +14,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" "github.com/smartcontractkit/chainlink/v2/core/bridges" mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" @@ -30,12 +31,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" - "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" evmrelayer "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/plugins" ) @@ -129,7 +128,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA2 := mocks.NewServiceCtx(t) serviceA1.On("Start", mock.Anything).Return(nil).Once() serviceA2.On("Start", mock.Anything).Return(nil).Once().Run(func(mock.Arguments) { eventuallyA.ItHappened() }) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) dA := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, make(chan struct{}), dA} @@ -188,7 +187,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { lggr := logger.TestLogger(t) orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database()) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ @@ -222,7 +221,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { lggr := logger.TestLogger(t) orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database()) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ @@ -285,10 +284,9 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { chain := evmtest.MustGetDefaultChain(t, legacyChains) evmRelayer, err := evmrelayer.NewRelayer(lggr, chain, evmrelayer.RelayerOpts{ - DB: db, - QConfig: testopts.GeneralConfig.Database(), - CSAETHKeystore: keyStore, - EventBroadcaster: pg.NewNullEventBroadcaster(), + DB: db, + QConfig: testopts.GeneralConfig.Database(), + CSAETHKeystore: keyStore, }) assert.NoError(t, err) @@ -300,13 +298,13 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { jobOCR2VRF := makeOCR2VRFJobSpec(t, keyStore, config, address, chain.ID(), 2) orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database()) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) processConfig := plugins.NewRegistrarConfig(loop.GRPCOpts{}, func(name string) (*plugins.RegisteredLoop, error) { return nil, nil }) ocr2DelegateConfig := ocr2.NewDelegateConfig(config.OCR2(), config.Mercury(), config.Threshold(), config.Insecure(), config.JobPipeline(), config.Database(), processConfig) d := ocr2.NewDelegate(nil, orm, nil, nil, nil, nil, monitoringEndpoint, legacyChains, lggr, ocr2DelegateConfig, - keyStore.OCR2(), keyStore.DKGSign(), keyStore.DKGEncrypt(), ethKeyStore, testRelayGetter, mailMon, nil) + keyStore.OCR2(), keyStore.DKGSign(), keyStore.DKGEncrypt(), ethKeyStore, testRelayGetter, mailMon) delegateOCR2 := &delegate{jobOCR2VRF.Type, []job.ServiceCtx{}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ diff --git a/core/services/keeper/models.go b/core/services/keeper/models.go index 8f72f0b22c9..fe034bcc505 100644 --- a/core/services/keeper/models.go +++ b/core/services/keeper/models.go @@ -8,10 +8,10 @@ import ( "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type KeeperIndexMap map[ethkey.EIP55Address]int32 diff --git a/core/services/keeper/orm_test.go b/core/services/keeper/orm_test.go index e5b56e9511e..2ce459886ae 100644 --- a/core/services/keeper/orm_test.go +++ b/core/services/keeper/orm_test.go @@ -15,6 +15,7 @@ import ( "github.com/jmoiron/sqlx" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -177,7 +178,7 @@ func TestKeeperDB_EligibleUpkeeps_Shuffle(t *testing.T) { } cltest.AssertCount(t, db, "upkeep_registrations", 100) - eligibleUpkeeps, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, blockheight, gracePeriod, fmt.Sprintf("%b", utils.NewHash().Big())) + eligibleUpkeeps, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, blockheight, gracePeriod, fmt.Sprintf("%b", evmutils.NewHash().Big())) assert.NoError(t, err) require.Len(t, eligibleUpkeeps, 100) @@ -205,12 +206,12 @@ func TestKeeperDB_NewEligibleUpkeeps_GracePeriod(t *testing.T) { // if current keeper index = 0 and all upkeeps last perform was done by index = 0 and still within grace period upkeep := keeper.UpkeepRegistration{} require.NoError(t, db.Get(&upkeep, `UPDATE upkeep_registrations SET last_keeper_index = 0, last_run_block_height = 10 RETURNING *`)) - list0, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 21, 100, fmt.Sprintf("%b", utils.NewHash().Big())) // none eligible + list0, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 21, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) // none eligible require.NoError(t, err) require.Equal(t, 0, len(list0), "should be 0 as all last perform was done by current node") // once passed grace period - list1, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 121, 100, fmt.Sprintf("%b", utils.NewHash().Big())) // none eligible + list1, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 121, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) // none eligible require.NoError(t, err) require.NotEqual(t, 0, len(list1), "should get some eligible upkeeps now that they are outside grace period") } @@ -230,13 +231,13 @@ func TestKeeperDB_EligibleUpkeeps_TurnsRandom(t *testing.T) { cltest.AssertCount(t, db, "upkeep_registrations", 1000) // 3 keepers 10 block turns should be different every turn - list1, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 20, 100, fmt.Sprintf("%b", utils.NewHash().Big())) + list1, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 20, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) require.NoError(t, err) - list2, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 31, 100, fmt.Sprintf("%b", utils.NewHash().Big())) + list2, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 31, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) require.NoError(t, err) - list3, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 42, 100, fmt.Sprintf("%b", utils.NewHash().Big())) + list3, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 42, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) require.NoError(t, err) - list4, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 53, 100, fmt.Sprintf("%b", utils.NewHash().Big())) + list4, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 53, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) require.NoError(t, err) // sort before compare @@ -275,7 +276,7 @@ func TestKeeperDB_NewEligibleUpkeeps_SkipIfLastPerformedByCurrentKeeper(t *testi // if current keeper index = 0 and all upkeeps last perform was done by index = 0 then skip as it would not pass required turn taking upkeep := keeper.UpkeepRegistration{} require.NoError(t, db.Get(&upkeep, `UPDATE upkeep_registrations SET last_keeper_index = 0 RETURNING *`)) - list0, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 21, 100, fmt.Sprintf("%b", utils.NewHash().Big())) // none eligible + list0, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 21, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) // none eligible require.NoError(t, err) require.Equal(t, 0, len(list0), "should be 0 as all last perform was done by current node") } @@ -295,7 +296,7 @@ func TestKeeperDB_NewEligibleUpkeeps_CoverBuddy(t *testing.T) { cltest.AssertCount(t, db, "upkeep_registrations", 100) upkeep := keeper.UpkeepRegistration{} - binaryHash := fmt.Sprintf("%b", utils.NewHash().Big()) + binaryHash := fmt.Sprintf("%b", evmutils.NewHash().Big()) listBefore, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 21, 100, binaryHash) // normal require.NoError(t, err) require.NoError(t, db.Get(&upkeep, `UPDATE upkeep_registrations SET last_keeper_index = 0 RETURNING *`)) @@ -318,7 +319,7 @@ func TestKeeperDB_NewEligibleUpkeeps_FirstTurn(t *testing.T) { cltest.AssertCount(t, db, "keeper_registries", 1) cltest.AssertCount(t, db, "upkeep_registrations", 100) - binaryHash := fmt.Sprintf("%b", utils.NewHash().Big()) + binaryHash := fmt.Sprintf("%b", evmutils.NewHash().Big()) // last keeper index is null to simulate a normal first run listKpr0, err := orm.EligibleUpkeepsForRegistry(registry.ContractAddress, 21, 100, binaryHash) // someone eligible only kpr0 turn require.NoError(t, err) @@ -339,7 +340,7 @@ func TestKeeperDB_NewEligibleUpkeeps_FiltersByRegistry(t *testing.T) { cltest.AssertCount(t, db, "keeper_registries", 2) cltest.AssertCount(t, db, "upkeep_registrations", 2) - binaryHash := fmt.Sprintf("%b", utils.NewHash().Big()) + binaryHash := fmt.Sprintf("%b", evmutils.NewHash().Big()) list1, err := orm.EligibleUpkeepsForRegistry(registry1.ContractAddress, 20, 100, binaryHash) require.NoError(t, err) list2, err := orm.EligibleUpkeepsForRegistry(registry2.ContractAddress, 20, 100, binaryHash) @@ -400,8 +401,8 @@ func TestKeeperDB_NewSetLastRunInfoForUpkeepOnJob(t *testing.T) { upkeep := cltest.MustInsertUpkeepForRegistry(t, db, config.Database(), registry) registry.NumKeepers = 2 registry.KeeperIndexMap = map[ethkey.EIP55Address]int32{ - registry.FromAddress: 0, - ethkey.EIP55AddressFromAddress(utils.ZeroAddress): 1, + registry.FromAddress: 0, + ethkey.EIP55AddressFromAddress(evmutils.ZeroAddress): 1, } err := orm.UpsertRegistry(®istry) require.NoError(t, err, "UPDATE keeper_registries") @@ -417,7 +418,7 @@ func TestKeeperDB_NewSetLastRunInfoForUpkeepOnJob(t *testing.T) { require.Equal(t, rowsAffected, int64(0)) assertLastRunHeight(t, db, upkeep, 100, 0) // update to same block height allowed - rowsAffected, err = orm.SetLastRunInfoForUpkeepOnJob(j.ID, upkeep.UpkeepID, 100, ethkey.EIP55AddressFromAddress(utils.ZeroAddress)) + rowsAffected, err = orm.SetLastRunInfoForUpkeepOnJob(j.ID, upkeep.UpkeepID, 100, ethkey.EIP55AddressFromAddress(evmutils.ZeroAddress)) require.NoError(t, err) require.Equal(t, rowsAffected, int64(1)) assertLastRunHeight(t, db, upkeep, 100, 1) @@ -489,11 +490,11 @@ func TestKeeperDB_Uint256ToBit(t *testing.T) { }, { name: "max", - input: utils.MaxUint256, + input: evmutils.MaxUint256, }, { name: "rand", - input: utils.RandUint256(), + input: evmutils.RandUint256(), }, { name: "needs pading", @@ -501,7 +502,7 @@ func TestKeeperDB_Uint256ToBit(t *testing.T) { }, { name: "overflow", - input: bigmath.Add(utils.MaxUint256, big.NewInt(1)), + input: bigmath.Add(evmutils.MaxUint256, big.NewInt(1)), errorExpected: true, }, } { diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go index dff97202f6c..19ba2eedbbb 100644 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ b/core/services/keeper/registry_synchronizer_helper_test.go @@ -11,7 +11,7 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -73,7 +73,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( })).Maybe().Return(func() {}) lbMock.On("IsConnected").Return(true).Maybe() - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) orm := keeper.NewORM(db, logger.TestLogger(t), ch.Config().Database()) synchronizer := keeper.NewRegistrySynchronizer(keeper.RegistrySynchronizerOptions{ diff --git a/core/services/keeper/registry_synchronizer_sync.go b/core/services/keeper/registry_synchronizer_sync.go index f90e0bc85d7..7614ed15edb 100644 --- a/core/services/keeper/registry_synchronizer_sync.go +++ b/core/services/keeper/registry_synchronizer_sync.go @@ -7,9 +7,9 @@ import ( "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func (rs *RegistrySynchronizer) fullSync() { diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index 61ccca956f4..590c9720cb2 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -36,7 +37,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func newHead() evmtypes.Head { @@ -335,7 +335,12 @@ func Test_UpkeepExecuter_PerformsUpkeep_Error(t *testing.T) { executer.OnNewLongestChain(testutils.Context(t), &head) g.Eventually(wasCalled.Load).Should(gomega.Equal(true)) - cltest.AssertCountStays(t, db, "evm.txes", 0) + + cfg := pgtest.NewQConfig(false) + txStore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg) + txes, err := txStore.GetAllTxes(testutils.Context(t)) + require.NoError(t, err) + require.Len(t, txes, 0) } func ptr[T any](t T) *T { return &t } diff --git a/core/services/keystore/cosmos_test.go b/core/services/keystore/cosmos_test.go index 3c33f16282d..30c669f7545 100644 --- a/core/services/keystore/cosmos_test.go +++ b/core/services/keystore/cosmos_test.go @@ -6,12 +6,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_CosmosKeyStore_E2E(t *testing.T) { diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index 3935a44558b..dd42f4049c3 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -9,11 +9,12 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + 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" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -21,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_EthKeyStore(t *testing.T) { @@ -36,8 +36,8 @@ func Test_EthKeyStore(t *testing.T) { ethKeyStore := keyStore.Eth() reset := func() { keyStore.ResetXXXTestOnly() - require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) - require.NoError(t, utils.JustError(db.Exec("DELETE FROM evm.key_states"))) + require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) + require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM evm.key_states"))) require.NoError(t, keyStore.Unlock(cltest.Password)) } const statesTableName = "evm.key_states" @@ -337,7 +337,7 @@ func Test_EthKeyStore_SignTx(t *testing.T) { k, _ := cltest.MustInsertRandomKey(t, ethKeyStore) chainID := big.NewInt(evmclient.NullClientChainID) - tx := types.NewTransaction(0, testutils.NewAddress(), big.NewInt(53), 21000, big.NewInt(1000000000), []byte{1, 2, 3, 4}) + tx := cltest.NewLegacyTransaction(0, testutils.NewAddress(), big.NewInt(53), 21000, big.NewInt(1000000000), []byte{1, 2, 3, 4}) randomAddress := testutils.NewAddress() _, err := ethKeyStore.SignTx(randomAddress, tx, chainID) @@ -361,8 +361,8 @@ func Test_EthKeyStore_E2E(t *testing.T) { ks := keyStore.Eth() reset := func() { keyStore.ResetXXXTestOnly() - require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) - require.NoError(t, utils.JustError(db.Exec("DELETE FROM evm.key_states"))) + require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) + require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM evm.key_states"))) require.NoError(t, keyStore.Unlock(cltest.Password)) } diff --git a/core/services/keystore/keys/vrfkey/crypto.go b/core/services/keystore/keys/vrfkey/crypto.go index a3792b98075..fe105d13f11 100644 --- a/core/services/keystore/keys/vrfkey/crypto.go +++ b/core/services/keystore/keys/vrfkey/crypto.go @@ -7,8 +7,9 @@ import ( "github.com/ethereum/go-ethereum/common" "go.dedis.ch/kyber/v3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" - "github.com/smartcontractkit/chainlink/v2/core/utils" bm "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) @@ -19,7 +20,7 @@ import ( var ( // FieldSize is number of elements in secp256k1's base field, i.e. GF(FieldSize) - FieldSize = utils.HexToBig( + FieldSize = mustParseBig( "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", ) Secp256k1Curve = &secp256k1.Secp256k1{} @@ -176,3 +177,11 @@ func ScalarFromCurvePoints( msg = append(msg, uWitness[:]...) return bm.I().SetBytes(utils.MustHash(string(msg)).Bytes()) } + +func mustParseBig(hx string) *big.Int { + n, err := hex.ParseBig(hx) + if err != nil { + panic(fmt.Errorf(`failed to convert "%s" as hex to big.Int`, hx)) + } + return n +} diff --git a/core/services/keystore/keys/vrfkey/key_v2.go b/core/services/keystore/keys/vrfkey/key_v2.go index 49c5a4999d8..786bd39b3f0 100644 --- a/core/services/keystore/keys/vrfkey/key_v2.go +++ b/core/services/keystore/keys/vrfkey/key_v2.go @@ -9,8 +9,8 @@ import ( "github.com/pkg/errors" "go.dedis.ch/kyber/v3" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" - "github.com/smartcontractkit/chainlink/v2/core/utils" bm "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) diff --git a/core/services/keystore/keys/vrfkey/proof.go b/core/services/keystore/keys/vrfkey/proof.go index d4ee9b160b7..b7f9032255b 100644 --- a/core/services/keystore/keys/vrfkey/proof.go +++ b/core/services/keystore/keys/vrfkey/proof.go @@ -6,8 +6,8 @@ import ( "go.dedis.ch/kyber/v3" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" - "github.com/smartcontractkit/chainlink/v2/core/utils" bm "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) diff --git a/core/services/keystore/ocr_test.go b/core/services/keystore/ocr_test.go index 200d62415eb..c65d576c452 100644 --- a/core/services/keystore/ocr_test.go +++ b/core/services/keystore/ocr_test.go @@ -6,12 +6,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_OCRKeyStore_E2E(t *testing.T) { diff --git a/core/services/keystore/p2p_test.go b/core/services/keystore/p2p_test.go index 829df9812fd..4e9ca75c456 100644 --- a/core/services/keystore/p2p_test.go +++ b/core/services/keystore/p2p_test.go @@ -9,13 +9,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "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/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_P2PKeyStore_E2E(t *testing.T) { diff --git a/core/services/keystore/solana_test.go b/core/services/keystore/solana_test.go index 6e895a56117..cf2515f5f70 100644 --- a/core/services/keystore/solana_test.go +++ b/core/services/keystore/solana_test.go @@ -6,13 +6,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "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/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_SolanaKeyStore_E2E(t *testing.T) { diff --git a/core/services/keystore/starknet_test.go b/core/services/keystore/starknet_test.go index 7fc5718bac0..a007b01f120 100644 --- a/core/services/keystore/starknet_test.go +++ b/core/services/keystore/starknet_test.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/caigo" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "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" @@ -20,7 +21,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" starktxm "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/txm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_StarkNetKeyStore_E2E(t *testing.T) { diff --git a/core/services/keystore/vrf_test.go b/core/services/keystore/vrf_test.go index 7a2e91ffec3..77fccd865ff 100644 --- a/core/services/keystore/vrf_test.go +++ b/core/services/keystore/vrf_test.go @@ -7,12 +7,12 @@ import ( "github.com/stretchr/testify/assert" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/require" ) diff --git a/core/services/ocr/config_overrider_test.go b/core/services/ocr/config_overrider_test.go index acd5245e19b..e01102a62f8 100644 --- a/core/services/ocr/config_overrider_test.go +++ b/core/services/ocr/config_overrider_test.go @@ -15,6 +15,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -187,7 +188,7 @@ func Test_OCRConfigOverrider(t *testing.T) { func checkFlagsAddress(t *testing.T, contractAddress ethkey.EIP55Address) func(args mock.Arguments) { return func(args mock.Arguments) { require.Equal(t, []common.Address{ - utils.ZeroAddress, + evmutils.ZeroAddress, contractAddress.Address(), }, args.Get(1).([]common.Address)) } diff --git a/core/services/ocr/contract_tracker_test.go b/core/services/ocr/contract_tracker_test.go index f7ebbe08481..185a9cd3197 100644 --- a/core/services/ocr/contract_tracker_test.go +++ b/core/services/ocr/contract_tracker_test.go @@ -16,7 +16,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -84,7 +84,7 @@ func newContractTrackerUni(t *testing.T, opts ...interface{}) (uni contractTrack uni.hb = commonmocks.NewHeadBroadcaster[*evmtypes.Head, common.Hash](t) uni.ec = evmtest.NewEthClientMock(t) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) db := pgtest.NewSqlxDB(t) uni.tracker = ocr.NewOCRContractTracker( contract, diff --git a/core/services/ocr/database_test.go b/core/services/ocr/database_test.go index 6a72c27aa65..5ccf257b2bb 100644 --- a/core/services/ocr/database_test.go +++ b/core/services/ocr/database_test.go @@ -13,12 +13,12 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "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/services/ocr" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_DB_ReadWriteState(t *testing.T) { diff --git a/core/services/ocr/flags.go b/core/services/ocr/flags.go index 8e4eb802e5e..6a18d73cd7e 100644 --- a/core/services/ocr/flags.go +++ b/core/services/ocr/flags.go @@ -5,8 +5,8 @@ import ( "github.com/pkg/errors" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ContractFlags wraps the a contract diff --git a/core/services/ocr/flags_test.go b/core/services/ocr/flags_test.go index 9e57b8489ed..bcce1ed2f96 100644 --- a/core/services/ocr/flags_test.go +++ b/core/services/ocr/flags_test.go @@ -7,10 +7,10 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestFlags_IsLowered(t *testing.T) { diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 1b7be2b7f0e..37235437de1 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -190,6 +190,7 @@ type jobPipelineConfig interface { type mercuryConfig interface { Credentials(credName string) *models.MercuryCredentials Cache() coreconfig.MercuryCache + TLS() coreconfig.MercuryTLS } type thresholdConfig interface { @@ -227,7 +228,6 @@ func NewDelegate( ethKs keystore.Eth, relayers RelayGetter, mailMon *mailbox.Monitor, - eventBroadcaster pg.EventBroadcaster, ) *Delegate { return &Delegate{ db: db, @@ -441,7 +441,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) { return d.newServicesOCR2VRF(lggr, jb, bootstrapPeers, kb, ocrDB, lc) case types.OCR2Keeper: - return d.newServicesOCR2Keepers(lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger) + return d.newServicesOCR2Keepers(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger) case types.Functions: const ( @@ -1026,6 +1026,7 @@ func (d *Delegate) newServicesOCR2VRF( } func (d *Delegate) newServicesOCR2Keepers( + ctx context.Context, lggr logger.SugaredLogger, jb job.Job, bootstrapPeers []commontypes.BootstrapperLocator, @@ -1046,7 +1047,7 @@ func (d *Delegate) newServicesOCR2Keepers( switch cfg.ContractVersion { case "v2.1": - return d.newServicesOCR2Keepers21(lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, cfg, spec) + return d.newServicesOCR2Keepers21(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, cfg, spec) case "v2.0": return d.newServicesOCR2Keepers20(lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, cfg, spec) default: @@ -1055,6 +1056,7 @@ func (d *Delegate) newServicesOCR2Keepers( } func (d *Delegate) newServicesOCR2Keepers21( + ctx context.Context, lggr logger.SugaredLogger, jb job.Job, bootstrapPeers []commontypes.BootstrapperLocator, @@ -1079,14 +1081,41 @@ func (d *Delegate) newServicesOCR2Keepers21( return nil, fmt.Errorf("keeper2 services: expected EVM relayer got %s", rid.Network) } - chain, err2 := d.legacyChains.Get(rid.ChainID) - if err2 != nil { - return nil, fmt.Errorf("keeper2 services: failed to get chain %s: %w", rid.ChainID, err2) + transmitterID := spec.TransmitterID.String + relayer, err := d.RelayGetter.Get(rid) + if err != nil { + return nil, ErrRelayNotEnabled{Err: err, Relay: spec.Relay, PluginName: "ocr2keepers"} } - keeperProvider, services, err2 := ocr2keeper.EVMDependencies21(jb, d.db, lggr, chain, mc, kb, d.cfg.Database(), d.ethKs) - if err2 != nil { - return nil, errors.Wrap(err2, "could not build dependencies for ocr2 keepers") + provider, err := relayer.NewPluginProvider(ctx, + types.RelayArgs{ + ExternalJobID: jb.ExternalJobID, + JobID: jb.ID, + ContractID: spec.ContractID, + New: d.isNewlyCreatedJob, + RelayConfig: spec.RelayConfig.Bytes(), + ProviderType: string(spec.PluginType), + }, types.PluginArgs{ + TransmitterID: transmitterID, + PluginConfig: spec.PluginConfig.Bytes(), + }) + if err != nil { + return nil, err + } + + keeperProvider, ok := provider.(types.AutomationProvider) + if !ok { + return nil, errors.New("could not coerce PluginProvider to AutomationProvider") + } + + chain, err := d.legacyChains.Get(rid.ChainID) + if err != nil { + return nil, fmt.Errorf("keeper2 services: failed to get chain %s: %w", rid.ChainID, err) + } + + services, err := ocr2keeper.EVMDependencies21(jb, d.db, lggr, chain, mc, kb, d.cfg.Database()) + if err != nil { + return nil, errors.Wrap(err, "could not build dependencies for ocr2 keepers") } // set some defaults conf := ocr2keepers21config.ReportingFactoryConfig{ diff --git a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go index 22a59feb3ae..9388b93329b 100644 --- a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go +++ b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go @@ -18,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/hashicorp/consul/sdk/freeport" @@ -31,6 +30,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_allow_list" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_client_example" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" @@ -49,7 +49,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var nilOpts *bind.CallOpts @@ -348,7 +347,7 @@ func StartNewNode( n, err := b.NonceAt(testutils.Context(t), owner.From, nil) require.NoError(t, err) - tx := types.NewTransaction( + tx := cltest.NewLegacyTransaction( n, transmitter, assets.Ether(1).ToInt(), 21000, diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go index 7e2b15bdccf..c6cfa946aba 100644 --- a/core/services/ocr2/plugins/functions/plugin.go +++ b/core/services/ocr2/plugins/functions/plugin.go @@ -143,7 +143,11 @@ func NewFunctionsServices(functionsOracleArgs, thresholdOracleArgs, s4OracleArgs if err2 != nil { return nil, errors.Wrap(err, "failed to create a RateLimiter") } - subscriptions, err2 := gwFunctions.NewOnchainSubscriptions(conf.Chain.Client(), *pluginConfig.OnchainSubscriptions, conf.Logger) + gwFunctionsORM, err := gwFunctions.NewORM(conf.DB, conf.Logger, conf.QConfig, pluginConfig.OnchainSubscriptions.ContractAddress) + if err != nil { + return nil, errors.Wrap(err, "failed to create functions ORM") + } + subscriptions, err2 := gwFunctions.NewOnchainSubscriptions(conf.Chain.Client(), *pluginConfig.OnchainSubscriptions, gwFunctionsORM, conf.Logger) if err2 != nil { return nil, errors.Wrap(err, "failed to create a OnchainSubscriptions") } diff --git a/core/services/ocr2/plugins/mercury/helpers_test.go b/core/services/ocr2/plugins/mercury/helpers_test.go index ed59213840c..68fb27fa82e 100644 --- a/core/services/ocr2/plugins/mercury/helpers_test.go +++ b/core/services/ocr2/plugins/mercury/helpers_test.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2/chains/evmutil" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "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" @@ -40,7 +41,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var _ pb.MercuryServer = &mercuryServer{} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go index ed3218ea405..4555a5b0b9b 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go @@ -7,48 +7,47 @@ import ( iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" ) +type UpkeepFailureReason uint8 +type PipelineExecutionState uint8 + const ( - // NOTE: This enum should be kept in sync with evmregistry/v21/mercury/upkeep_failure_reasons.go - // TODO (AUTO-7928) Remove this duplication // upkeep failure onchain reasons - UpkeepFailureReasonNone uint8 = 0 - UpkeepFailureReasonUpkeepCancelled uint8 = 1 - UpkeepFailureReasonUpkeepPaused uint8 = 2 - UpkeepFailureReasonTargetCheckReverted uint8 = 3 - UpkeepFailureReasonUpkeepNotNeeded uint8 = 4 - UpkeepFailureReasonPerformDataExceedsLimit uint8 = 5 - UpkeepFailureReasonInsufficientBalance uint8 = 6 - UpkeepFailureReasonMercuryCallbackReverted uint8 = 7 - UpkeepFailureReasonRevertDataExceedsLimit uint8 = 8 - UpkeepFailureReasonRegistryPaused uint8 = 9 + UpkeepFailureReasonNone UpkeepFailureReason = 0 + UpkeepFailureReasonUpkeepCancelled UpkeepFailureReason = 1 + UpkeepFailureReasonUpkeepPaused UpkeepFailureReason = 2 + UpkeepFailureReasonTargetCheckReverted UpkeepFailureReason = 3 + UpkeepFailureReasonUpkeepNotNeeded UpkeepFailureReason = 4 + UpkeepFailureReasonPerformDataExceedsLimit UpkeepFailureReason = 5 + UpkeepFailureReasonInsufficientBalance UpkeepFailureReason = 6 + UpkeepFailureReasonMercuryCallbackReverted UpkeepFailureReason = 7 + UpkeepFailureReasonRevertDataExceedsLimit UpkeepFailureReason = 8 + UpkeepFailureReasonRegistryPaused UpkeepFailureReason = 9 // leaving a gap here for more onchain failure reasons in the future // upkeep failure offchain reasons - UpkeepFailureReasonMercuryAccessNotAllowed uint8 = 32 - UpkeepFailureReasonTxHashNoLongerExists uint8 = 33 - UpkeepFailureReasonInvalidRevertDataInput uint8 = 34 - UpkeepFailureReasonSimulationFailed uint8 = 35 - UpkeepFailureReasonTxHashReorged uint8 = 36 + UpkeepFailureReasonMercuryAccessNotAllowed UpkeepFailureReason = 32 + UpkeepFailureReasonTxHashNoLongerExists UpkeepFailureReason = 33 + UpkeepFailureReasonInvalidRevertDataInput UpkeepFailureReason = 34 + UpkeepFailureReasonSimulationFailed UpkeepFailureReason = 35 + UpkeepFailureReasonTxHashReorged UpkeepFailureReason = 36 - // NOTE: This enum should be kept in sync with evmregistry/v21/mercury/upkeep_states.go - // TODO (AUTO-7928) Remove this duplication // pipeline execution error - NoPipelineError uint8 = 0 - CheckBlockTooOld uint8 = 1 - CheckBlockInvalid uint8 = 2 - RpcFlakyFailure uint8 = 3 - MercuryFlakyFailure uint8 = 4 - PackUnpackDecodeFailed uint8 = 5 - MercuryUnmarshalError uint8 = 6 - InvalidMercuryRequest uint8 = 7 - InvalidMercuryResponse uint8 = 8 // this will only happen if Mercury server sends bad responses - UpkeepNotAuthorized uint8 = 9 + NoPipelineError PipelineExecutionState = 0 + CheckBlockTooOld PipelineExecutionState = 1 + CheckBlockInvalid PipelineExecutionState = 2 + RpcFlakyFailure PipelineExecutionState = 3 + MercuryFlakyFailure PipelineExecutionState = 4 + PackUnpackDecodeFailed PipelineExecutionState = 5 + MercuryUnmarshalError PipelineExecutionState = 6 + InvalidMercuryRequest PipelineExecutionState = 7 + InvalidMercuryResponse PipelineExecutionState = 8 // this will only happen if Mercury server sends bad responses + UpkeepNotAuthorized PipelineExecutionState = 9 ) type UpkeepInfo = iregistry21.KeeperRegistryBase21UpkeepInfo type Packer interface { UnpackCheckResult(payload ocr2keepers.UpkeepPayload, raw string) (ocr2keepers.CheckResult, error) - UnpackPerformResult(raw string) (uint8, bool, error) + UnpackPerformResult(raw string) (PipelineExecutionState, bool, error) UnpackLogTriggerConfig(raw []byte) (automation_utils_2_1.LogTriggerConfig, error) PackReport(report automation_utils_2_1.KeeperRegistryBase21Report) ([]byte, error) UnpackReport(raw []byte) (automation_utils_2_1.KeeperRegistryBase21Report, error) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go index 4a92b4a17ec..7db8b220a4d 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go @@ -66,7 +66,7 @@ func (p *abiPacker) UnpackCheckResult(payload ocr2keepers.UpkeepPayload, raw str return result, nil } -func (p *abiPacker) UnpackPerformResult(raw string) (uint8, bool, error) { +func (p *abiPacker) UnpackPerformResult(raw string) (PipelineExecutionState, bool, error) { b, err := hexutil.Decode(raw) if err != nil { return PackUnpackDecodeFailed, false, err @@ -134,10 +134,10 @@ func (p *abiPacker) UnpackReport(raw []byte) (automation_utils_2_1.KeeperRegistr } // GetIneligibleCheckResultWithoutPerformData returns an ineligible check result with ineligibility reason and pipeline execution state but without perform data -func GetIneligibleCheckResultWithoutPerformData(p ocr2keepers.UpkeepPayload, reason uint8, state uint8, retryable bool) ocr2keepers.CheckResult { +func GetIneligibleCheckResultWithoutPerformData(p ocr2keepers.UpkeepPayload, reason UpkeepFailureReason, state PipelineExecutionState, retryable bool) ocr2keepers.CheckResult { return ocr2keepers.CheckResult{ - IneligibilityReason: reason, - PipelineExecutionState: state, + IneligibilityReason: uint8(reason), + PipelineExecutionState: uint8(state), Retryable: retryable, UpkeepID: p.UpkeepID, Trigger: p.Trigger, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go index 71c2755f150..3f08fcf0a2d 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go @@ -209,7 +209,7 @@ func TestPacker_UnpackPerformResult(t *testing.T) { tests := []struct { Name string RawData string - State uint8 + State PipelineExecutionState }{ { Name: "unpack success", diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go index 10e77bf50ce..d3a5167ef72 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go @@ -69,7 +69,7 @@ type MercuryData struct { Error error Retryable bool Bytes [][]byte - State MercuryUpkeepState + State encoding.PipelineExecutionState } type MercuryConfigProvider interface { @@ -85,7 +85,7 @@ type HttpClient interface { } type MercuryClient interface { - DoRequest(ctx context.Context, streamsLookup *StreamsLookup, pluginRetryKey string) (MercuryUpkeepState, MercuryUpkeepFailureReason, [][]byte, bool, time.Duration, error) + DoRequest(ctx context.Context, streamsLookup *StreamsLookup, pluginRetryKey string) (encoding.PipelineExecutionState, encoding.UpkeepFailureReason, [][]byte, bool, time.Duration, error) } type StreamsLookupError struct { @@ -116,7 +116,7 @@ func (l *StreamsLookup) IsMercuryV03UsingBlockNumber() bool { } type Packer interface { - UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) + UnpackCheckCallbackResult(callbackResp []byte) (encoding.PipelineExecutionState, bool, []byte, encoding.UpkeepFailureReason, *big.Int, error) PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error) DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError, error) @@ -149,7 +149,7 @@ func (p *abiPacker) DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError }, nil } -func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) { +func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (encoding.PipelineExecutionState, bool, []byte, encoding.UpkeepFailureReason, *big.Int, error) { out, err := p.registryABI.Methods["checkCallback"].Outputs.UnpackValues(callbackResp) if err != nil { return encoding.PackUnpackDecodeFailed, false, nil, 0, nil, fmt.Errorf("%w: unpack checkUpkeep return: %s", err, hexutil.Encode(callbackResp)) @@ -157,7 +157,7 @@ func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, upkeepNeeded := *abi.ConvertType(out[0], new(bool)).(*bool) rawPerformData := *abi.ConvertType(out[1], new([]byte)).(*[]byte) - failureReason := *abi.ConvertType(out[2], new(uint8)).(*uint8) + failureReason := encoding.UpkeepFailureReason(*abi.ConvertType(out[2], new(uint8)).(*uint8)) gasUsed := *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) return encoding.NoPipelineError, upkeepNeeded, rawPerformData, failureReason, gasUsed, nil diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go index 6095e7b9466..c7e22d45878 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go @@ -191,17 +191,17 @@ func TestPacker_UnpackCheckCallbackResult(t *testing.T) { CallbackResp []byte UpkeepNeeded bool PerformData []byte - FailureReason uint8 + FailureReason encoding.UpkeepFailureReason GasUsed *big.Int ErrorString string - State uint8 + State encoding.PipelineExecutionState }{ { Name: "unpack upkeep needed", CallbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, UpkeepNeeded: true, PerformData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - FailureReason: uint8(encoding.UpkeepFailureReasonNone), + FailureReason: encoding.UpkeepFailureReasonNone, GasUsed: big.NewInt(11796), }, { @@ -209,7 +209,7 @@ func TestPacker_UnpackCheckCallbackResult(t *testing.T) { CallbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, UpkeepNeeded: false, PerformData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - FailureReason: uint8(encoding.UpkeepFailureReasonUpkeepNotNeeded), + FailureReason: encoding.UpkeepFailureReasonUpkeepNotNeeded, GasUsed: big.NewInt(13008), }, { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go index e1bb69f33d8..27aafeca553 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go @@ -21,6 +21,7 @@ import ( iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" v02 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02" v03 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03" @@ -114,7 +115,7 @@ func (s *streams) Lookup(ctx context.Context, checkResults []ocr2keepers.CheckRe // buildResult checks if the upkeep is allowed by Mercury and builds a streams lookup request from the check result func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keepers.CheckResult, checkResults []ocr2keepers.CheckResult, lookups map[int]*mercury.StreamsLookup) { lookupLggr := s.lggr.With("where", "StreamsLookup") - if checkResult.IneligibilityReason != uint8(mercury.MercuryUpkeepFailureReasonTargetCheckReverted) { + if checkResult.IneligibilityReason != uint8(encoding.UpkeepFailureReasonTargetCheckReverted) { // Streams Lookup only works when upkeep target check reverts return } @@ -139,7 +140,7 @@ func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keeper streamsLookupResponse := &mercury.StreamsLookup{StreamsLookupError: streamsLookupErr} if len(streamsLookupResponse.Feeds) == 0 { - checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput) + checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonInvalidRevertDataInput) lookupLggr.Debugf("at block %s upkeep %s has empty feeds array", block, upkeepId) return } @@ -156,13 +157,13 @@ func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keeper return } else if !allowed { lookupLggr.Debugf("at block %d upkeep %s NOT allowed to query Mercury server", block, upkeepId) - checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonMercuryAccessNotAllowed) + checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonMercuryAccessNotAllowed) return } } else if !streamsLookupResponse.IsMercuryV03() { // if mercury version is not v02 or v03, set failure reason lookupLggr.Debugf("at block %d upkeep %s NOT allowed to query Mercury server", block, upkeepId) - checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput) + checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonInvalidRevertDataInput) return } @@ -191,7 +192,7 @@ func (s *streams) CheckCallback(ctx context.Context, values [][]byte, lookup *me payload, err := s.abi.Pack("checkCallback", lookup.UpkeepId, values, lookup.ExtraData) if err != nil { checkResults[i].Retryable = false - checkResults[i].PipelineExecutionState = uint8(mercury.PackUnpackDecodeFailed) + checkResults[i].PipelineExecutionState = uint8(encoding.PackUnpackDecodeFailed) return err } @@ -204,7 +205,7 @@ func (s *streams) CheckCallback(ctx context.Context, values [][]byte, lookup *me // call checkCallback function at the block which OCR3 has agreed upon if err = s.client.CallContext(ctx, &mercuryBytes, "eth_call", args, hexutil.EncodeUint64(lookup.Block)); err != nil { checkResults[i].Retryable = true - checkResults[i].PipelineExecutionState = uint8(mercury.RpcFlakyFailure) + checkResults[i].PipelineExecutionState = uint8(encoding.RpcFlakyFailure) return err } @@ -212,24 +213,23 @@ func (s *streams) CheckCallback(ctx context.Context, values [][]byte, lookup *me unpackCallBackState, needed, performData, failureReason, _, err := s.packer.UnpackCheckCallbackResult(mercuryBytes) if err != nil { - checkResults[i].PipelineExecutionState = unpackCallBackState + checkResults[i].PipelineExecutionState = uint8(unpackCallBackState) return err } - if failureReason == uint8(mercury.MercuryUpkeepFailureReasonMercuryCallbackReverted) { - checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonMercuryCallbackReverted) + if failureReason == encoding.UpkeepFailureReasonMercuryCallbackReverted { + checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonMercuryCallbackReverted) s.lggr.Debugf("at block %d upkeep %s requested time %s mercury callback reverts", lookup.Block, lookup.UpkeepId, lookup.Time) return nil - } if !needed { - checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonUpkeepNotNeeded) + checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonUpkeepNotNeeded) s.lggr.Debugf("at block %d upkeep %s requested time %s callback reports upkeep not needed", lookup.Block, lookup.UpkeepId, lookup.Time) return nil } - checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonNone) + checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonNone) checkResults[i].Eligible = true checkResults[i].PerformData = performData s.lggr.Infof("at block %d upkeep %s requested time %s CheckCallback successful with perform data: %s", lookup.Block, lookup.UpkeepId, lookup.Time, hexutil.Encode(performData)) @@ -238,7 +238,7 @@ func (s *streams) CheckCallback(ctx context.Context, values [][]byte, lookup *me } func (s *streams) DoMercuryRequest(ctx context.Context, lookup *mercury.StreamsLookup, checkResults []ocr2keepers.CheckResult, i int) ([][]byte, error) { - state, reason, values, retryable, retryInterval, err := mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0*time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", lookup.FeedParamKey, lookup.TimeParamKey, lookup.Feeds) + state, reason, values, retryable, retryInterval, err := encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0*time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", lookup.FeedParamKey, lookup.TimeParamKey, lookup.Feeds) pluginRetryKey := generatePluginRetryKey(checkResults[i].WorkID, lookup.Block) if lookup.IsMercuryV02() { @@ -263,10 +263,10 @@ func (s *streams) DoMercuryRequest(ctx context.Context, lookup *mercury.StreamsL // AllowedToUseMercury retrieves upkeep's administrative offchain config and decode a mercuryEnabled bool to indicate if // this upkeep is allowed to use Mercury service. -func (s *streams) AllowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (state mercury.MercuryUpkeepState, reason mercury.MercuryUpkeepFailureReason, retryable bool, allow bool, err error) { +func (s *streams) AllowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (state encoding.PipelineExecutionState, reason encoding.UpkeepFailureReason, retryable bool, allow bool, err error) { allowed, ok := s.mercuryConfig.IsUpkeepAllowed(upkeepId.String()) if ok { - return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonNone, false, allowed.(bool), nil + return encoding.NoPipelineError, encoding.UpkeepFailureReasonNone, false, allowed.(bool), nil } payload, err := s.packer.PackGetUpkeepPrivilegeConfig(upkeepId) @@ -274,7 +274,7 @@ func (s *streams) AllowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (s // pack error, no retryable s.lggr.Warnf("failed to pack getUpkeepPrivilegeConfig data for upkeepId %s: %s", upkeepId, err) - return mercury.PackUnpackDecodeFailed, mercury.MercuryUpkeepFailureReasonNone, false, false, fmt.Errorf("failed to pack upkeepId: %w", err) + return encoding.PackUnpackDecodeFailed, encoding.UpkeepFailureReasonNone, false, false, fmt.Errorf("failed to pack upkeepId: %w", err) } var resultBytes hexutil.Bytes @@ -284,29 +284,29 @@ func (s *streams) AllowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (s } if err = s.client.CallContext(opts.Context, &resultBytes, "eth_call", args, hexutil.EncodeBig(opts.BlockNumber)); err != nil { - return mercury.RpcFlakyFailure, mercury.MercuryUpkeepFailureReasonNone, true, false, fmt.Errorf("failed to get upkeep privilege config: %v", err) + return encoding.RpcFlakyFailure, encoding.UpkeepFailureReasonNone, true, false, fmt.Errorf("failed to get upkeep privilege config: %v", err) } var upkeepPrivilegeConfigBytes []byte upkeepPrivilegeConfigBytes, err = s.packer.UnpackGetUpkeepPrivilegeConfig(resultBytes) if err != nil { - return mercury.PackUnpackDecodeFailed, mercury.MercuryUpkeepFailureReasonNone, false, false, fmt.Errorf("failed to get upkeep privilege config: %v", err) + return encoding.PackUnpackDecodeFailed, encoding.UpkeepFailureReasonNone, false, false, fmt.Errorf("failed to get upkeep privilege config: %v", err) } if len(upkeepPrivilegeConfigBytes) == 0 { s.mercuryConfig.SetUpkeepAllowed(upkeepId.String(), false, cache.DefaultExpiration) - return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonMercuryAccessNotAllowed, false, false, fmt.Errorf("upkeep privilege config is empty") + return encoding.NoPipelineError, encoding.UpkeepFailureReasonMercuryAccessNotAllowed, false, false, fmt.Errorf("upkeep privilege config is empty") } var privilegeConfig UpkeepPrivilegeConfig if err = json.Unmarshal(upkeepPrivilegeConfigBytes, &privilegeConfig); err != nil { - return mercury.MercuryUnmarshalError, mercury.MercuryUpkeepFailureReasonNone, false, false, fmt.Errorf("failed to unmarshal privilege config: %v", err) + return encoding.MercuryUnmarshalError, encoding.UpkeepFailureReasonNone, false, false, fmt.Errorf("failed to unmarshal privilege config: %v", err) } s.mercuryConfig.SetUpkeepAllowed(upkeepId.String(), privilegeConfig.MercuryEnabled, cache.DefaultExpiration) - return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonNone, false, privilegeConfig.MercuryEnabled, nil + return encoding.NoPipelineError, encoding.UpkeepFailureReasonNone, false, privilegeConfig.MercuryEnabled, nil } func (s *streams) buildCallOpts(ctx context.Context, block *big.Int) *bind.CallOpts { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go index 54124b7c1a3..31b6597bb23 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go @@ -136,7 +136,7 @@ func TestStreams_CheckCallback(t *testing.T) { performData []byte wantErr assert.ErrorAssertionFunc - state mercury.MercuryUpkeepState + state encoding.PipelineExecutionState retryable bool registry streamsRegistry }{ @@ -230,7 +230,7 @@ func TestStreams_CheckCallback(t *testing.T) { callbackResp: []byte{}, callbackErr: errors.New("bad response"), wantErr: assert.Error, - state: mercury.RpcFlakyFailure, + state: encoding.RpcFlakyFailure, retryable: true, registry: &mockRegistry{ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { @@ -281,8 +281,8 @@ func TestStreams_AllowedToUseMercury(t *testing.T) { allowed bool ethCallErr error err error - state mercury.MercuryUpkeepState - reason mercury.MercuryUpkeepFailureReason + state encoding.PipelineExecutionState + reason encoding.UpkeepFailureReason registry streamsRegistry retryable bool config []byte @@ -340,7 +340,7 @@ func TestStreams_AllowedToUseMercury(t *testing.T) { { name: "failure - cannot unmarshal privilege config", err: fmt.Errorf("failed to unmarshal privilege config: invalid character '\\x00' looking for beginning of value"), - state: mercury.MercuryUnmarshalError, + state: encoding.MercuryUnmarshalError, config: []byte{0, 1}, registry: &mockRegistry{ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { @@ -355,7 +355,7 @@ func TestStreams_AllowedToUseMercury(t *testing.T) { name: "failure - flaky RPC", retryable: true, err: fmt.Errorf("failed to get upkeep privilege config: flaky RPC"), - state: mercury.RpcFlakyFailure, + state: encoding.RpcFlakyFailure, ethCallErr: fmt.Errorf("flaky RPC"), registry: &mockRegistry{ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { @@ -369,7 +369,7 @@ func TestStreams_AllowedToUseMercury(t *testing.T) { { name: "failure - empty upkeep privilege config", err: fmt.Errorf("upkeep privilege config is empty"), - reason: mercury.MercuryUpkeepFailureReasonMercuryAccessNotAllowed, + reason: encoding.UpkeepFailureReasonMercuryAccessNotAllowed, config: []byte{}, registry: &mockRegistry{ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { @@ -484,7 +484,7 @@ func TestStreams_StreamsLookup(t *testing.T) { Trigger: ocr2keepers.Trigger{ BlockNumber: blockNum, }, - IneligibilityReason: uint8(mercury.MercuryUpkeepFailureReasonTargetCheckReverted), + IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted), }, }, blobs: map[string]string{ @@ -521,6 +521,69 @@ func TestStreams_StreamsLookup(t *testing.T) { }, }, }, + { + name: "two CheckResults: Mercury success E2E and No Mercury because of insufficient balance", + input: []ocr2keepers.CheckResult{ + { + PerformData: []byte{}, + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: 26046145, + }, + IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance), + }, + { + PerformData: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000966656564496448657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: blockNum, + }, + IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted), + }, + }, + blobs: map[string]string{ + "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000": "0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3", + "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000": "0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d", + }, + cachedAdminCfg: false, + extraData: hexutil.MustDecode("0x0000000000000000000000000000000000000064"), + callbackNeeded: true, + checkCallbackResp: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063a400000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + values: [][]byte{hexutil.MustDecode("0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3"), hexutil.MustDecode("0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d")}, + expectedResults: []ocr2keepers.CheckResult{ + { + Eligible: false, + PerformData: []byte{}, + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: 26046145, + }, + IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance), + }, + { + Eligible: true, + PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: blockNum, + }, + IneligibilityReason: uint8(encoding.UpkeepFailureReasonNone), + }, + }, + hasPermission: true, + v3: false, + registry: &mockRegistry{ + GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { + return []byte(`{"mercuryEnabled":true}`), nil + }, + CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) { + return iregistry21.CheckCallback{ + UpkeepNeeded: true, + PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + }, nil + }, + }, + }, { name: "success - happy path no cache - v0.3", input: []ocr2keepers.CheckResult{ @@ -648,7 +711,7 @@ func TestStreams_StreamsLookup(t *testing.T) { Trigger: ocr2keepers.Trigger{ BlockNumber: blockNum, }, - IneligibilityReason: uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput), + IneligibilityReason: uint8(encoding.UpkeepFailureReasonInvalidRevertDataInput), }, }, hasError: true, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/upkeep_failure_reasons.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/upkeep_failure_reasons.go deleted file mode 100644 index 66f8bca402f..00000000000 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/upkeep_failure_reasons.go +++ /dev/null @@ -1,17 +0,0 @@ -package mercury - -type MercuryUpkeepFailureReason uint8 - -// NOTE: This enum should be kept in sync with evmregistry/v21/encoding/interface.go -// TODO (AUTO-7928) Remove this duplication -const ( - // upkeep failure onchain reasons - MercuryUpkeepFailureReasonNone MercuryUpkeepFailureReason = 0 - MercuryUpkeepFailureReasonTargetCheckReverted MercuryUpkeepFailureReason = 3 - MercuryUpkeepFailureReasonUpkeepNotNeeded MercuryUpkeepFailureReason = 4 - MercuryUpkeepFailureReasonMercuryCallbackReverted MercuryUpkeepFailureReason = 7 - // leaving a gap here for more onchain failure reasons in the future - // upkeep failure offchain reasons - MercuryUpkeepFailureReasonMercuryAccessNotAllowed MercuryUpkeepFailureReason = 32 - MercuryUpkeepFailureReasonInvalidRevertDataInput MercuryUpkeepFailureReason = 34 -) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/upkeep_states.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/upkeep_states.go deleted file mode 100644 index 0d8276ff2de..00000000000 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/upkeep_states.go +++ /dev/null @@ -1,16 +0,0 @@ -package mercury - -type MercuryUpkeepState uint8 - -// NOTE: This enum should be kept in sync with evmregistry/v21/encoding/interface.go -// TODO (AUTO-7928) Remove this duplication -const ( - NoPipelineError MercuryUpkeepState = 0 - RpcFlakyFailure MercuryUpkeepState = 3 - MercuryFlakyFailure MercuryUpkeepState = 4 - PackUnpackDecodeFailed MercuryUpkeepState = 5 - MercuryUnmarshalError MercuryUpkeepState = 6 - InvalidMercuryRequest MercuryUpkeepState = 7 - InvalidMercuryResponse MercuryUpkeepState = 8 // this will only happen if Mercury server sends bad responses - UpkeepNotAuthorized MercuryUpkeepState = 9 -) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go index 8135617b6fd..f69fbb35e35 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -52,11 +53,11 @@ func NewClient(mercuryConfig mercury.MercuryConfigProvider, httpClient mercury.H } } -func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLookup, pluginRetryKey string) (mercury.MercuryUpkeepState, mercury.MercuryUpkeepFailureReason, [][]byte, bool, time.Duration, error) { +func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLookup, pluginRetryKey string) (encoding.PipelineExecutionState, encoding.UpkeepFailureReason, [][]byte, bool, time.Duration, error) { resultLen := len(streamsLookup.Feeds) ch := make(chan mercury.MercuryData, resultLen) if len(streamsLookup.Feeds) == 0 { - return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", streamsLookup.FeedParamKey, streamsLookup.TimeParamKey, streamsLookup.Feeds) + return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", streamsLookup.FeedParamKey, streamsLookup.TimeParamKey, streamsLookup.Feeds) } for i := range streamsLookup.Feeds { // TODO (AUTO-7209): limit the number of concurrent requests @@ -72,15 +73,15 @@ func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLo retryable := true allSuccess := true // in v0.2, use the last execution error as the state, if no execution errors, state will be no error - state := mercury.NoPipelineError + state := encoding.NoPipelineError for i := 0; i < resultLen; i++ { m := <-ch if m.Error != nil { reqErr = errors.Join(reqErr, m.Error) retryable = retryable && m.Retryable allSuccess = false - if m.State != mercury.NoPipelineError { - state = mercury.MercuryUpkeepState(m.State) + if m.State != encoding.NoPipelineError { + state = encoding.PipelineExecutionState(m.State) } continue } @@ -90,7 +91,7 @@ func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLo retryInterval = mercury.CalculateRetryConfigFn(pluginRetryKey, c.mercuryConfig) } // only retry when not all successful AND none are not retryable - return state, mercury.MercuryUpkeepFailureReasonNone, results, retryable && !allSuccess, retryInterval, reqErr + return state, encoding.UpkeepFailureReasonNone, results, retryable && !allSuccess, retryInterval, reqErr } func (c *client) singleFeedRequest(ctx context.Context, ch chan<- mercury.MercuryData, index int, sl *mercury.StreamsLookup) { @@ -107,7 +108,7 @@ func (c *client) singleFeedRequest(ctx context.Context, ch chan<- mercury.Mercur httpRequest, err = http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil) if err != nil { - ch <- mercury.MercuryData{Index: index, Error: err, Retryable: false, State: mercury.InvalidMercuryRequest} + ch <- mercury.MercuryData{Index: index, Error: err, Retryable: false, State: encoding.InvalidMercuryRequest} return } @@ -119,7 +120,7 @@ func (c *client) singleFeedRequest(ctx context.Context, ch chan<- mercury.Mercur httpRequest.Header.Set(signatureHeader, signature) // in the case of multiple retries here, use the last attempt's data - state := mercury.NoPipelineError + state := encoding.NoPipelineError retryable := false sent := false retryErr := retry.Do( @@ -132,13 +133,13 @@ func (c *client) singleFeedRequest(ctx context.Context, ch chan<- mercury.Mercur if httpResponse, err = c.httpClient.Do(httpRequest); err != nil { c.lggr.Warnf("at block %s upkeep %s GET request fails for feed %s: %v", sl.Time.String(), sl.UpkeepId.String(), sl.Feeds[index], err) retryable = true - state = mercury.MercuryFlakyFailure + state = encoding.MercuryFlakyFailure return err } defer httpResponse.Body.Close() if responseBody, err = io.ReadAll(httpResponse.Body); err != nil { - state = mercury.InvalidMercuryResponse + state = encoding.InvalidMercuryResponse return err } @@ -146,12 +147,12 @@ func (c *client) singleFeedRequest(ctx context.Context, ch chan<- mercury.Mercur case http.StatusNotFound, http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout: c.lggr.Warnf("at block %s upkeep %s received status code %d for feed %s", sl.Time.String(), sl.UpkeepId.String(), httpResponse.StatusCode, sl.Feeds[index]) retryable = true - state = mercury.MercuryFlakyFailure + state = encoding.MercuryFlakyFailure return errors.New(strconv.FormatInt(int64(httpResponse.StatusCode), 10)) case http.StatusOK: // continue default: - state = mercury.InvalidMercuryRequest + state = encoding.InvalidMercuryRequest return fmt.Errorf("at block %s upkeep %s received status code %d for feed %s", sl.Time.String(), sl.UpkeepId.String(), httpResponse.StatusCode, sl.Feeds[index]) } @@ -160,19 +161,19 @@ func (c *client) singleFeedRequest(ctx context.Context, ch chan<- mercury.Mercur var m MercuryV02Response if err = json.Unmarshal(responseBody, &m); err != nil { c.lggr.Warnf("at block %s upkeep %s failed to unmarshal body to MercuryV02Response for feed %s: %v", sl.Time.String(), sl.UpkeepId.String(), sl.Feeds[index], err) - state = mercury.MercuryUnmarshalError + state = encoding.MercuryUnmarshalError return err } if blobBytes, err = hexutil.Decode(m.ChainlinkBlob); err != nil { c.lggr.Warnf("at block %s upkeep %s failed to decode chainlinkBlob %s for feed %s: %v", sl.Time.String(), sl.UpkeepId.String(), m.ChainlinkBlob, sl.Feeds[index], err) - state = mercury.InvalidMercuryResponse + state = encoding.InvalidMercuryResponse return err } ch <- mercury.MercuryData{ Index: index, Bytes: [][]byte{blobBytes}, Retryable: false, - State: mercury.NoPipelineError, + State: encoding.NoPipelineError, } sent = true return nil diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go index ac945859d89..686b2199ebc 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -289,8 +290,8 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { expectedRetryable bool expectedRetryInterval time.Duration expectedError error - state mercury.MercuryUpkeepState - reason mercury.MercuryUpkeepFailureReason + state encoding.PipelineExecutionState + reason encoding.UpkeepFailureReason }{ { name: "success", @@ -329,7 +330,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { pluginRetries: 0, expectedRetryInterval: 1 * time.Second, expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"), - state: mercury.MercuryFlakyFailure, + state: encoding.MercuryFlakyFailure, }, { name: "failure - retryable and interval is 5s", @@ -350,7 +351,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { expectedRetryable: true, expectedRetryInterval: 5 * time.Second, expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"), - state: mercury.MercuryFlakyFailure, + state: encoding.MercuryFlakyFailure, }, { name: "failure - not retryable because there are many plugin retries already", @@ -370,7 +371,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { expectedValues: [][]byte{nil}, expectedRetryable: true, expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"), - state: mercury.MercuryFlakyFailure, + state: encoding.MercuryFlakyFailure, }, { name: "failure - not retryable", @@ -389,7 +390,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { expectedValues: [][]byte{nil}, expectedRetryable: false, expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 25880526 upkeep 88786950015966611018675766524283132478093844178961698330929478019253453382042 received status code 429 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"), - state: mercury.InvalidMercuryRequest, + state: encoding.InvalidMercuryRequest, }, { name: "failure - no feeds", @@ -404,7 +405,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { UpkeepId: upkeepId, }, expectedValues: [][]byte{}, - reason: mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, + reason: encoding.UpkeepFailureReasonInvalidRevertDataInput, }, { name: "failure - invalid revert data", @@ -419,7 +420,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { UpkeepId: upkeepId, }, expectedValues: [][]byte{}, - reason: mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, + reason: encoding.UpkeepFailureReasonInvalidRevertDataInput, }, } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go index ea465ff8582..584069adde3 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -60,9 +61,9 @@ func NewClient(mercuryConfig mercury.MercuryConfigProvider, httpClient mercury.H } } -func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLookup, pluginRetryKey string) (mercury.MercuryUpkeepState, mercury.MercuryUpkeepFailureReason, [][]byte, bool, time.Duration, error) { +func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLookup, pluginRetryKey string) (encoding.PipelineExecutionState, encoding.UpkeepFailureReason, [][]byte, bool, time.Duration, error) { if len(streamsLookup.Feeds) == 0 { - return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", streamsLookup.FeedParamKey, streamsLookup.TimeParamKey, streamsLookup.Feeds) + return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", streamsLookup.FeedParamKey, streamsLookup.TimeParamKey, streamsLookup.Feeds) } resultLen := 1 // Only 1 multi-feed request is made for all feeds ch := make(chan mercury.MercuryData, resultLen) @@ -74,7 +75,7 @@ func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLo var retryInterval time.Duration results := make([][]byte, len(streamsLookup.Feeds)) retryable := false - state := mercury.NoPipelineError + state := encoding.NoPipelineError m := <-ch if m.Error != nil { @@ -88,7 +89,7 @@ func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLo results = m.Bytes } - return state, mercury.MercuryUpkeepFailureReasonNone, results, retryable, retryInterval, reqErr + return state, encoding.UpkeepFailureReasonNone, results, retryable, retryInterval, reqErr } func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.MercuryData, sl *mercury.StreamsLookup) { @@ -109,7 +110,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil) if err != nil { - ch <- mercury.MercuryData{Index: 0, Error: err, Retryable: false, State: mercury.InvalidMercuryRequest} + ch <- mercury.MercuryData{Index: 0, Error: err, Retryable: false, State: encoding.InvalidMercuryRequest} return } @@ -126,7 +127,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur req.Header.Set(upkeepIDHeader, sl.UpkeepId.String()) // in the case of multiple retries here, use the last attempt's data - state := mercury.NoPipelineError + state := encoding.NoPipelineError retryable := false sent := false retryErr := retry.Do( @@ -136,7 +137,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur if err != nil { c.lggr.Warnf("at timestamp %s upkeep %s GET request fails from mercury v0.3: %v", sl.Time.String(), sl.UpkeepId.String(), err) retryable = true - state = mercury.MercuryFlakyFailure + state = encoding.MercuryFlakyFailure return err } defer resp.Body.Close() @@ -144,7 +145,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur body, err := io.ReadAll(resp.Body) if err != nil { retryable = false - state = mercury.InvalidMercuryResponse + state = encoding.InvalidMercuryResponse return err } @@ -152,27 +153,27 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur switch resp.StatusCode { case http.StatusUnauthorized: retryable = false - state = mercury.UpkeepNotAuthorized + state = encoding.UpkeepNotAuthorized return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by unauthorized upkeep", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode) case http.StatusBadRequest: retryable = false - state = mercury.InvalidMercuryRequest + state = encoding.InvalidMercuryRequest return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by invalid format of timestamp", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode) case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout: retryable = true - state = mercury.MercuryFlakyFailure + state = encoding.MercuryFlakyFailure return fmt.Errorf("%d", resp.StatusCode) case http.StatusPartialContent: // TODO (AUTO-5044): handle response code 206 entirely with errors field parsing c.lggr.Warnf("at timestamp %s upkeep %s requested [%s] feeds but mercury v0.3 server returned 206 status, treating it as 404 and retrying", sl.Time.String(), sl.UpkeepId.String(), sl.Feeds) retryable = true - state = mercury.MercuryFlakyFailure + state = encoding.MercuryFlakyFailure return fmt.Errorf("%d", http.StatusPartialContent) case http.StatusOK: // continue default: retryable = false - state = mercury.InvalidMercuryRequest + state = encoding.InvalidMercuryRequest return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode) } c.lggr.Debugf("at block %s upkeep %s received status code %d from mercury v0.3 with BODY=%s", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode, hexutil.Encode(body)) @@ -181,7 +182,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur if err := json.Unmarshal(body, &response); err != nil { c.lggr.Warnf("at timestamp %s upkeep %s failed to unmarshal body to MercuryV03Response from mercury v0.3: %v", sl.Time.String(), sl.UpkeepId.String(), err) retryable = false - state = mercury.MercuryUnmarshalError + state = encoding.MercuryUnmarshalError return err } @@ -194,7 +195,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur } c.lggr.Warnf("at timestamp %s upkeep %s mercury v0.3 server returned 206 status with [%s] reports while we requested [%s] feeds, retrying", sl.Time.String(), sl.UpkeepId.String(), receivedFeeds, sl.Feeds) retryable = true - state = mercury.MercuryFlakyFailure + state = encoding.MercuryFlakyFailure return fmt.Errorf("%d", http.StatusNotFound) } var reportBytes [][]byte @@ -203,7 +204,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur if err != nil { c.lggr.Warnf("at timestamp %s upkeep %s failed to decode reportBlob %s: %v", sl.Time.String(), sl.UpkeepId.String(), rsp.FullReport, err) retryable = false - state = mercury.InvalidMercuryResponse + state = encoding.InvalidMercuryResponse return err } reportBytes = append(reportBytes, b) @@ -212,7 +213,7 @@ func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.Mercur Index: 0, Bytes: reportBytes, Retryable: false, - State: mercury.NoPipelineError, + State: encoding.NoPipelineError, } sent = true return nil diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go index 16ccdac5d1f..4a22ae477e6 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -108,8 +109,8 @@ func TestV03_DoMercuryRequestV03(t *testing.T) { expectedRetryable bool expectedRetryInterval time.Duration expectedError error - state mercury.MercuryUpkeepState - reason mercury.MercuryUpkeepFailureReason + state encoding.PipelineExecutionState + reason encoding.UpkeepFailureReason }{ { name: "success v0.3", diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go index f5a931aae45..33d4a7157be 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go @@ -105,7 +105,7 @@ func (r *EvmRegistry) getBlockHash(blockNumber *big.Int) (common.Hash, error) { } // verifyCheckBlock checks that the check block and hash are valid, returns the pipeline execution state and retryable -func (r *EvmRegistry) verifyCheckBlock(_ context.Context, checkBlock, upkeepId *big.Int, checkHash common.Hash) (state uint8, retryable bool) { +func (r *EvmRegistry) verifyCheckBlock(_ context.Context, checkBlock, upkeepId *big.Int, checkHash common.Hash) (state encoding.PipelineExecutionState, retryable bool) { // verify check block number and hash are valid h, ok := r.bs.queryBlocksMap(checkBlock.Int64()) // if this block number/hash combo exists in block subscriber, this check block and hash still exist on chain and are valid @@ -128,7 +128,7 @@ func (r *EvmRegistry) verifyCheckBlock(_ context.Context, checkBlock, upkeepId * } // verifyLogExists checks that the log still exists on chain, returns failure reason, pipeline error, and retryable -func (r *EvmRegistry) verifyLogExists(upkeepId *big.Int, p ocr2keepers.UpkeepPayload) (uint8, uint8, bool) { +func (r *EvmRegistry) verifyLogExists(upkeepId *big.Int, p ocr2keepers.UpkeepPayload) (encoding.UpkeepFailureReason, encoding.PipelineExecutionState, bool) { logBlockNumber := int64(p.Trigger.LogTriggerExtension.BlockNumber) logBlockHash := common.BytesToHash(p.Trigger.LogTriggerExtension.BlockHash[:]) checkBlockHash := common.BytesToHash(p.Trigger.BlockHash[:]) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go index a14aaec0c5e..9867a58201b 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go @@ -90,7 +90,7 @@ func TestRegistry_VerifyCheckBlock(t *testing.T) { payload ocr2keepers.UpkeepPayload blocks map[int64]string poller logpoller.LogPoller - state uint8 + state encoding.PipelineExecutionState retryable bool makeEthCall bool }{ @@ -248,8 +248,8 @@ func TestRegistry_VerifyLogExists(t *testing.T) { payload ocr2keepers.UpkeepPayload blocks map[int64]string makeEthCall bool - reason uint8 - state uint8 + reason encoding.UpkeepFailureReason + state encoding.PipelineExecutionState retryable bool ethCallErr error receipt *types.Receipt diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go index c3c60ad58b1..199bbac0536 100644 --- a/core/services/ocr2/plugins/ocr2keeper/util.go +++ b/core/services/ocr2/plugins/ocr2keeper/util.go @@ -3,6 +3,10 @@ package ocr2keeper import ( "fmt" + "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" @@ -12,19 +16,16 @@ import ( ocr2keepers20polling "github.com/smartcontractkit/chainlink-automation/pkg/v2/observer/polling" ocr2keepers20runner "github.com/smartcontractkit/chainlink-automation/pkg/v2/runner" ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" 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" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) type Encoder20 interface { @@ -115,24 +116,18 @@ func EVMDependencies21( mc *models.MercuryCredentials, keyring ocrtypes.OnchainKeyring, dbCfg pg.QConfig, - ethKeystore keystore.Eth, -) (evmrelay.OCR2KeeperProvider, evmregistry21.AutomationServices, error) { +) (evmregistry21.AutomationServices, error) { var err error - var keeperProvider evmrelay.OCR2KeeperProvider oSpec := spec.OCR2OracleSpec - // the provider will be returned as a dependency - if keeperProvider, err = EVMProvider(db, chain, lggr, spec, ethKeystore); err != nil { - return nil, nil, err - } rAddr := ethkey.MustEIP55Address(oSpec.ContractID).Address() services, err := evmregistry21.New(rAddr, chain, mc, keyring, lggr, db, dbCfg) if err != nil { - return nil, nil, err + return nil, err } - return keeperProvider, services, err + return services, err } func FilterNamesFromSpec21(spec *job.OCR2OracleSpec) (names []string, err error) { 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 c559fb27fb7..55517d5719d 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -14,7 +14,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/hashicorp/consul/sdk/freeport" @@ -31,8 +30,10 @@ import ( "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "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" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" @@ -55,7 +56,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ocr2vrfUniverse struct { @@ -134,13 +134,13 @@ func setupOCR2VRFContracts( require.NoError(t, err) b.Commit() - require.NoError(t, utils.JustError(coordinator.SetCallbackConfig(owner, vrf_wrapper.VRFCoordinatorCallbackConfig{ + require.NoError(t, commonutils.JustError(coordinator.SetCallbackConfig(owner, vrf_wrapper.VRFCoordinatorCallbackConfig{ MaxCallbackGasLimit: 2.5e6, MaxCallbackArgumentsLength: 160, // 5 EVM words }))) b.Commit() - require.NoError(t, utils.JustError(coordinator.SetCoordinatorConfig(owner, vrf_wrapper.VRFBeaconTypesCoordinatorConfig{ + require.NoError(t, commonutils.JustError(coordinator.SetCoordinatorConfig(owner, vrf_wrapper.VRFBeaconTypesCoordinatorConfig{ RedeemableRequestGasOverhead: 50_000, CallbackRequestGasOverhead: 50_000, StalenessSeconds: 60, @@ -164,7 +164,7 @@ func setupOCR2VRFContracts( b.Commit() // Set up coordinator subscription for billing. - require.NoError(t, utils.JustError(coordinator.CreateSubscription(owner))) + require.NoError(t, commonutils.JustError(coordinator.CreateSubscription(owner))) b.Commit() fopts := &bind.FilterOpts{} @@ -175,13 +175,13 @@ func setupOCR2VRFContracts( require.True(t, subscriptionIterator.Next()) subID := subscriptionIterator.Event.SubId - require.NoError(t, utils.JustError(coordinator.AddConsumer(owner, subID, consumerAddress))) + require.NoError(t, commonutils.JustError(coordinator.AddConsumer(owner, subID, consumerAddress))) b.Commit() - require.NoError(t, utils.JustError(coordinator.AddConsumer(owner, subID, loadTestConsumerAddress))) + require.NoError(t, commonutils.JustError(coordinator.AddConsumer(owner, subID, loadTestConsumerAddress))) b.Commit() data, err := utils.ABIEncode(`[{"type":"uint256"}]`, subID) require.NoError(t, err) - require.NoError(t, utils.JustError(link.TransferAndCall(owner, coordinatorAddress, big.NewInt(5e18), data))) + require.NoError(t, commonutils.JustError(link.TransferAndCall(owner, coordinatorAddress, big.NewInt(5e18), data))) b.Commit() _, err = dkg.AddClient(owner, keyID, beaconAddress) @@ -299,7 +299,7 @@ func setupNodeOCR2( n, err := b.NonceAt(testutils.Context(t), owner.From, nil) require.NoError(t, err) - tx := types.NewTransaction( + tx := cltest.NewLegacyTransaction( n, k.Address, assets.Ether(1).ToInt(), 21000, @@ -663,7 +663,7 @@ linkEthFeedAddress = "%s" // Fund the payee with some ETH. n, err2 := uni.backend.NonceAt(testutils.Context(t), uni.owner.From, nil) require.NoError(t, err2) - tx := types.NewTransaction( + tx := cltest.NewLegacyTransaction( n, payeeTransactor.From, assets.Ether(1).ToInt(), 21000, diff --git a/core/services/ocrcommon/arbitrum_block_translator_test.go b/core/services/ocrcommon/arbitrum_block_translator_test.go index b7d1b4e60c2..1ad3a6c5950 100644 --- a/core/services/ocrcommon/arbitrum_block_translator_test.go +++ b/core/services/ocrcommon/arbitrum_block_translator_test.go @@ -6,12 +6,12 @@ import ( "testing" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go index 5fbda456088..b641bd2b3cf 100644 --- a/core/services/ocrcommon/telemetry.go +++ b/core/services/ocrcommon/telemetry.go @@ -234,19 +234,23 @@ func (e *EnhancedTelemetryService[T]) collectAndSend(trrs *pipeline.TaskRunResul if trr.Task.Type() != pipeline.TaskTypeBridge { continue } + var bridgeName string + if b, is := trr.Task.(*pipeline.BridgeTask); is { + bridgeName = b.Name + } if trr.Result.Error != nil { - e.lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, job %d, id %s", e.job.ID, trr.Task.DotID()), "err", trr.Result.Error) + e.lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, job=%d, id=%s, name=%q", e.job.ID, trr.Task.DotID(), bridgeName), "err", trr.Result.Error, "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } bridgeRawResponse, ok := trr.Result.Value.(string) if !ok { - e.lggr.Warnf("cannot parse bridge response from bridge task, job %d, id %s: expected string, got: %v (type %T)", e.job.ID, trr.Task.DotID(), trr.Result.Value, trr.Result.Value) + e.lggr.Warnw(fmt.Sprintf("cannot parse bridge response from bridge task, job=%d, id=%s, name=%q: expected string, got: %v (type %T)", e.job.ID, trr.Task.DotID(), bridgeName, trr.Result.Value, trr.Result.Value), "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse)) if err != nil { - e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job %d, id %s", e.job.ID, trr.Task.DotID()), "err", err) + e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job=%d, id=%s, name=%q", e.job.ID, trr.Task.DotID(), bridgeName), "err", err, "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } value := e.getParsedValue(trrs, trr) @@ -359,15 +363,16 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(d Enhanced continue } bridgeTask := trr.Task.(*pipeline.BridgeTask) + bridgeName := bridgeTask.Name bridgeRawResponse, ok := trr.Result.Value.(string) if !ok { - e.lggr.Warnf("cannot get bridge response from bridge task, job %d, id %s, expected string got %T", e.job.ID, trr.Task.DotID(), trr.Result.Value) + e.lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, job=%d, id=%s, name=%q, expected string got %T", e.job.ID, trr.Task.DotID(), bridgeName, trr.Result.Value), "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse)) if err != nil { - e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job %d, id %s", e.job.ID, trr.Task.DotID()), "err", err) + e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job=%d, id=%s, name=%q", e.job.ID, trr.Task.DotID(), bridgeName), "err", err, "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) } assetSymbol := e.getAssetSymbolFromRequestData(bridgeTask.RequestData) diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go index 7627a627dea..caa8ccfcc01 100644 --- a/core/services/ocrcommon/telemetry_test.go +++ b/core/services/ocrcommon/telemetry_test.go @@ -19,6 +19,7 @@ import ( mercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" mercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -28,7 +29,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const bridgeResponse = `{ @@ -46,6 +46,7 @@ const bridgeResponse = `{ var trrs = pipeline.TaskRunResults{ pipeline.TaskRunResult{ Task: &pipeline.BridgeTask{ + Name: "test-bridge-1", BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), }, Result: pipeline.Result{ @@ -62,6 +63,7 @@ var trrs = pipeline.TaskRunResults{ }, pipeline.TaskRunResult{ Task: &pipeline.BridgeTask{ + Name: "test-bridge-2", BaseTask: pipeline.NewBaseTask(0, "ds2", nil, nil, 0), }, Result: pipeline.Result{ @@ -78,6 +80,7 @@ var trrs = pipeline.TaskRunResults{ }, pipeline.TaskRunResult{ Task: &pipeline.BridgeTask{ + Name: "test-bridge-3", BaseTask: pipeline.NewBaseTask(0, "ds3", nil, nil, 0), }, Result: pipeline.Result{ @@ -390,6 +393,7 @@ func TestCollectAndSend(t *testing.T) { var trrsMercuryV1 = pipeline.TaskRunResults{ pipeline.TaskRunResult{ Task: &pipeline.BridgeTask{ + Name: "link-usd-test-bridge-v1", BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), RequestData: `{"data":{"to":"LINK","from":"USD"}}`, }, @@ -426,6 +430,7 @@ var trrsMercuryV1 = pipeline.TaskRunResults{ var trrsMercuryV2 = pipeline.TaskRunResults{ pipeline.TaskRunResult{ Task: &pipeline.BridgeTask{ + Name: "link-usd-test-bridge-v2", BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), RequestData: `{"data":{"to":"LINK","from":"USD"}}`, }, @@ -477,6 +482,7 @@ func TestGetPricesFromResults(t *testing.T) { trrs2 := pipeline.TaskRunResults{ pipeline.TaskRunResult{ Task: &pipeline.BridgeTask{ + Name: "test-bridge-1", BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), }, Result: pipeline.Result{ @@ -630,6 +636,7 @@ func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) { chTelem <- EnhancedTelemetryMercuryData{ TaskRunResults: pipeline.TaskRunResults{ pipeline.TaskRunResult{Task: &pipeline.BridgeTask{ + Name: "test-mercury-bridge-1", BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), }, Result: pipeline.Result{ @@ -657,7 +664,7 @@ func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) { wg.Wait() require.Equal(t, 2, logs.Len()) - require.Contains(t, logs.All()[0].Message, "cannot get bridge response from bridge task") + require.Contains(t, logs.All()[0].Message, `cannot get bridge response from bridge task, job=0, id=ds1, name="test-mercury-bridge-1"`) require.Contains(t, logs.All()[1].Message, "cannot parse EA telemetry") chDone <- struct{}{} } @@ -744,6 +751,7 @@ func TestCollectMercuryEnhancedTelemetryV2(t *testing.T) { chTelem <- EnhancedTelemetryMercuryData{ TaskRunResults: pipeline.TaskRunResults{ pipeline.TaskRunResult{Task: &pipeline.BridgeTask{ + Name: "test-mercury-bridge-2", BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), }, Result: pipeline.Result{ diff --git a/core/services/pg/event_broadcaster.go b/core/services/pg/event_broadcaster.go deleted file mode 100644 index 70008f4c0de..00000000000 --- a/core/services/pg/event_broadcaster.go +++ /dev/null @@ -1,345 +0,0 @@ -package pg - -import ( - "context" - "database/sql" - "net/url" - "sync" - "time" - - "github.com/google/uuid" - "github.com/lib/pq" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/static" - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -//go:generate mockery --quiet --name EventBroadcaster --output ./mocks/ --case=underscore -//go:generate mockery --quiet --name Subscription --output ./mocks/ --case=underscore - -// EventBroadcaster opaquely manages a collection of Postgres event listeners -// and broadcasts events to subscribers (with an optional payload filter). -type EventBroadcaster interface { - services.Service - Subscribe(channel, payloadFilter string) (Subscription, error) - Notify(channel string, payload string) error -} - -type eventBroadcaster struct { - services.StateMachine - uri string - minReconnectInterval time.Duration - maxReconnectDuration time.Duration - db *sql.DB - listener *pq.Listener - subscriptions map[string]map[Subscription]struct{} - subscriptionsMu sync.RWMutex - chStop chan struct{} - chDone chan struct{} - lggr logger.Logger -} - -var _ EventBroadcaster = (*eventBroadcaster)(nil) - -type Event struct { - Channel string - Payload string -} - -func NewEventBroadcaster(uri url.URL, minReconnectInterval time.Duration, maxReconnectDuration time.Duration, lggr logger.Logger, appID uuid.UUID) *eventBroadcaster { - if minReconnectInterval == time.Duration(0) { - minReconnectInterval = 1 * time.Second - } - if maxReconnectDuration == time.Duration(0) { - maxReconnectDuration = 1 * time.Minute - } - static.SetConsumerName(&uri, "EventBroadcaster", &appID) - return &eventBroadcaster{ - uri: uri.String(), - minReconnectInterval: minReconnectInterval, - maxReconnectDuration: maxReconnectDuration, - subscriptions: make(map[string]map[Subscription]struct{}), - chStop: make(chan struct{}), - chDone: make(chan struct{}), - lggr: lggr.Named("EventBroadcaster"), - } -} - -// Start starts EventBroadcaster. -func (b *eventBroadcaster) Start(context.Context) error { - return b.StartOnce("Postgres event broadcaster", func() (err error) { - // Explicitly using the lib/pq for notifications so we use the postgres driverName - // and NOT pgx. - db, err := sql.Open("postgres", b.uri) - if err != nil { - return err - } - b.db = db - b.listener = pq.NewListener(b.uri, b.minReconnectInterval, b.maxReconnectDuration, func(ev pq.ListenerEventType, err error) { - // sanity check since these can still be called after closing the listener - select { - case <-b.chStop: - return - default: - } - // These are always connection-related events, and the pq library - // automatically handles reconnecting to the DB. Therefore, we do not - // need to terminate, but rather simply log these events for node - // operators' sanity. - switch ev { - case pq.ListenerEventConnected: - b.lggr.Debug("Postgres event broadcaster: connected") - case pq.ListenerEventDisconnected: - b.lggr.Warnw("Postgres event broadcaster: disconnected, trying to reconnect...", "err", err) - case pq.ListenerEventReconnected: - b.lggr.Debug("Postgres event broadcaster: reconnected") - case pq.ListenerEventConnectionAttemptFailed: - b.lggr.Warnw("Postgres event broadcaster: reconnect attempt failed, trying again...", "err", err) - } - }) - - go b.runLoop() - return nil - }) -} - -// Stop permanently destroys the EventBroadcaster. Calling this does not clean -// up any outstanding subscriptions. Subscribers must explicitly call `.Close()` -// or they will leak goroutines. -func (b *eventBroadcaster) Close() error { - return b.StopOnce("Postgres event broadcaster", func() (err error) { - b.subscriptionsMu.RLock() - defer b.subscriptionsMu.RUnlock() - b.subscriptions = nil - - err = services.CloseAll(b.db, b.listener) - close(b.chStop) - <-b.chDone - return err - }) -} - -func (b *eventBroadcaster) Name() string { - return b.lggr.Name() -} - -func (b *eventBroadcaster) HealthReport() map[string]error { - return map[string]error{b.Name(): b.Healthy()} -} - -func (b *eventBroadcaster) runLoop() { - defer close(b.chDone) - for { - select { - case <-b.chStop: - return - - case notification, open := <-b.listener.NotificationChannel(): - if !open { - return - } else if notification == nil { - continue - } - b.lggr.Debugw("Postgres event broadcaster: received notification", - "channel", notification.Channel, - "payload", notification.Extra, - ) - b.broadcast(notification) - } - } -} - -func (b *eventBroadcaster) Notify(channel string, payload string) error { - _, err := b.db.Exec(`SELECT pg_notify($1, $2)`, channel, payload) - return errors.Wrap(err, "Postgres event broadcaster could not notify") -} - -func (b *eventBroadcaster) Subscribe(channel, payloadFilter string) (Subscription, error) { - b.subscriptionsMu.Lock() - defer b.subscriptionsMu.Unlock() - - if _, exists := b.subscriptions[channel]; !exists { - err := b.listener.Listen(channel) - if err != nil { - return nil, errors.Wrap(err, "Postgres event broadcaster could not subscribe") - } - b.subscriptions[channel] = make(map[Subscription]struct{}) - } - - sub := &subscription{ - channel: channel, - payloadFilter: payloadFilter, - eventBroadcaster: b, - queue: utils.NewBoundedQueue[Event](1000), - chEvents: make(chan Event), - chDone: make(chan struct{}), - lggr: logger.Sugared(b.lggr), - } - sub.processQueueWorker = utils.NewSleeperTask( - utils.SleeperFuncTask(sub.processQueue, "SubscriptionQueueProcessor"), - ) - b.subscriptions[channel][sub] = struct{}{} - return sub, nil -} - -func (b *eventBroadcaster) removeSubscription(sub Subscription) { - b.subscriptionsMu.Lock() - defer b.subscriptionsMu.Unlock() - - // The following conditions can occur on shutdown when .Stop() is called - // before one or more subscriptions' .Close() methods are called - if b.subscriptions == nil { - return - } - subs, exists := b.subscriptions[sub.ChannelName()] - if !exists || subs == nil { - return - } - - delete(b.subscriptions[sub.ChannelName()], sub) - if len(b.subscriptions[sub.ChannelName()]) == 0 { - err := b.listener.Unlisten(sub.ChannelName()) - if err != nil { - b.lggr.Errorw("Postgres event broadcaster: failed to unsubscribe", "err", err) - } - delete(b.subscriptions, sub.ChannelName()) - } -} - -func (b *eventBroadcaster) broadcast(notification *pq.Notification) { - b.subscriptionsMu.RLock() - defer b.subscriptionsMu.RUnlock() - - event := Event{ - Channel: notification.Channel, - Payload: notification.Extra, - } - - var wg sync.WaitGroup - for sub := range b.subscriptions[event.Channel] { - if sub.InterestedIn(event) { - wg.Add(1) - go func(sub Subscription) { - defer wg.Done() - sub.Send(event) - }(sub) - } - } - wg.Wait() -} - -// Subscription represents a subscription to a Postgres event channel -type Subscription interface { - Events() <-chan Event - Close() - - ChannelName() string - InterestedIn(event Event) bool - Send(event Event) -} - -type subscription struct { - channel string - payloadFilter string - eventBroadcaster *eventBroadcaster - queue *utils.BoundedQueue[Event] - processQueueWorker utils.SleeperTask - chEvents chan Event - chDone chan struct{} - lggr logger.SugaredLogger -} - -var _ Subscription = (*subscription)(nil) - -func (sub *subscription) InterestedIn(event Event) bool { - return sub.payloadFilter == event.Payload || sub.payloadFilter == "" -} - -func (sub *subscription) Send(event Event) { - sub.queue.Add(event) - sub.processQueueWorker.WakeUpIfStarted() -} - -const broadcastTimeout = 10 * time.Second - -func (sub *subscription) processQueue() { - deadline := time.Now().Add(broadcastTimeout) - for !sub.queue.Empty() { - event := sub.queue.Take() - select { - case sub.chEvents <- event: - case <-time.After(time.Until(deadline)): - sub.lggr.Warnf("Postgres event broadcaster: SLOW processQueue(), timed out after %s", broadcastTimeout) - return - case <-sub.chDone: - sub.lggr.Debugw("Postgres event broadcaster: request cancelled during processQueue()") - return - } - } -} - -func (sub *subscription) Events() <-chan Event { - return sub.chEvents -} - -func (sub *subscription) ChannelName() string { - return sub.channel -} - -func (sub *subscription) Close() { - sub.eventBroadcaster.removeSubscription(sub) - // Close chDone before stopping the SleeperTask to avoid deadlocks - close(sub.chDone) - err := sub.processQueueWorker.Stop() - if err != nil { - sub.lggr.Errorw("THIS NEVER RETURNS AN ERROR", "err", err) - } - close(sub.chEvents) -} - -// NullEventBroadcaster implements null pattern for event broadcaster -type NullEventBroadcaster struct { - Sub *NullSubscription -} - -func NewNullEventBroadcaster() *NullEventBroadcaster { - sub := &NullSubscription{make(chan (Event))} - return &NullEventBroadcaster{sub} -} - -var _ EventBroadcaster = &NullEventBroadcaster{} - -func (*NullEventBroadcaster) Name() string { return "NullEventBroadcaster" } - -// Start does no-op. -func (*NullEventBroadcaster) Start(context.Context) error { return nil } - -// Close does no-op. -func (*NullEventBroadcaster) Close() error { return nil } - -// Ready does no-op. -func (*NullEventBroadcaster) Ready() error { return nil } - -// HealthReport does no-op -func (*NullEventBroadcaster) HealthReport() map[string]error { return map[string]error{} } - -func (ne *NullEventBroadcaster) Subscribe(channel, payloadFilter string) (Subscription, error) { - return ne.Sub, nil -} -func (*NullEventBroadcaster) Notify(channel string, payload string) error { return nil } - -var _ Subscription = &NullSubscription{} - -type NullSubscription struct { - Ch chan (Event) -} - -func (ns *NullSubscription) Events() <-chan Event { return ns.Ch } -func (ns *NullSubscription) Close() {} -func (ns *NullSubscription) ChannelName() string { return "" } -func (ns *NullSubscription) InterestedIn(event Event) bool { return false } -func (ns *NullSubscription) Send(event Event) {} diff --git a/core/services/pg/event_broadcaster_test.go b/core/services/pg/event_broadcaster_test.go deleted file mode 100644 index e8a4a1086db..00000000000 --- a/core/services/pg/event_broadcaster_test.go +++ /dev/null @@ -1,239 +0,0 @@ -package pg_test - -import ( - "sync" - "testing" - "time" - - "github.com/google/uuid" - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" -) - -func TestEventBroadcaster(t *testing.T) { - config, _ := heavyweight.FullTestDBNoFixturesV2(t, nil) - - eventBroadcaster := pg.NewEventBroadcaster(config.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New()) - servicetest.Run(t, eventBroadcaster) - - t.Run("doesn't broadcast unrelated events (no payload filter)", func(t *testing.T) { - sub, err := eventBroadcaster.Subscribe("foo", "") - require.NoError(t, err) - defer sub.Close() - - go func() { - err := eventBroadcaster.Notify("bar", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("fooo", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("fo", "123") - require.NoError(t, err) - }() - - ch := sub.Events() - gomega.NewWithT(t).Consistently(ch).ShouldNot(gomega.Receive()) - }) - - t.Run("doesn't broadcast unrelated events (with payload filter)", func(t *testing.T) { - sub, err := eventBroadcaster.Subscribe("foo", "123") - require.NoError(t, err) - defer sub.Close() - - go func() { - err := eventBroadcaster.Notify("foo", "asdf") - require.NoError(t, err) - err = eventBroadcaster.Notify("bar", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("fooo", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("fo", "123") - require.NoError(t, err) - }() - - ch := sub.Events() - gomega.NewWithT(t).Consistently(ch).ShouldNot(gomega.Receive()) - }) - - t.Run("does broadcast related events (no payload filter)", func(t *testing.T) { - sub, err := eventBroadcaster.Subscribe("foo", "") - require.NoError(t, err) - defer sub.Close() - - go func() { - err := eventBroadcaster.Notify("foo", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "aslkdjslkdfj") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "true") - require.NoError(t, err) - }() - - ch := sub.Events() - gomega.NewWithT(t).Eventually(ch).Should(gomega.Receive()) - gomega.NewWithT(t).Eventually(ch).Should(gomega.Receive()) - gomega.NewWithT(t).Eventually(ch).Should(gomega.Receive()) - }) - - t.Run("does broadcast related events (with payload filter)", func(t *testing.T) { - sub, err := eventBroadcaster.Subscribe("foo", "123") - require.NoError(t, err) - defer sub.Close() - - go func() { - err := eventBroadcaster.Notify("foo", "asdf") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "true") - require.NoError(t, err) - }() - - ch := sub.Events() - gomega.NewWithT(t).Eventually(ch).Should(gomega.Receive()) - gomega.NewWithT(t).Eventually(ch).Should(gomega.Receive()) - gomega.NewWithT(t).Consistently(ch).ShouldNot(gomega.Receive()) - }) - - t.Run("broadcasts to the correct subscribers", func(t *testing.T) { - sub1, err := eventBroadcaster.Subscribe("foo", "") - require.NoError(t, err) - defer sub1.Close() - - sub2, err := eventBroadcaster.Subscribe("foo", "123") - require.NoError(t, err) - defer sub2.Close() - - sub3, err := eventBroadcaster.Subscribe("bar", "") - require.NoError(t, err) - defer sub3.Close() - - sub4, err := eventBroadcaster.Subscribe("bar", "asdf") - require.NoError(t, err) - defer sub4.Close() - - var wg sync.WaitGroup - wg.Add(5) - - recv := func(ch <-chan pg.Event) pg.Event { - select { - case e := <-ch: - return e - case <-time.After(5 * time.Second): - t.Fatal("did not receive") - } - return pg.Event{} - } - - go func() { - defer wg.Done() - err := eventBroadcaster.Notify("foo", "asdf") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("foo", "true") - require.NoError(t, err) - - err = eventBroadcaster.Notify("bar", "asdf") - require.NoError(t, err) - err = eventBroadcaster.Notify("bar", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("bar", "123") - require.NoError(t, err) - err = eventBroadcaster.Notify("bar", "true") - require.NoError(t, err) - }() - - go func() { - defer wg.Done() - e := recv(sub1.Events()) - require.Equal(t, "foo", e.Channel) - require.Equal(t, "asdf", e.Payload) - - e = recv(sub1.Events()) - require.Equal(t, "foo", e.Channel) - require.Equal(t, "123", e.Payload) - - e = recv(sub1.Events()) - require.Equal(t, "foo", e.Channel) - require.Equal(t, "123", e.Payload) - - e = recv(sub1.Events()) - require.Equal(t, "foo", e.Channel) - require.Equal(t, "true", e.Payload) - - gomega.NewWithT(t).Consistently(sub1.Events()).ShouldNot(gomega.Receive()) - }() - - go func() { - defer wg.Done() - e := recv(sub2.Events()) - require.Equal(t, "foo", e.Channel) - require.Equal(t, "123", e.Payload) - - e = recv(sub2.Events()) - require.Equal(t, "foo", e.Channel) - require.Equal(t, "123", e.Payload) - - gomega.NewWithT(t).Consistently(sub2.Events()).ShouldNot(gomega.Receive()) - }() - - go func() { - defer wg.Done() - e := recv(sub3.Events()) - require.Equal(t, "bar", e.Channel) - require.Equal(t, "asdf", e.Payload) - - e = recv(sub3.Events()) - require.Equal(t, "bar", e.Channel) - require.Equal(t, "123", e.Payload) - - e = recv(sub3.Events()) - require.Equal(t, "bar", e.Channel) - require.Equal(t, "123", e.Payload) - - e = recv(sub3.Events()) - require.Equal(t, "bar", e.Channel) - require.Equal(t, "true", e.Payload) - - gomega.NewWithT(t).Consistently(sub3.Events()).ShouldNot(gomega.Receive()) - }() - - go func() { - defer wg.Done() - e := recv(sub4.Events()) - require.Equal(t, "bar", e.Channel) - require.Equal(t, "asdf", e.Payload) - - gomega.NewWithT(t).Consistently(sub4.Events()).ShouldNot(gomega.Receive()) - }() - - wg.Wait() - }) - - t.Run("closes events channel on subscription close", func(t *testing.T) { - sub, err := eventBroadcaster.Subscribe("foo", "") - require.NoError(t, err) - - chEvents := sub.Events() - - sub.Close() - - select { - case _, ok := <-chEvents: - if ok { - t.Fatal("expected chEvents to be closed") - } - default: - t.Fatal("expected chEvents to not block") - } - }) -} diff --git a/core/services/pg/lease_lock.go b/core/services/pg/lease_lock.go index e21cec44bda..58ec2781245 100644 --- a/core/services/pg/lease_lock.go +++ b/core/services/pg/lease_lock.go @@ -12,8 +12,8 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // LeaseLock handles taking an exclusive lease on database access. This is not diff --git a/core/services/pg/mocks/event_broadcaster.go b/core/services/pg/mocks/event_broadcaster.go deleted file mode 100644 index 63f06db494b..00000000000 --- a/core/services/pg/mocks/event_broadcaster.go +++ /dev/null @@ -1,169 +0,0 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" - mock "github.com/stretchr/testify/mock" -) - -// EventBroadcaster is an autogenerated mock type for the EventBroadcaster type -type EventBroadcaster struct { - mock.Mock -} - -// Close provides a mock function with given fields: -func (_m *EventBroadcaster) Close() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Close") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// HealthReport provides a mock function with given fields: -func (_m *EventBroadcaster) HealthReport() map[string]error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HealthReport") - } - - var r0 map[string]error - if rf, ok := ret.Get(0).(func() map[string]error); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]error) - } - } - - return r0 -} - -// Name provides a mock function with given fields: -func (_m *EventBroadcaster) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// Notify provides a mock function with given fields: channel, payload -func (_m *EventBroadcaster) Notify(channel string, payload string) error { - ret := _m.Called(channel, payload) - - if len(ret) == 0 { - panic("no return value specified for Notify") - } - - var r0 error - if rf, ok := ret.Get(0).(func(string, string) error); ok { - r0 = rf(channel, payload) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Ready provides a mock function with given fields: -func (_m *EventBroadcaster) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Start provides a mock function with given fields: _a0 -func (_m *EventBroadcaster) Start(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for Start") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Subscribe provides a mock function with given fields: channel, payloadFilter -func (_m *EventBroadcaster) Subscribe(channel string, payloadFilter string) (pg.Subscription, error) { - ret := _m.Called(channel, payloadFilter) - - if len(ret) == 0 { - panic("no return value specified for Subscribe") - } - - var r0 pg.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(string, string) (pg.Subscription, error)); ok { - return rf(channel, payloadFilter) - } - if rf, ok := ret.Get(0).(func(string, string) pg.Subscription); ok { - r0 = rf(channel, payloadFilter) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(pg.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(channel, payloadFilter) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewEventBroadcaster creates a new instance of EventBroadcaster. 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 NewEventBroadcaster(t interface { - mock.TestingT - Cleanup(func()) -}) *EventBroadcaster { - mock := &EventBroadcaster{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/services/pg/mocks/subscription.go b/core/services/pg/mocks/subscription.go deleted file mode 100644 index fcd194004de..00000000000 --- a/core/services/pg/mocks/subscription.go +++ /dev/null @@ -1,93 +0,0 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. - -package mocks - -import ( - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" - mock "github.com/stretchr/testify/mock" -) - -// Subscription is an autogenerated mock type for the Subscription type -type Subscription struct { - mock.Mock -} - -// ChannelName provides a mock function with given fields: -func (_m *Subscription) ChannelName() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ChannelName") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// Close provides a mock function with given fields: -func (_m *Subscription) Close() { - _m.Called() -} - -// Events provides a mock function with given fields: -func (_m *Subscription) Events() <-chan pg.Event { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Events") - } - - var r0 <-chan pg.Event - if rf, ok := ret.Get(0).(func() <-chan pg.Event); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan pg.Event) - } - } - - return r0 -} - -// InterestedIn provides a mock function with given fields: event -func (_m *Subscription) InterestedIn(event pg.Event) bool { - ret := _m.Called(event) - - if len(ret) == 0 { - panic("no return value specified for InterestedIn") - } - - var r0 bool - if rf, ok := ret.Get(0).(func(pg.Event) bool); ok { - r0 = rf(event) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Send provides a mock function with given fields: event -func (_m *Subscription) Send(event pg.Event) { - _m.Called(event) -} - -// NewSubscription creates a new instance of Subscription. 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 NewSubscription(t interface { - mock.TestingT - Cleanup(func()) -}) *Subscription { - mock := &Subscription{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/services/pipeline/common.go b/core/services/pipeline/common.go index 8cc54d540fb..0e72bed4226 100644 --- a/core/services/pipeline/common.go +++ b/core/services/pipeline/common.go @@ -20,6 +20,7 @@ import ( pkgerrors "github.com/pkg/errors" "gopkg.in/guregu/null.v4" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/logger" cnull "github.com/smartcontractkit/chainlink/v2/core/null" @@ -409,7 +410,7 @@ var ( ) func UnmarshalTaskFromMap(taskType TaskType, taskMap interface{}, ID int, dotID string) (_ Task, err error) { - defer utils.WrapIfError(&err, "UnmarshalTaskFromMap") + defer cutils.WrapIfError(&err, "UnmarshalTaskFromMap") switch taskMap.(type) { default: diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index 92a6c25da39..638977863d6 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -12,6 +12,7 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -25,7 +26,6 @@ import ( "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" ) type ormconfig struct { @@ -348,7 +348,7 @@ func Test_PipelineORM_StoreRun_UpdateTaskRunResult(t *testing.T) { ds1_id := uuid.New() now := time.Now() - address, err := utils.TryParseHex("0x8bd112d3f8f92e41c861939545ad387307af9703") + address, err := hex.DecodeString("0x8bd112d3f8f92e41c861939545ad387307af9703") require.NoError(t, err) cborOutput := map[string]interface{}{ "blockNum": "0x13babbd", diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index 768f163f9b1..3e5d77db5f2 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -15,6 +15,8 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/services" + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -60,7 +62,7 @@ type runner struct { legacyEVMChains legacyevm.LegacyChainContainer ethKeyStore ETHKeyStore vrfKeyStore VRFKeyStore - runReaperWorker utils.SleeperTask + runReaperWorker *commonutils.SleeperTask lggr logger.Logger httpClient *http.Client unrestrictedHTTPClient *http.Client @@ -118,8 +120,8 @@ func NewRunner(orm ORM, btORM bridges.ORM, cfg Config, bridgeCfg BridgeConfig, l httpClient: httpClient, unrestrictedHTTPClient: unrestrictedHTTPClient, } - r.runReaperWorker = utils.NewSleeperTask( - utils.SleeperFuncTask(r.runReaper, "PipelineRunnerReaper"), + r.runReaperWorker = commonutils.NewSleeperTask( + commonutils.SleeperFuncTask(r.runReaper, "PipelineRunnerReaper"), ) return r } @@ -211,18 +213,39 @@ func (r *runner) OnRunFinished(fn func(*Run)) { r.runFinished = fn } -// Be careful with the ctx passed in here: it applies to requests in individual -// tasks but should _not_ apply to the scheduler or run itself +// github.com/smartcontractkit/libocr/offchainreporting2plus/internal/protocol.ReportingPluginTimeoutWarningGracePeriod +var overtime = 100 * time.Millisecond + +func init() { + // undocumented escape hatch + if v := env.PipelineOvertime.Get(); v != "" { + d, err := time.ParseDuration(v) + if err == nil { + overtime = d + } + } +} + func (r *runner) ExecuteRun( ctx context.Context, spec Spec, vars Vars, l logger.Logger, ) (*Run, TaskRunResults, error) { + // Pipeline runs may return results after the context is cancelled, so we modify the + // deadline to give them time to return before the parent context deadline. + var cancel func() + ctx, cancel = commonutils.ContextWithDeadlineFn(ctx, func(orig time.Time) time.Time { + if tenPct := time.Until(orig) / 10; overtime > tenPct { + return orig.Add(-tenPct) + } + return orig.Add(-overtime) + }) + defer cancel() + run := NewRun(spec, vars) pipeline, err := r.initializePipeline(run) - if err != nil { return run, nil, err } diff --git a/core/services/pipeline/task.estimategas.go b/core/services/pipeline/task.estimategas.go index 1c0159819b4..43c148b287f 100644 --- a/core/services/pipeline/task.estimategas.go +++ b/core/services/pipeline/task.estimategas.go @@ -12,9 +12,9 @@ import ( "github.com/shopspring/decimal" "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Return types: diff --git a/core/services/pipeline/task.eth_abi_decode_log_test.go b/core/services/pipeline/task.eth_abi_decode_log_test.go index f8958f3517e..62cd005a047 100644 --- a/core/services/pipeline/task.eth_abi_decode_log_test.go +++ b/core/services/pipeline/task.eth_abi_decode_log_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestETHABIDecodeLogTask(t *testing.T) { diff --git a/core/services/pipeline/task.eth_abi_decode_test.go b/core/services/pipeline/task.eth_abi_decode_test.go index b0f03402278..3c7f5b4776b 100644 --- a/core/services/pipeline/task.eth_abi_decode_test.go +++ b/core/services/pipeline/task.eth_abi_decode_test.go @@ -10,9 +10,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var testsABIDecode = []struct { diff --git a/core/services/pipeline/task.eth_call.go b/core/services/pipeline/task.eth_call.go index 3862ea10301..56b2df08c4e 100644 --- a/core/services/pipeline/task.eth_call.go +++ b/core/services/pipeline/task.eth_call.go @@ -13,9 +13,9 @@ import ( "go.uber.org/multierr" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Return types: diff --git a/core/services/pipeline/task.eth_tx.go b/core/services/pipeline/task.eth_tx.go index 58e9f6f2c15..1687c974140 100644 --- a/core/services/pipeline/task.eth_tx.go +++ b/core/services/pipeline/task.eth_tx.go @@ -13,12 +13,12 @@ import ( "go.uber.org/multierr" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" 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" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Return types: @@ -189,7 +189,7 @@ func decodeMeta(metaMap MapParam) (*txmgr.TxMeta, error) { i, err2 := strconv.ParseInt(data.(string), 10, 32) return int32(i), err2 case reflect.TypeOf(common.Hash{}): - hb, err := utils.TryParseHex(data.(string)) + hb, err := hex.DecodeString(data.(string)) if err != nil { return nil, err } @@ -220,7 +220,7 @@ func decodeTransmitChecker(checkerMap MapParam) (txmgr.TransmitCheckerSpec, erro case stringType: switch to { case reflect.TypeOf(common.Address{}): - ab, err := utils.TryParseHex(data.(string)) + ab, err := hex.DecodeString(data.(string)) if err != nil { return nil, err } diff --git a/core/services/pipeline/task.hexdecode.go b/core/services/pipeline/task.hexdecode.go index 7feca555111..893130bcf2c 100644 --- a/core/services/pipeline/task.hexdecode.go +++ b/core/services/pipeline/task.hexdecode.go @@ -7,8 +7,8 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" + commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Return types: @@ -40,8 +40,8 @@ func (t *HexDecodeTask) Run(_ context.Context, _ logger.Logger, vars Vars, input return Result{Error: err}, runInfo } - if utils.HasHexPrefix(input.String()) { - noHexPrefix := utils.RemoveHexPrefix(input.String()) + if commonhex.HasPrefix(input.String()) { + noHexPrefix := commonhex.TrimPrefix(input.String()) bs, err := hex.DecodeString(noHexPrefix) if err == nil { return Result{Value: bs}, runInfo diff --git a/core/services/pipeline/task.vrfv2.go b/core/services/pipeline/task.vrfv2.go index a871e543496..2c2c85eaedf 100644 --- a/core/services/pipeline/task.vrfv2.go +++ b/core/services/pipeline/task.vrfv2.go @@ -39,7 +39,7 @@ func (t *VRFTaskV2) Type() TaskType { return TaskTypeVRFV2 } -func (t *VRFTaskV2) Run(_ context.Context, _ logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { +func (t *VRFTaskV2) Run(_ context.Context, lggr logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { if len(inputs) != 1 { return Result{Error: ErrWrongInputCardinality}, runInfo } @@ -134,7 +134,8 @@ func (t *VRFTaskV2) Run(_ context.Context, _ logger.Logger, vars Vars, inputs [] return Result{Error: err}, runInfo } results := make(map[string]interface{}) - results["output"] = hexutil.Encode(b) + output := hexutil.Encode(b) + results["output"] = output // RequestID needs to be a [32]byte for EvmTxMeta. results["requestID"] = hexutil.Encode(requestId.Bytes()) @@ -142,5 +143,7 @@ func (t *VRFTaskV2) Run(_ context.Context, _ logger.Logger, vars Vars, inputs [] results["proof"] = onChainProof results["requestCommitment"] = rc + lggr.Debugw("Completed VRF V2 task run", "reqID", requestId.String(), "output", output) + return Result{Value: results}, runInfo } diff --git a/core/services/pipeline/task.vrfv2plus.go b/core/services/pipeline/task.vrfv2plus.go index a596bfa3092..c029af68cbe 100644 --- a/core/services/pipeline/task.vrfv2plus.go +++ b/core/services/pipeline/task.vrfv2plus.go @@ -42,7 +42,7 @@ func (t *VRFTaskV2Plus) Type() TaskType { return TaskTypeVRFV2Plus } -func (t *VRFTaskV2Plus) Run(_ context.Context, _ logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { +func (t *VRFTaskV2Plus) Run(_ context.Context, lggr logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { if len(inputs) != 1 { return Result{Error: ErrWrongInputCardinality}, runInfo } @@ -142,7 +142,8 @@ func (t *VRFTaskV2Plus) Run(_ context.Context, _ logger.Logger, vars Vars, input return Result{Error: err}, runInfo } results := make(map[string]interface{}) - results["output"] = hexutil.Encode(b) + output := hexutil.Encode(b) + results["output"] = output // RequestID needs to be a [32]byte for EvmTxMeta. results["requestID"] = hexutil.Encode(requestId.Bytes()) @@ -150,5 +151,7 @@ func (t *VRFTaskV2Plus) Run(_ context.Context, _ logger.Logger, vars Vars, input results["proof"] = onChainProof results["requestCommitment"] = rc + lggr.Debugw("Completed VRF V2 task run", "reqID", requestId.String(), "output", output) + return Result{Value: results}, runInfo } diff --git a/core/services/pipeline/task_params.go b/core/services/pipeline/task_params.go index dc020c30715..261728fbe9e 100644 --- a/core/services/pipeline/task_params.go +++ b/core/services/pipeline/task_params.go @@ -13,6 +13,7 @@ import ( "github.com/pkg/errors" "github.com/shopspring/decimal" + commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -122,8 +123,8 @@ func (b *BytesParam) UnmarshalPipelineParam(val interface{}) error { switch v := val.(type) { case string: // first check if this is a valid hex-encoded string - if utils.HasHexPrefix(v) { - noHexPrefix := utils.RemoveHexPrefix(v) + if commonhex.HasPrefix(v) { + noHexPrefix := commonhex.TrimPrefix(v) bs, err := hex.DecodeString(noHexPrefix) if err == nil { *b = bs @@ -452,7 +453,7 @@ func (a *AddressParam) UnmarshalPipelineParam(val interface{}) error { case []byte: switch len(v) { case 42: - bs, err := utils.TryParseHex(string(v)) + bs, err := commonhex.DecodeString(string(v)) if err == nil { *a = AddressParam(common.BytesToAddress(bs)) return nil diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index 7b9930e4daa..60d6d9388fa 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -26,7 +26,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/promreporter" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func newHead() evmtypes.Head { @@ -113,7 +112,7 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) - require.NoError(t, utils.JustError(db.Exec(`UPDATE evm.tx_attempts SET broadcast_before_block_num = 7 WHERE eth_tx_id = $1`, etx.ID))) + require.NoError(t, txStore.UpdateTxAttemptBroadcastBeforeBlockNum(testutils.Context(t), etx.ID, 7)) head := newHead() reporter.OnNewLongestChain(testutils.Context(t), &head) diff --git a/core/services/relay/evm/config_poller_test.go b/core/services/relay/evm/config_poller_test.go index 3409c2f1591..79533a06f01 100644 --- a/core/services/relay/evm/config_poller_test.go +++ b/core/services/relay/evm/config_poller_test.go @@ -33,6 +33,7 @@ import ( evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -326,12 +327,12 @@ func setConfig(t *testing.T, pluginConfig median.OffchainConfig, ocrContract *oc for i := 0; i < 4; i++ { oracles = append(oracles, confighelper2.OracleIdentityExtra{ OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: utils.RandomAddress().Bytes(), - TransmitAccount: ocrtypes2.Account(utils.RandomAddress().Hex()), - OffchainPublicKey: utils.RandomBytes32(), + OnchainPublicKey: evmutils.RandomAddress().Bytes(), + TransmitAccount: ocrtypes2.Account(evmutils.RandomAddress().Hex()), + OffchainPublicKey: evmutils.RandomBytes32(), PeerID: utils.MustNewPeerID(), }, - ConfigEncryptionPublicKey: utils.RandomBytes32(), + ConfigEncryptionPublicKey: evmutils.RandomBytes32(), }) } // Gnerate OnchainConfig diff --git a/core/services/relay/evm/contract_transmitter.go b/core/services/relay/evm/contract_transmitter.go index 470b5bae076..76360e34e1a 100644 --- a/core/services/relay/evm/contract_transmitter.go +++ b/core/services/relay/evm/contract_transmitter.go @@ -16,10 +16,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ContractTransmitter interface { diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 303cdd3ba0e..d6a8c584fab 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -12,7 +12,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/jmoiron/sqlx" pkgerrors "github.com/pkg/errors" - "go.uber.org/multierr" "golang.org/x/exp/maps" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" @@ -46,14 +45,13 @@ import ( var _ commontypes.Relayer = &Relayer{} //nolint:staticcheck type Relayer struct { - db *sqlx.DB - chain legacyevm.Chain - lggr logger.Logger - ks CSAETHKeystore - mercuryPool wsrpc.Pool - eventBroadcaster pg.EventBroadcaster - pgCfg pg.QConfig - chainReader commontypes.ChainReader + db *sqlx.DB + chain legacyevm.Chain + lggr logger.Logger + ks CSAETHKeystore + mercuryPool wsrpc.Pool + pgCfg pg.QConfig + chainReader commontypes.ChainReader } type CSAETHKeystore interface { @@ -65,7 +63,6 @@ type RelayerOpts struct { *sqlx.DB pg.QConfig CSAETHKeystore - pg.EventBroadcaster MercuryPool wsrpc.Pool } @@ -80,9 +77,6 @@ func (c RelayerOpts) Validate() error { if c.CSAETHKeystore == nil { err = errors.Join(err, errors.New("nil Keystore")) } - if c.EventBroadcaster == nil { - err = errors.Join(err, errors.New("nil Eventbroadcaster")) - } if err != nil { err = fmt.Errorf("invalid RelayerOpts: %w", err) @@ -97,13 +91,12 @@ func NewRelayer(lggr logger.Logger, chain legacyevm.Chain, opts RelayerOpts) (*R } lggr = lggr.Named("Relayer") return &Relayer{ - db: opts.DB, - chain: chain, - lggr: lggr, - ks: opts.CSAETHKeystore, - mercuryPool: opts.MercuryPool, - eventBroadcaster: opts.EventBroadcaster, - pgCfg: opts.QConfig, + db: opts.DB, + chain: chain, + lggr: lggr, + ks: opts.CSAETHKeystore, + mercuryPool: opts.MercuryPool, + pgCfg: opts.QConfig, }, nil } @@ -152,7 +145,7 @@ func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commonty if relayConfig.ChainID.String() != r.chain.ID().String() { return nil, fmt.Errorf("internal error: chain id in spec does not match this relayer's chain: have %s expected %s", relayConfig.ChainID.String(), r.chain.ID().String()) } - cw, err := newConfigProvider(lggr, r.chain, relayOpts, r.eventBroadcaster) + cw, err := newConfigProvider(lggr, r.chain, relayOpts) if err != nil { return nil, pkgerrors.WithStack(err) } @@ -211,7 +204,7 @@ func (r *Relayer) NewConfigProvider(args commontypes.RelayArgs) (commontypes.Con return nil, fmt.Errorf("internal error: chain id in spec does not match this relayer's chain: have %s expected %s", relayConfig.ChainID.String(), r.chain.ID().String()) } - configProvider, err := newConfigProvider(lggr, r.chain, relayOpts, r.eventBroadcaster) + configProvider, err := newConfigProvider(lggr, r.chain, relayOpts) if err != nil { // Never return (*configProvider)(nil) return nil, err @@ -321,7 +314,7 @@ func (c *configWatcher) ContractConfigTracker() ocrtypes.ContractConfigTracker { return c.configPoller } -func newConfigProvider(lggr logger.Logger, chain legacyevm.Chain, opts *types.RelayOpts, eventBroadcaster pg.EventBroadcaster) (*configWatcher, error) { +func newConfigProvider(lggr logger.Logger, chain legacyevm.Chain, opts *types.RelayOpts) (*configWatcher, error) { if !common.IsHexAddress(opts.ContractID) { return nil, pkgerrors.Errorf("invalid contractID, expected hex address") } @@ -343,7 +336,6 @@ func newConfigProvider(lggr logger.Logger, chain legacyevm.Chain, opts *types.Re chain.LogPoller(), aggregatorAddress, *relayConfig.FeedID, - eventBroadcaster, // TODO: Does mercury need to support config contract? DF-19182 ) } else { @@ -466,7 +458,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp } contractID := common.HexToAddress(relayOpts.ContractID) - configWatcher, err := newConfigProvider(lggr, r.chain, relayOpts, r.eventBroadcaster) + configWatcher, err := newConfigProvider(lggr, r.chain, relayOpts) if err != nil { return nil, err } @@ -483,6 +475,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp } medianProvider := medianProvider{ + lggr: lggr.Named("MedianProvider"), configWatcher: configWatcher, reportCodec: reportCodec, contractTransmitter: contractTransmitter, @@ -503,9 +496,17 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp return &medianProvider, nil } +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()) + + return ocr2keeperRelayer.NewOCR2KeeperProvider(rargs, pargs) +} + var _ commontypes.MedianProvider = (*medianProvider)(nil) type medianProvider struct { + lggr logger.Logger configWatcher *configWatcher contractTransmitter ContractTransmitter reportCodec median.ReportCodec @@ -514,26 +515,22 @@ type medianProvider struct { ms services.MultiStart } -func (p *medianProvider) Name() string { - return "EVM.MedianProvider" -} +func (p *medianProvider) Name() string { return p.lggr.Name() } func (p *medianProvider) Start(ctx context.Context) error { - return p.ms.Start(ctx, p.configWatcher, p.contractTransmitter) + return p.ms.Start(ctx, p.configWatcher, p.contractTransmitter, p.medianContract) } -func (p *medianProvider) Close() error { - return p.ms.Close() -} +func (p *medianProvider) Close() error { return p.ms.Close() } -func (p *medianProvider) Ready() error { - return multierr.Combine(p.configWatcher.Ready(), p.contractTransmitter.Ready()) -} +func (p *medianProvider) Ready() error { return nil } func (p *medianProvider) HealthReport() map[string]error { - report := p.configWatcher.HealthReport() - services.CopyHealth(report, p.contractTransmitter.HealthReport()) - return report + hp := map[string]error{p.Name(): p.Ready()} + services.CopyHealth(hp, p.configWatcher.HealthReport()) + services.CopyHealth(hp, p.contractTransmitter.HealthReport()) + services.CopyHealth(hp, p.medianContract.HealthReport()) + return hp } func (p *medianProvider) ContractTransmitter() ocrtypes.ContractTransmitter { diff --git a/core/services/relay/evm/evm_test.go b/core/services/relay/evm/evm_test.go index 8f49128ff2d..41e51a7ab8f 100644 --- a/core/services/relay/evm/evm_test.go +++ b/core/services/relay/evm/evm_test.go @@ -15,10 +15,9 @@ import ( func TestRelayerOpts_Validate(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) type fields struct { - DB *sqlx.DB - QConfig pg.QConfig - CSAETHKeystore evm.CSAETHKeystore - EventBroadcaster pg.EventBroadcaster + DB *sqlx.DB + QConfig pg.QConfig + CSAETHKeystore evm.CSAETHKeystore } tests := []struct { name string @@ -28,23 +27,19 @@ func TestRelayerOpts_Validate(t *testing.T) { { name: "all invalid", fields: fields{ - DB: nil, - QConfig: nil, - CSAETHKeystore: nil, - EventBroadcaster: nil, + DB: nil, + QConfig: nil, + CSAETHKeystore: nil, }, wantErrContains: `nil DB nil QConfig -nil Keystore -nil Eventbroadcaster`, +nil Keystore`, }, { name: "missing db, keystore", fields: fields{ - DB: nil, - QConfig: cfg.Database(), - CSAETHKeystore: nil, - EventBroadcaster: pg.NewNullEventBroadcaster(), + DB: nil, + QConfig: cfg.Database(), }, wantErrContains: `nil DB nil Keystore`, @@ -53,10 +48,9 @@ nil Keystore`, for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := evm.RelayerOpts{ - DB: tt.fields.DB, - QConfig: tt.fields.QConfig, - CSAETHKeystore: tt.fields.CSAETHKeystore, - EventBroadcaster: tt.fields.EventBroadcaster, + DB: tt.fields.DB, + QConfig: tt.fields.QConfig, + CSAETHKeystore: tt.fields.CSAETHKeystore, } err := c.Validate() if tt.wantErrContains != "" { diff --git a/core/services/relay/evm/functions/config_poller_test.go b/core/services/relay/evm/functions/config_poller_test.go index a5e5c1f8058..2cf373d2e86 100644 --- a/core/services/relay/evm/functions/config_poller_test.go +++ b/core/services/relay/evm/functions/config_poller_test.go @@ -24,6 +24,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -158,12 +159,12 @@ func setFunctionsConfig(t *testing.T, pluginConfig *functionsConfig.ReportingPlu for i := 0; i < 4; i++ { oracles = append(oracles, confighelper2.OracleIdentityExtra{ OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: utils.RandomAddress().Bytes(), - TransmitAccount: ocrtypes2.Account(utils.RandomAddress().String()), - OffchainPublicKey: utils.RandomBytes32(), + OnchainPublicKey: evmutils.RandomAddress().Bytes(), + TransmitAccount: ocrtypes2.Account(evmutils.RandomAddress().String()), + OffchainPublicKey: evmutils.RandomBytes32(), PeerID: utils.MustNewPeerID(), }, - ConfigEncryptionPublicKey: utils.RandomBytes32(), + ConfigEncryptionPublicKey: evmutils.RandomBytes32(), }) } diff --git a/core/services/relay/evm/functions/contract_transmitter.go b/core/services/relay/evm/functions/contract_transmitter.go index 17baab4525c..2a62db31a8c 100644 --- a/core/services/relay/evm/functions/contract_transmitter.go +++ b/core/services/relay/evm/functions/contract_transmitter.go @@ -18,12 +18,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/pg" evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type FunctionsContractTransmitter interface { diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go index e7f3a1a96af..e76b567b42b 100644 --- a/core/services/relay/evm/functions/logpoller_wrapper.go +++ b/core/services/relay/evm/functions/logpoller_wrapper.go @@ -108,7 +108,7 @@ func NewLogPollerWrapper(routerContractAddress common.Address, pluginConfig conf client: client, subscribers: make(map[string]evmRelayTypes.RouteUpdateSubscriber), stopCh: make(services.StopChan), - lggr: lggr, + lggr: lggr.Named("LogPollerWrapper"), }, nil } @@ -136,16 +136,10 @@ func (l *logPollerWrapper) Close() error { } func (l *logPollerWrapper) HealthReport() map[string]error { - return make(map[string]error) + return map[string]error{l.Name(): l.Ready()} } -func (l *logPollerWrapper) Name() string { - return "LogPollerWrapper" -} - -func (l *logPollerWrapper) Ready() error { - return nil -} +func (l *logPollerWrapper) Name() string { return l.lggr.Name() } // methods of LogPollerWrapper func (l *logPollerWrapper) LatestEvents() ([]evmRelayTypes.OracleRequest, []evmRelayTypes.OracleResponse, error) { diff --git a/core/services/relay/evm/median.go b/core/services/relay/evm/median.go index db521a97208..e3200d8e867 100644 --- a/core/services/relay/evm/median.go +++ b/core/services/relay/evm/median.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" offchain_aggregator_wrapper "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -22,12 +23,15 @@ import ( var _ median.MedianContract = &medianContract{} type medianContract struct { + services.StateMachine + lggr logger.Logger configTracker types.ContractConfigTracker contractCaller *ocr2aggregator.OCR2AggregatorCaller requestRoundTracker *RequestRoundTracker } func newMedianContract(configTracker types.ContractConfigTracker, contractAddress common.Address, chain legacyevm.Chain, specID int32, db *sqlx.DB, lggr logger.Logger) (*medianContract, error) { + lggr = lggr.Named("MedianContract") contract, err := offchain_aggregator_wrapper.NewOffchainAggregator(contractAddress, chain.Client()) if err != nil { return nil, errors.Wrap(err, "could not instantiate NewOffchainAggregator") @@ -44,6 +48,7 @@ func newMedianContract(configTracker types.ContractConfigTracker, contractAddres } return &medianContract{ + lggr: lggr, configTracker: configTracker, contractCaller: contractCaller, requestRoundTracker: NewRequestRoundTracker( @@ -60,13 +65,22 @@ func newMedianContract(configTracker types.ContractConfigTracker, contractAddres ), }, nil } - -func (oc *medianContract) Start() error { - return oc.requestRoundTracker.Start() +func (oc *medianContract) Start(context.Context) error { + return oc.StartOnce("MedianContract", func() error { + return oc.requestRoundTracker.Start() + }) } func (oc *medianContract) Close() error { - return oc.requestRoundTracker.Close() + return oc.StopOnce("MedianContract", func() error { + return oc.requestRoundTracker.Close() + }) +} + +func (oc *medianContract) Name() string { return oc.lggr.Name() } + +func (oc *medianContract) HealthReport() map[string]error { + return map[string]error{oc.Name(): oc.Ready()} } func (oc *medianContract) LatestTransmissionDetails(ctx context.Context) (ocrtypes.ConfigDigest, uint32, uint8, *big.Int, time.Time, error) { diff --git a/core/services/relay/evm/mercury/config_poller.go b/core/services/relay/evm/mercury/config_poller.go index 8964a283049..98ef78020c7 100644 --- a/core/services/relay/evm/mercury/config_poller.go +++ b/core/services/relay/evm/mercury/config_poller.go @@ -91,8 +91,6 @@ type ConfigPoller struct { destChainLogPoller logpoller.LogPoller addr common.Address feedId common.Hash - notifyCh chan struct{} - subscription pg.Subscription } func FilterName(addr common.Address, feedID common.Hash) string { @@ -100,43 +98,30 @@ func FilterName(addr common.Address, feedID common.Hash) string { } // NewConfigPoller creates a new Mercury ConfigPoller -func NewConfigPoller(lggr logger.Logger, destChainPoller logpoller.LogPoller, addr common.Address, feedId common.Hash, eventBroadcaster pg.EventBroadcaster) (*ConfigPoller, error) { +func NewConfigPoller(lggr logger.Logger, destChainPoller logpoller.LogPoller, addr common.Address, feedId common.Hash) (*ConfigPoller, error) { err := destChainPoller.RegisterFilter(logpoller.Filter{Name: FilterName(addr, feedId), EventSigs: []common.Hash{FeedScopedConfigSet}, Addresses: []common.Address{addr}}) if err != nil { return nil, err } - subscription, err := eventBroadcaster.Subscribe(pg.ChannelInsertOnEVMLogs, "") - if err != nil { - return nil, err - } - cp := &ConfigPoller{ lggr: lggr, destChainLogPoller: destChainPoller, addr: addr, feedId: feedId, - notifyCh: make(chan struct{}, 1), - subscription: subscription, } return cp, nil } -// Start the subscription to Postgres' notify events. -func (cp *ConfigPoller) Start() { - go cp.startLogSubscription() -} +func (cp *ConfigPoller) Start() {} -// Close the subscription to Postgres' notify events. func (cp *ConfigPoller) Close() error { - cp.subscription.Close() return nil } -// Notify abstracts the logpoller.LogPoller Notify() implementation func (cp *ConfigPoller) Notify() <-chan struct{} { - return cp.notifyCh + return nil // rely on libocr's builtin config polling } // Replay abstracts the logpoller.LogPoller Replay() implementation @@ -190,42 +175,3 @@ func (cp *ConfigPoller) LatestBlockHeight(ctx context.Context) (blockHeight uint } return uint64(latest.BlockNumber), nil } - -func (cp *ConfigPoller) startLogSubscription() { - // trim the leading 0x to make it comparable to pg's hex encoding. - addressPgHex := cp.addr.Hex()[2:] - feedIdPgHex := cp.feedId.Hex()[2:] - - for { - event, ok := <-cp.subscription.Events() - if !ok { - cp.lggr.Debug("eventBroadcaster subscription closed, exiting notify loop") - return - } - - // Event payload should look like: "
:," - addressTopicValues := strings.Split(event.Payload, ":") - if len(addressTopicValues) < 2 { - cp.lggr.Warnf("invalid event from %s channel: %s", pg.ChannelInsertOnEVMLogs, event.Payload) - continue - } - - address := addressTopicValues[0] - if address != addressPgHex { - continue - } - - topicValues := strings.Split(addressTopicValues[1], ",") - if len(topicValues) <= feedIdTopicIndex { - continue - } - if topicValues[feedIdTopicIndex] != feedIdPgHex { - continue - } - - select { - case cp.notifyCh <- struct{}{}: - default: - } - } -} diff --git a/core/services/relay/evm/mercury/config_poller_test.go b/core/services/relay/evm/mercury/config_poller_test.go index 1b3ba72128d..f828938f954 100644 --- a/core/services/relay/evm/mercury/config_poller_test.go +++ b/core/services/relay/evm/mercury/config_poller_test.go @@ -6,7 +6,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/onsi/gomega" "github.com/pkg/errors" confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" @@ -16,17 +15,16 @@ import ( "github.com/stretchr/testify/require" "github.com/umbracle/ethgo/abi" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestMercuryConfigPoller(t *testing.T) { - feedID := utils.NewHash() + feedID := evmutils.NewHash() feedIDBytes := [32]byte(feedID) th := SetupTH(t, feedID) - th.subscription.On("Events").Return(nil) notify := th.configPoller.Notify() assert.Empty(t, notify) @@ -42,12 +40,12 @@ func TestMercuryConfigPoller(t *testing.T) { for i := 0; i < n; i++ { oracles = append(oracles, confighelper2.OracleIdentityExtra{ OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: utils.RandomAddress().Bytes(), - TransmitAccount: ocrtypes2.Account(utils.RandomAddress().String()), - OffchainPublicKey: utils.RandomBytes32(), + OnchainPublicKey: evmutils.RandomAddress().Bytes(), + TransmitAccount: ocrtypes2.Account(evmutils.RandomAddress().String()), + OffchainPublicKey: evmutils.RandomBytes32(), PeerID: utils.MustNewPeerID(), }, - ConfigEncryptionPublicKey: utils.RandomBytes32(), + ConfigEncryptionPublicKey: evmutils.RandomBytes32(), }) } f := uint8(1) @@ -114,54 +112,6 @@ func TestMercuryConfigPoller(t *testing.T) { assert.Equal(t, offchainConfig, newConfig.OffchainConfig) } -func TestNotify(t *testing.T) { - testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCF-2746") - feedIDStr := "8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1" - feedIDBytes, err := hexutil.Decode("0x" + feedIDStr) - require.NoError(t, err) - feedID := common.BytesToHash(feedIDBytes) - - eventCh := make(chan pg.Event) - - th := SetupTH(t, feedID) - th.subscription.On("Events").Return((<-chan pg.Event)(eventCh)) - - addressPgHex := th.verifierAddress.Hex()[2:] - - notify := th.configPoller.Notify() - assert.Empty(t, notify) - - eventCh <- pg.Event{} // Empty event - assert.Empty(t, notify) - - eventCh <- pg.Event{Payload: addressPgHex} // missing topic values - assert.Empty(t, notify) - - eventCh <- pg.Event{Payload: addressPgHex + ":val1"} // missing feedId topic value - assert.Empty(t, notify) - - eventCh <- pg.Event{Payload: addressPgHex + ":8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1,val2"} // wrong index - assert.Empty(t, notify) - - eventCh <- pg.Event{Payload: addressPgHex + ":val1,val2,8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1"} // wrong index - assert.Empty(t, notify) - - eventCh <- pg.Event{Payload: addressPgHex + ":val1,0x8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1"} // 0x prefix - assert.Empty(t, notify) - - eventCh <- pg.Event{Payload: "wrong_address:val1,8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1"} // wrong address - assert.Empty(t, notify) - - eventCh <- pg.Event{Payload: addressPgHex + ":val1,8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1"} // expected event to notify on - assert.Eventually(t, func() bool { <-notify; return true }, time.Second, 10*time.Millisecond) - - eventCh <- pg.Event{Payload: addressPgHex + ":val1,8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1"} // try second time - assert.Eventually(t, func() bool { <-notify; return true }, time.Second, 10*time.Millisecond) - - eventCh <- pg.Event{Payload: addressPgHex + ":val1,8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1:additional"} // additional colon separated parts - assert.Eventually(t, func() bool { <-notify; return true }, time.Second, 10*time.Millisecond) -} - func onchainPublicKeyToAddress(publicKeys []types.OnchainPublicKey) (addresses []common.Address, err error) { for _, signer := range publicKeys { if len(signer) != 20 { diff --git a/core/services/relay/evm/mercury/helpers_test.go b/core/services/relay/evm/mercury/helpers_test.go index 59e0e587813..f1686ee00c8 100644 --- a/core/services/relay/evm/mercury/helpers_test.go +++ b/core/services/relay/evm/mercury/helpers_test.go @@ -18,18 +18,18 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + evmclient "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/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - pgmocks "github.com/smartcontractkit/chainlink/v2/core/services/pg/mocks" reportcodecv1 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v1/reportcodec" reportcodecv2 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v2/reportcodec" reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -143,8 +143,6 @@ type TestHarness struct { verifierAddress common.Address verifierContract *verifier.Verifier logPoller logpoller.LogPoller - eventBroadcaster *pgmocks.EventBroadcaster - subscription *pgmocks.Subscription } func SetupTH(t *testing.T, feedID common.Hash) TestHarness { @@ -170,13 +168,9 @@ func SetupTH(t *testing.T, feedID common.Hash) TestHarness { lggr := logger.TestLogger(t) lorm := logpoller.NewORM(big.NewInt(1337), db, lggr, cfg) lp := logpoller.NewLogPoller(lorm, ethClient, lggr, 100*time.Millisecond, false, 1, 2, 2, 1000) - eventBroadcaster := pgmocks.NewEventBroadcaster(t) - subscription := pgmocks.NewSubscription(t) servicetest.Run(t, lp) - eventBroadcaster.On("Subscribe", "evm.insert_on_logs", "").Return(subscription, nil) - - configPoller, err := NewConfigPoller(lggr, lp, verifierAddress, feedID, eventBroadcaster) + configPoller, err := NewConfigPoller(lggr, lp, verifierAddress, feedID) require.NoError(t, err) configPoller.Start() @@ -188,7 +182,5 @@ func SetupTH(t *testing.T, feedID common.Hash) TestHarness { verifierAddress: verifierAddress, verifierContract: verifierContract, logPoller: lp, - eventBroadcaster: eventBroadcaster, - subscription: subscription, } } diff --git a/core/services/relay/evm/mercury/v1/data_source_test.go b/core/services/relay/evm/mercury/v1/data_source_test.go index ce0d71acc6f..e02efd8d9a4 100644 --- a/core/services/relay/evm/mercury/v1/data_source_test.go +++ b/core/services/relay/evm/mercury/v1/data_source_test.go @@ -21,6 +21,7 @@ import ( commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -30,7 +31,6 @@ import ( mercurymocks "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/mocks" mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" reportcodecv1 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v1/reportcodec" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var _ mercurytypes.ServerFetcher = &mockFetcher{} diff --git a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go index 2e50faf47d4..3e898d6c1da 100644 --- a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go +++ b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" v1 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) var hash = hexutil.MustDecode("0x552c2cea3ab43bae137d89ee6142a01db3ae2b5678bc3c9bd5f509f537bea57b") diff --git a/core/services/relay/evm/mercury/wsrpc/cache/cache_set.go b/core/services/relay/evm/mercury/wsrpc/cache/cache_set.go index 3171c8ab643..7101cec39f3 100644 --- a/core/services/relay/evm/mercury/wsrpc/cache/cache_set.go +++ b/core/services/relay/evm/mercury/wsrpc/cache/cache_set.go @@ -46,7 +46,7 @@ func newCacheSet(lggr logger.Logger, cfg Config) *cacheSet { func (cs *cacheSet) Start(context.Context) error { return cs.StartOnce("CacheSet", func() error { - cs.lggr.Debugw("CacheSet starting", "config", cs.cfg) + cs.lggr.Debugw("CacheSet starting", "config", cs.cfg, "cachingEnabled", cs.cfg.LatestReportTTL > 0) return nil }) } @@ -65,6 +65,10 @@ func (cs *cacheSet) Close() error { } func (cs *cacheSet) Get(ctx context.Context, client Client) (f Fetcher, err error) { + if cs.cfg.LatestReportTTL == 0 { + // caching disabled + return nil, nil + } ok := cs.IfStarted(func() { f, err = cs.get(ctx, client) }) @@ -104,8 +108,9 @@ func (cs *cacheSet) HealthReport() map[string]error { cs.Name(): cs.Ready(), } cs.RLock() - defer cs.RUnlock() - for _, c := range cs.caches { + caches := maps.Values(cs.caches) + cs.RUnlock() + for _, c := range caches { services.CopyHealth(report, c.HealthReport()) } return report diff --git a/core/services/relay/evm/mercury/wsrpc/cache/cache_set_test.go b/core/services/relay/evm/mercury/wsrpc/cache/cache_set_test.go index 7d754b8326e..f12dc8a9bc7 100644 --- a/core/services/relay/evm/mercury/wsrpc/cache/cache_set_test.go +++ b/core/services/relay/evm/mercury/wsrpc/cache/cache_set_test.go @@ -13,7 +13,8 @@ import ( func Test_CacheSet(t *testing.T) { lggr := logger.TestLogger(t) - cs := newCacheSet(lggr, Config{}) + cs := newCacheSet(lggr, Config{LatestReportTTL: 1}) + disabledCs := newCacheSet(lggr, Config{LatestReportTTL: 0}) ctx := testutils.Context(t) servicetest.Run(t, cs) @@ -22,6 +23,16 @@ func Test_CacheSet(t *testing.T) { var err error var f Fetcher + t.Run("with caching disabled, returns nil, nil", func(t *testing.T) { + assert.Len(t, disabledCs.caches, 0) + + f, err = disabledCs.Get(ctx, c) + require.NoError(t, err) + + assert.Nil(t, f) + assert.Len(t, disabledCs.caches, 0) + }) + t.Run("with virgin cacheset, makes new entry and returns it", func(t *testing.T) { assert.Len(t, cs.caches, 0) diff --git a/core/services/relay/evm/mercury/wsrpc/client.go b/core/services/relay/evm/mercury/wsrpc/client.go index 5b6bfa1a9b0..c9533717757 100644 --- a/core/services/relay/evm/mercury/wsrpc/client.go +++ b/core/services/relay/evm/mercury/wsrpc/client.go @@ -24,9 +24,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils" ) -// MaxConsecutiveTransmitFailures controls how many consecutive requests are +// MaxConsecutiveRequestFailures controls how many consecutive requests are // allowed to time out before we reset the connection -const MaxConsecutiveTransmitFailures = 5 +const MaxConsecutiveRequestFailures = 10 var ( timeoutCount = promauto.NewCounterVec(prometheus.CounterOpts{ @@ -55,7 +55,7 @@ var ( ) connectionResetCount = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "mercury_connection_reset_count", - Help: fmt.Sprintf("Running count of times connection to mercury server has been reset (connection reset happens automatically after %d consecutive transmit failures)", MaxConsecutiveTransmitFailures), + Help: fmt.Sprintf("Running count of times connection to mercury server has been reset (connection reset happens automatically after %d consecutive request failures)", MaxConsecutiveRequestFailures), }, []string{"serverURL"}, ) @@ -256,13 +256,26 @@ func (w *client) Transmit(ctx context.Context, req *pb.TransmitRequest) (resp *p return nil, errors.Wrap(err, "Transmit call failed") } resp, err = w.rawClient.Transmit(ctx, req) + w.handleTimeout(err) + if err != nil { + w.logger.Warnw("Transmit call failed due to networking error", "err", err, "resp", resp) + incRequestStatusMetric(statusFailed) + } else { + w.logger.Tracew("Transmit call succeeded", "resp", resp) + incRequestStatusMetric(statusSuccess) + setRequestLatencyMetric(float64(time.Since(start).Milliseconds())) + } + return +} + +func (w *client) handleTimeout(err error) { if errors.Is(err, context.DeadlineExceeded) { w.timeoutCountMetric.Inc() cnt := w.consecutiveTimeoutCnt.Add(1) - if cnt == MaxConsecutiveTransmitFailures { + if cnt == MaxConsecutiveRequestFailures { w.logger.Errorf("Timed out on %d consecutive transmits, resetting transport", cnt) - // NOTE: If we get 5+ request timeouts in a row, close and re-open - // the websocket connection. + // NOTE: If we get at least MaxConsecutiveRequestFailures request + // timeouts in a row, close and re-open the websocket connection. // // This *shouldn't* be necessary in theory (ideally, wsrpc would // handle it for us) but it acts as a "belts and braces" approach @@ -271,11 +284,11 @@ func (w *client) Transmit(ctx context.Context, req *pb.TransmitRequest) (resp *p select { case w.chResetTransport <- struct{}{}: default: - // This can happen if we had 5 consecutive timeouts, already - // sent a reset signal, then the connection started working - // again (resetting the count) then we got 5 additional - // failures before the runloop was able to close the bad - // connection. + // This can happen if we had MaxConsecutiveRequestFailures + // consecutive timeouts, already sent a reset signal, then the + // connection started working again (resetting the count) then + // we got MaxConsecutiveRequestFailures additional failures + // before the runloop was able to close the bad connection. // // It should be safe to just ignore in this case. // @@ -286,15 +299,6 @@ func (w *client) Transmit(ctx context.Context, req *pb.TransmitRequest) (resp *p } else { w.consecutiveTimeoutCnt.Store(0) } - if err != nil { - w.logger.Warnw("Transmit call failed due to networking error", "err", err, "resp", resp) - incRequestStatusMetric(statusFailed) - } else { - w.logger.Tracew("Transmit call succeeded", "resp", resp) - incRequestStatusMetric(statusSuccess) - setRequestLatencyMetric(float64(time.Since(start).Milliseconds())) - } - return } func (w *client) LatestReport(ctx context.Context, req *pb.LatestReportRequest) (resp *pb.LatestReportResponse, err error) { @@ -306,6 +310,7 @@ func (w *client) LatestReport(ctx context.Context, req *pb.LatestReportRequest) var cached bool if w.cache == nil { resp, err = w.rawClient.LatestReport(ctx, req) + w.handleTimeout(err) } else { cached = true resp, err = w.cache.LatestReport(ctx, req) diff --git a/core/services/relay/evm/mercury/wsrpc/client_test.go b/core/services/relay/evm/mercury/wsrpc/client_test.go index f265d54879c..b4a3dae733d 100644 --- a/core/services/relay/evm/mercury/wsrpc/client_test.go +++ b/core/services/relay/evm/mercury/wsrpc/client_test.go @@ -17,6 +17,14 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" ) +// simulate start without dialling +func simulateStart(ctx context.Context, t *testing.T, c *client) { + require.NoError(t, c.StartOnce("Mock WSRPC Client", func() (err error) { + c.cache, err = c.cacheSet.Get(ctx, c) + return err + })) +} + var _ cache.CacheSet = &mockCacheSet{} type mockCacheSet struct{} @@ -54,7 +62,7 @@ func Test_Client_Transmit(t *testing.T) { noopCacheSet := newNoopCacheSet() - t.Run("sends on reset channel after MaxConsecutiveTransmitFailures timed out transmits", func(t *testing.T) { + t.Run("sends on reset channel after MaxConsecutiveRequestFailures timed out transmits", func(t *testing.T) { calls := 0 transmitErr := context.DeadlineExceeded wsrpcClient := &mocks.MockWSRPCClient{ @@ -70,11 +78,11 @@ func Test_Client_Transmit(t *testing.T) { c.conn = conn c.rawClient = wsrpcClient require.NoError(t, c.StartOnce("Mock WSRPC Client", func() error { return nil })) - for i := 1; i < MaxConsecutiveTransmitFailures; i++ { + for i := 1; i < MaxConsecutiveRequestFailures; i++ { _, err := c.Transmit(ctx, req) require.EqualError(t, err, "context deadline exceeded") } - assert.Equal(t, 4, calls) + assert.Equal(t, MaxConsecutiveRequestFailures-1, calls) select { case <-c.chResetTransport: t.Fatal("unexpected send on chResetTransport") @@ -82,7 +90,7 @@ func Test_Client_Transmit(t *testing.T) { } _, err := c.Transmit(ctx, req) require.EqualError(t, err, "context deadline exceeded") - assert.Equal(t, 5, calls) + assert.Equal(t, MaxConsecutiveRequestFailures, calls) select { case <-c.chResetTransport: default: @@ -94,14 +102,14 @@ func Test_Client_Transmit(t *testing.T) { // working transmit to reset counter _, err = c.Transmit(ctx, req) require.NoError(t, err) - assert.Equal(t, 6, calls) + assert.Equal(t, MaxConsecutiveRequestFailures+1, calls) assert.Equal(t, 0, int(c.consecutiveTimeoutCnt.Load())) }) t.Run("doesn't block in case channel is full", func(t *testing.T) { transmitErr = context.DeadlineExceeded c.chResetTransport = nil // simulate full channel - for i := 0; i < MaxConsecutiveTransmitFailures; i++ { + for i := 0; i < MaxConsecutiveRequestFailures; i++ { _, err := c.Transmit(ctx, req) require.EqualError(t, err, "context deadline exceeded") } @@ -112,105 +120,59 @@ func Test_Client_Transmit(t *testing.T) { func Test_Client_LatestReport(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) + cacheReads := 5 + + tests := []struct { + name string + ttl time.Duration + expectedCalls int + }{ + { + name: "with cache disabled", + ttl: 0, + expectedCalls: 5, + }, + { + name: "with cache enabled", + ttl: 1000 * time.Hour, //some large value that will never expire during a test + expectedCalls: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := &pb.LatestReportRequest{} + + cacheSet := cache.NewCacheSet(lggr, cache.Config{LatestReportTTL: tt.ttl}) + + resp := &pb.LatestReportResponse{} + + var calls int + wsrpcClient := &mocks.MockWSRPCClient{ + LatestReportF: func(ctx context.Context, in *pb.LatestReportRequest) (*pb.LatestReportResponse, error) { + calls++ + assert.Equal(t, req, in) + return resp, nil + }, + } - t.Run("with nil cache", func(t *testing.T) { - req := &pb.LatestReportRequest{} - noopCacheSet := newNoopCacheSet() - resp := &pb.LatestReportResponse{} - - wsrpcClient := &mocks.MockWSRPCClient{ - LatestReportF: func(ctx context.Context, in *pb.LatestReportRequest) (*pb.LatestReportResponse, error) { - assert.Equal(t, req, in) - return resp, nil - }, - } - - conn := &mocks.MockConn{ - Ready: true, - } - c := newClient(lggr, csakey.KeyV2{}, nil, "", noopCacheSet) - c.conn = conn - c.rawClient = wsrpcClient - require.NoError(t, c.StartOnce("Mock WSRPC Client", func() error { return nil })) - - r, err := c.LatestReport(ctx, req) - - require.NoError(t, err) - assert.Equal(t, resp, r) - }) - - t.Run("with cache disabled", func(t *testing.T) { - req := &pb.LatestReportRequest{} - cacheSet := cache.NewCacheSet(lggr, cache.Config{LatestReportTTL: 0}) - resp := &pb.LatestReportResponse{} - - var calls int - wsrpcClient := &mocks.MockWSRPCClient{ - LatestReportF: func(ctx context.Context, in *pb.LatestReportRequest) (*pb.LatestReportResponse, error) { - calls++ - assert.Equal(t, req, in) - return resp, nil - }, - } - - conn := &mocks.MockConn{ - Ready: true, - } - c := newClient(lggr, csakey.KeyV2{}, nil, "", cacheSet) - c.conn = conn - c.rawClient = wsrpcClient - - // simulate start without dialling - require.NoError(t, c.StartOnce("Mock WSRPC Client", func() error { return nil })) - var err error - servicetest.Run(t, cacheSet) - c.cache, err = cacheSet.Get(ctx, c) - require.NoError(t, err) - - for i := 0; i < 5; i++ { - r, err := c.LatestReport(ctx, req) - - require.NoError(t, err) - assert.Equal(t, resp, r) - } - assert.Equal(t, 5, calls, "expected 5 calls to LatestReport but it was called %d times", calls) - }) - - t.Run("with caching", func(t *testing.T) { - req := &pb.LatestReportRequest{} - const neverExpireTTL = 1000 * time.Hour // some massive value that will never expire during a test - cacheSet := cache.NewCacheSet(lggr, cache.Config{LatestReportTTL: neverExpireTTL}) - resp := &pb.LatestReportResponse{} - - var calls int - wsrpcClient := &mocks.MockWSRPCClient{ - LatestReportF: func(ctx context.Context, in *pb.LatestReportRequest) (*pb.LatestReportResponse, error) { - calls++ - assert.Equal(t, req, in) - return resp, nil - }, - } - - conn := &mocks.MockConn{ - Ready: true, - } - c := newClient(lggr, csakey.KeyV2{}, nil, "", cacheSet) - c.conn = conn - c.rawClient = wsrpcClient + conn := &mocks.MockConn{ + Ready: true, + } + c := newClient(lggr, csakey.KeyV2{}, nil, "", cacheSet) + c.conn = conn + c.rawClient = wsrpcClient - // simulate start without dialling - require.NoError(t, c.StartOnce("Mock WSRPC Client", func() error { return nil })) - var err error - servicetest.Run(t, cacheSet) - c.cache, err = cacheSet.Get(ctx, c) - require.NoError(t, err) + servicetest.Run(t, cacheSet) + simulateStart(ctx, t, c) - for i := 0; i < 5; i++ { - r, err := c.LatestReport(ctx, req) + for i := 0; i < cacheReads; i++ { + r, err := c.LatestReport(ctx, req) - require.NoError(t, err) - assert.Equal(t, resp, r) - } - assert.Equal(t, 1, calls, "expected only 1 call to LatestReport but it was called %d times", calls) - }) + require.NoError(t, err) + assert.Equal(t, resp, r) + } + assert.Equal(t, tt.expectedCalls, calls, "expected %d calls to LatestReport but it was called %d times", tt.expectedCalls, calls) + }) + } } diff --git a/core/services/relay/evm/mercury/wsrpc/pool.go b/core/services/relay/evm/mercury/wsrpc/pool.go index 76f9bc808b9..dd85381469b 100644 --- a/core/services/relay/evm/mercury/wsrpc/pool.go +++ b/core/services/relay/evm/mercury/wsrpc/pool.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/smartcontractkit/wsrpc/credentials" + "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -224,7 +225,7 @@ func (p *pool) Ready() error { } func (p *pool) HealthReport() map[string]error { - return map[string]error{ - p.Name(): p.Ready(), - } + hp := map[string]error{p.Name(): p.Ready()} + maps.Copy(hp, p.cacheSet.HealthReport()) + return hp } diff --git a/core/services/relay/evm/mercury/wsrpc/pool_test.go b/core/services/relay/evm/mercury/wsrpc/pool_test.go index 3d418d39d87..bb5ceec0bb6 100644 --- a/core/services/relay/evm/mercury/wsrpc/pool_test.go +++ b/core/services/relay/evm/mercury/wsrpc/pool_test.go @@ -9,12 +9,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var _ Client = &mockClient{} diff --git a/core/services/relay/evm/types/types_test.go b/core/services/relay/evm/types/types_test.go index 6952c35a706..fb394ddf38b 100644 --- a/core/services/relay/evm/types/types_test.go +++ b/core/services/relay/evm/types/types_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ChainID *big.Big `json:"chainID"` diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go index eb6d3faf4fd..118d5935851 100644 --- a/core/services/relay/relay.go +++ b/core/services/relay/relay.go @@ -88,7 +88,9 @@ func (r *ServerAdapter) NewPluginProvider(ctx context.Context, rargs types.Relay return r.NewFunctionsProvider(ctx, rargs, pargs) case types.Mercury: return r.NewMercuryProvider(ctx, rargs, pargs) - case types.DKG, types.OCR2VRF, types.OCR2Keeper, types.GenericPlugin: + case types.OCR2Keeper: + return r.NewAutomationProvider(ctx, rargs, pargs) + case types.DKG, types.OCR2VRF, types.GenericPlugin: return r.RelayerAdapter.NewPluginProvider(ctx, rargs, pargs) case types.CCIPCommit, types.CCIPExecution: return nil, fmt.Errorf("provider type not supported: %s", rargs.ProviderType) diff --git a/core/services/relay/relay_test.go b/core/services/relay/relay_test.go index d23895699df..40a11518edd 100644 --- a/core/services/relay/relay_test.go +++ b/core/services/relay/relay_test.go @@ -97,6 +97,10 @@ type staticMercuryProvider struct { types.MercuryProvider } +type staticAutomationProvider struct { + types.AutomationProvider +} + type mockRelayer struct { types.Relayer } @@ -113,6 +117,10 @@ func (m *mockRelayer) NewMercuryProvider(rargs types.RelayArgs, pargs types.Plug return staticMercuryProvider{}, nil } +func (m *mockRelayer) NewAutomationProvider(rargs types.RelayArgs, pargs types.PluginArgs) (types.AutomationProvider, error) { + return staticAutomationProvider{}, nil +} + type mockRelayerExt struct { loop.RelayerExt } diff --git a/core/services/signatures/secp256k1/public_key.go b/core/services/signatures/secp256k1/public_key.go index 1f7fd9c0ebd..c39565984ae 100644 --- a/core/services/signatures/secp256k1/public_key.go +++ b/core/services/signatures/secp256k1/public_key.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "go.dedis.ch/kyber/v3" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) // PublicKey is a secp256k1 point in compressed format diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index 663080c86a0..591ca3e9508 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -26,6 +26,7 @@ import ( log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -124,14 +125,14 @@ func generateCallbackReturnValues(t *testing.T, fulfilled bool) []byte { // Empty callback b, err2 := args.Pack(solidity_vrf_coordinator_interface.Callbacks{ RandomnessFee: big.NewInt(10), - SeedAndBlockNum: utils.EmptyHash, + SeedAndBlockNum: evmutils.EmptyHash, }) require.NoError(t, err2) return b } b, err := args.Pack(solidity_vrf_coordinator_interface.Callbacks{ RandomnessFee: big.NewInt(10), - SeedAndBlockNum: utils.NewHash(), + SeedAndBlockNum: evmutils.NewHash(), }) require.NoError(t, err) return b @@ -150,7 +151,7 @@ func setup(t *testing.T) (vrfUniverse, *v1.Listener, job.Job) { cfg := configtest.NewTestGeneralConfig(t) vuni := buildVrfUni(t, db, cfg) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) vd := vrf.NewDelegate( db, @@ -185,7 +186,7 @@ func TestDelegate_ReorgAttackProtection(t *testing.T) { vuni, listener, jb := setup(t) // Same request has already been fulfilled twice - reqID := utils.NewHash() + reqID := evmutils.NewHash() var reqIDBytes [32]byte copy(reqIDBytes[:], reqID.Bytes()) listener.SetRespCount(reqIDBytes, 2) @@ -198,17 +199,17 @@ func TestDelegate_ReorgAttackProtection(t *testing.T) { added <- struct{}{} }) preSeed := common.BigToHash(big.NewInt(42)).Bytes() - txHash := utils.NewHash() + txHash := evmutils.NewHash() vuni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil).Maybe() vuni.lb.On("MarkConsumed", mock.Anything, mock.Anything).Return(nil).Maybe() vuni.ec.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(generateCallbackReturnValues(t, false), nil).Maybe() listener.HandleLog(log.NewLogBroadcast(types.Log{ // Data has all the NON-indexed parameters Data: bytes.Join([][]byte{pk.MustHash().Bytes(), // key hash - preSeed, // preSeed - utils.NewHash().Bytes(), // sender - utils.NewHash().Bytes(), // fee - reqID.Bytes()}, []byte{}, // requestID + preSeed, // preSeed + evmutils.NewHash().Bytes(), // sender + evmutils.NewHash().Bytes(), // fee + reqID.Bytes()}, []byte{}, // requestID ), // JobID is indexed, thats why it lives in the Topics. Topics: []common.Hash{ @@ -230,9 +231,9 @@ func TestDelegate_ReorgAttackProtection(t *testing.T) { func TestDelegate_ValidLog(t *testing.T) { vuni, listener, jb := setup(t) - txHash := utils.NewHash() - reqID1 := utils.NewHash() - reqID2 := utils.NewHash() + txHash := evmutils.NewHash() + reqID1 := evmutils.NewHash() + reqID2 := evmutils.NewHash() keyID := vuni.vrfkey.PublicKey.String() pk, err := secp256k1.NewPublicKeyFromHex(keyID) require.NoError(t, err) @@ -241,7 +242,7 @@ func TestDelegate_ValidLog(t *testing.T) { added <- struct{}{} }) preSeed := common.BigToHash(big.NewInt(42)).Bytes() - bh := utils.NewHash() + bh := evmutils.NewHash() var tt = []struct { reqID [32]byte log types.Log @@ -253,8 +254,8 @@ func TestDelegate_ValidLog(t *testing.T) { Data: bytes.Join([][]byte{ pk.MustHash().Bytes(), // key hash common.BigToHash(big.NewInt(42)).Bytes(), // seed - utils.NewHash().Bytes(), // sender - utils.NewHash().Bytes(), // fee + evmutils.NewHash().Bytes(), // sender + evmutils.NewHash().Bytes(), // fee reqID1.Bytes()}, // requestID []byte{}), // JobID is indexed, thats why it lives in the Topics. @@ -275,8 +276,8 @@ func TestDelegate_ValidLog(t *testing.T) { Data: bytes.Join([][]byte{ pk.MustHash().Bytes(), // key hash common.BigToHash(big.NewInt(42)).Bytes(), // seed - utils.NewHash().Bytes(), // sender - utils.NewHash().Bytes(), // fee + evmutils.NewHash().Bytes(), // sender + evmutils.NewHash().Bytes(), // fee reqID2.Bytes()}, // requestID []byte{}), Topics: []common.Hash{ @@ -324,7 +325,7 @@ func TestDelegate_ValidLog(t *testing.T) { // Should have 4 tasks all completed assert.Len(t, runs[0].PipelineTaskRuns, 4) - p, err := vuni.ks.VRF().GenerateProof(keyID, utils.MustHash(string(bytes.Join([][]byte{preSeed, bh.Bytes()}, []byte{}))).Big()) + p, err := vuni.ks.VRF().GenerateProof(keyID, evmutils.MustHash(string(bytes.Join([][]byte{preSeed, bh.Bytes()}, []byte{}))).Big()) require.NoError(t, err) vuni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) vuni.lb.On("MarkConsumed", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { @@ -367,11 +368,11 @@ func TestDelegate_InvalidLog(t *testing.T) { listener.HandleLog(log.NewLogBroadcast(types.Log{ // Data has all the NON-indexed parameters Data: append(append(append(append( - utils.NewHash().Bytes(), // key hash + evmutils.NewHash().Bytes(), // key hash common.BigToHash(big.NewInt(42)).Bytes()...), // seed - utils.NewHash().Bytes()...), // sender - utils.NewHash().Bytes()...), // fee - utils.NewHash().Bytes()...), // requestID + evmutils.NewHash().Bytes()...), // sender + evmutils.NewHash().Bytes()...), // fee + evmutils.NewHash().Bytes()...), // requestID // JobID is indexed, that's why it lives in the Topics. Topics: []common.Hash{ solidity_cross_tests.VRFRandomnessRequestLogTopic(), @@ -404,11 +405,13 @@ func TestDelegate_InvalidLog(t *testing.T) { } } - // Ensure we have NOT queued up an eth transaction - var ethTxes []txmgr.DbEthTx - err = vuni.prm.GetQ().Select(ðTxes, `SELECT * FROM evm.txes;`) + db := pgtest.NewSqlxDB(t) + cfg := pgtest.NewQConfig(false) + txStore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg) + + txes, err := txStore.GetAllTxes(testutils.Context(t)) require.NoError(t, err) - require.Len(t, ethTxes, 0) + require.Len(t, txes, 0) } func TestFulfilledCheck(t *testing.T) { @@ -433,18 +436,18 @@ func TestFulfilledCheck(t *testing.T) { Data: bytes.Join([][]byte{ vuni.vrfkey.PublicKey.MustHash().Bytes(), // key hash common.BigToHash(big.NewInt(42)).Bytes(), // seed - utils.NewHash().Bytes(), // sender - utils.NewHash().Bytes(), // fee - utils.NewHash().Bytes()}, // requestID + evmutils.NewHash().Bytes(), // sender + evmutils.NewHash().Bytes(), // fee + evmutils.NewHash().Bytes()}, // requestID []byte{}), // JobID is indexed, that's why it lives in the Topics. Topics: []common.Hash{ solidity_cross_tests.VRFRandomnessRequestLogTopic(), jb.ExternalIDEncodeBytesToTopic(), // jobID STRING }, - //TxHash: utils.NewHash().Bytes(), + //TxHash: evmutils.NewHash().Bytes(), BlockNumber: 10, - //BlockHash: utils.NewHash().Bytes(), + //BlockHash: evmutils.NewHash().Bytes(), }, vuni.cid, nil)) // Should queue the request, even though its already fulfilled @@ -674,7 +677,7 @@ func Test_VRFV2PlusServiceFailsWhenVRFOwnerProvided(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) vuni := buildVrfUni(t, db, cfg) - mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) + mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) vd := vrf.NewDelegate( db, diff --git a/core/services/vrf/extraargs/types.go b/core/services/vrf/extraargs/types.go index 4dcc87e5d04..eecd0bfa334 100644 --- a/core/services/vrf/extraargs/types.go +++ b/core/services/vrf/extraargs/types.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) const functionSignatureLength = 4 diff --git a/core/services/vrf/proof/proof_response.go b/core/services/vrf/proof/proof_response.go index 4cb58d921a4..f4e332616ca 100644 --- a/core/services/vrf/proof/proof_response.go +++ b/core/services/vrf/proof/proof_response.go @@ -13,9 +13,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ProofResponse is the data which is sent back to the VRFCoordinator, so that diff --git a/core/services/vrf/proof/seed.go b/core/services/vrf/proof/seed.go index 176a5e013ec..75dc441d881 100644 --- a/core/services/vrf/proof/seed.go +++ b/core/services/vrf/proof/seed.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) // Seed represents a VRF seed as a serialized uint256 diff --git a/core/services/vrf/proof/solidity_proof.go b/core/services/vrf/proof/solidity_proof.go index c5823289cf1..48f2f9fd984 100644 --- a/core/services/vrf/proof/solidity_proof.go +++ b/core/services/vrf/proof/solidity_proof.go @@ -11,9 +11,9 @@ import ( "github.com/pkg/errors" "go.dedis.ch/kyber/v3" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" - "github.com/smartcontractkit/chainlink/v2/core/utils" bm "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) diff --git a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go index 35556c6b45f..3603230fea0 100644 --- a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go +++ b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go @@ -8,8 +8,8 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // RawRandomnessRequestLog is used to parse a RandomnessRequest log into types diff --git a/core/services/vrf/solidity_cross_tests/vrf_coordinator_solidity_crosscheck_test.go b/core/services/vrf/solidity_cross_tests/vrf_coordinator_solidity_crosscheck_test.go index 8dfbdae0148..e758689593a 100644 --- a/core/services/vrf/solidity_cross_tests/vrf_coordinator_solidity_crosscheck_test.go +++ b/core/services/vrf/solidity_cross_tests/vrf_coordinator_solidity_crosscheck_test.go @@ -13,9 +13,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/solidity_cross_tests" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) diff --git a/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go b/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go index 06875edd74e..2476ee04ce2 100644 --- a/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go +++ b/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go @@ -19,11 +19,11 @@ import ( "github.com/stretchr/testify/require" "go.dedis.ch/kyber/v3" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Cross-checks of golang implementation details vs corresponding solidity diff --git a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go index d1b21b58647..0552f93fea1 100644 --- a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go +++ b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go @@ -15,11 +15,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Note these tests are identical to the ones in vrf_solidity_crosscheck_test.go, diff --git a/core/services/vrf/v1/listener_v1_test.go b/core/services/vrf/v1/listener_v1_test.go index 4ab5d7ab368..c05358686df 100644 --- a/core/services/vrf/v1/listener_v1_test.go +++ b/core/services/vrf/v1/listener_v1_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/theodesp/go-heaps/pairing" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestConfirmedLogExtraction(t *testing.T) { diff --git a/core/services/vrf/v2/coordinator_v2x_interface.go b/core/services/vrf/v2/coordinator_v2x_interface.go index e20500cca89..e88053ebc2c 100644 --- a/core/services/vrf/v2/coordinator_v2x_interface.go +++ b/core/services/vrf/v2/coordinator_v2x_interface.go @@ -36,9 +36,11 @@ type CoordinatorV2_X interface { GetConfig(opts *bind.CallOpts) (Config, error) ParseLog(log types.Log) (generated.AbigenLog, error) OracleWithdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) + Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) + WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) LogsWithTopics(keyHash common.Hash) map[common.Hash][][]log.Topic Version() vrfcommon.Version - RegisterProvingKey(opts *bind.TransactOpts, oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) + RegisterProvingKey(opts *bind.TransactOpts, oracle *common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) FilterSubscriptionCreated(opts *bind.FilterOpts, subID []*big.Int) (SubscriptionCreatedIterator, error) FilterRandomWordsRequested(opts *bind.FilterOpts, keyHash [][32]byte, subID []*big.Int, sender []common.Address) (RandomWordsRequestedIterator, error) FilterRandomWordsFulfilled(opts *bind.FilterOpts, requestID []*big.Int, subID []*big.Int) (RandomWordsFulfilledIterator, error) @@ -130,6 +132,14 @@ func (c *coordinatorV2) OracleWithdraw(opts *bind.TransactOpts, recipient common return c.coordinator.OracleWithdraw(opts, recipient, amount) } +func (c *coordinatorV2) Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return nil, errors.New("withdraw not implemented for v2") +} + +func (c *coordinatorV2) WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return nil, errors.New("withdrawNative not implemented for v2") +} + func (c *coordinatorV2) LogsWithTopics(keyHash common.Hash) map[common.Hash][][]log.Topic { return map[common.Hash][][]log.Topic{ vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested{}.Topic(): { @@ -144,8 +154,8 @@ func (c *coordinatorV2) Version() vrfcommon.Version { return c.vrfVersion } -func (c *coordinatorV2) RegisterProvingKey(opts *bind.TransactOpts, oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return c.coordinator.RegisterProvingKey(opts, oracle, publicProvingKey) +func (c *coordinatorV2) RegisterProvingKey(opts *bind.TransactOpts, oracle *common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return c.coordinator.RegisterProvingKey(opts, *oracle, publicProvingKey) } func (c *coordinatorV2) FilterSubscriptionCreated(opts *bind.FilterOpts, subID []*big.Int) (SubscriptionCreatedIterator, error) { @@ -281,7 +291,15 @@ func (c *coordinatorV2_5) ParseLog(log types.Log) (generated.AbigenLog, error) { } func (c *coordinatorV2_5) OracleWithdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { - return c.coordinator.OracleWithdraw(opts, recipient, amount) + return nil, errors.New("oracle withdraw not implemented for v2.5") +} + +func (c *coordinatorV2_5) Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return c.coordinator.Withdraw(opts, recipient) +} + +func (c *coordinatorV2_5) WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return c.coordinator.WithdrawNative(opts, recipient) } func (c *coordinatorV2_5) LogsWithTopics(keyHash common.Hash) map[common.Hash][][]log.Topic { @@ -298,8 +316,11 @@ func (c *coordinatorV2_5) Version() vrfcommon.Version { return c.vrfVersion } -func (c *coordinatorV2_5) RegisterProvingKey(opts *bind.TransactOpts, oracle common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return c.coordinator.RegisterProvingKey(opts, oracle, publicProvingKey) +func (c *coordinatorV2_5) RegisterProvingKey(opts *bind.TransactOpts, oracle *common.Address, publicProvingKey [2]*big.Int) (*types.Transaction, error) { + if oracle != nil { + return nil, errors.New("oracle address not supported for registering proving key in v2.5") + } + return c.coordinator.RegisterProvingKey(opts, publicProvingKey) } func (c *coordinatorV2_5) FilterSubscriptionCreated(opts *bind.FilterOpts, subID []*big.Int) (SubscriptionCreatedIterator, error) { diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index d8a7da70a86..b5f6a095cff 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_consumer_v2_upgradeable_example" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_external_sub_owner_example" @@ -31,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" v22 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" @@ -870,7 +870,7 @@ func setupAndFundSubscriptionAndConsumer( uni.backend.Commit() if vrfVersion == vrfcommon.V2Plus { - b, err2 := utils.ABIEncode(`[{"type":"uint256"}]`, subID) + b, err2 := evmutils.ABIEncode(`[{"type":"uint256"}]`, subID) require.NoError(t, err2) _, err2 = uni.linkContract.TransferAndCall( uni.sergey, coordinatorAddress, fundingAmount, b) @@ -878,7 +878,7 @@ func setupAndFundSubscriptionAndConsumer( uni.backend.Commit() return } - b, err := utils.ABIEncode(`[{"type":"uint64"}]`, subID.Uint64()) + b, err := evmutils.ABIEncode(`[{"type":"uint64"}]`, subID.Uint64()) require.NoError(t, err) _, err = uni.linkContract.TransferAndCall( uni.sergey, coordinatorAddress, fundingAmount, b) @@ -1682,11 +1682,7 @@ func testMaliciousConsumer( time.Sleep(1 * time.Second) // Register a proving key associated with the VRF job. - p, err := vrfkey.PublicKey.Point() - require.NoError(t, err) - _, err = uni.rootContract.RegisterProvingKey( - uni.neil, uni.nallory.From, pair(secp256k1.Coordinates(p))) - require.NoError(t, err) + registerProvingKeyHelper(t, uni, uni.rootContract, vrfkey) subFunding := decimal.RequireFromString("1000000000000000000") _, err = uni.maliciousConsumerContract.CreateSubscriptionAndFund(carol, diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go index 1564f0f6343..fb47d84ed7a 100644 --- a/core/services/vrf/v2/integration_v2_plus_test.go +++ b/core/services/vrf/v2/integration_v2_plus_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2plus" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" @@ -44,14 +45,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" - "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/extraargs" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof" v22 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type coordinatorV2PlusUniverse struct { @@ -850,12 +849,7 @@ func TestVRFV2PlusIntegration_RequestCost(t *testing.T) { vrfkey, err := app.GetKeyStore().VRF().Create() require.NoError(t, err) - p, err := vrfkey.PublicKey.Point() - require.NoError(t, err) - _, err = uni.rootContract.RegisterProvingKey( - uni.neil, uni.neil.From, pair(secp256k1.Coordinates(p))) - require.NoError(t, err) - uni.backend.Commit() + registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey) t.Run("non-proxied consumer", func(tt *testing.T) { carol := uni.vrfConsumers[0] carolContract := uni.consumerContracts[0] @@ -1010,12 +1004,7 @@ func TestVRFV2PlusIntegration_FulfillmentCost(t *testing.T) { vrfkey, err := app.GetKeyStore().VRF().Create() require.NoError(t, err) - p, err := vrfkey.PublicKey.Point() - require.NoError(t, err) - _, err = uni.rootContract.RegisterProvingKey( - uni.neil, uni.neil.From, pair(secp256k1.Coordinates(p))) - require.NoError(t, err) - uni.backend.Commit() + registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey) t.Run("non-proxied consumer", func(tt *testing.T) { carol := uni.vrfConsumers[0] diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 8d6354c4fd8..dee69c9abef 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -31,6 +31,7 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -40,6 +41,7 @@ import ( evmlogger "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" @@ -428,7 +430,7 @@ func deployOldCoordinator( ) { ctx := testutils.Context(t) bytecode := hexutil.MustDecode("0x60e06040523480156200001157600080fd5b506040516200608c3803806200608c8339810160408190526200003491620001b1565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e8565b5050506001600160601b0319606093841b811660805290831b811660a052911b1660c052620001fb565b6001600160a01b038116331415620001435760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001ac57600080fd5b919050565b600080600060608486031215620001c757600080fd5b620001d28462000194565b9250620001e26020850162000194565b9150620001f26040850162000194565b90509250925092565b60805160601c60a05160601c60c05160601c615e2762000265600039600081816105260152613bd901526000818161061d015261402401526000818161036d01528181611599015281816125960152818161302c0152818161318201526138360152615e276000f3fe608060405234801561001057600080fd5b506004361061025b5760003560e01c80636f64f03f11610145578063ad178361116100bd578063d2f9f9a71161008c578063e72f6e3011610071578063e72f6e30146106fa578063e82ad7d41461070d578063f2fde38b1461073057600080fd5b8063d2f9f9a7146106d4578063d7ae1d30146106e757600080fd5b8063ad17836114610618578063af198b971461063f578063c3f909d41461066f578063caf70c4a146106c157600080fd5b80638da5cb5b11610114578063a21a23e4116100f9578063a21a23e4146105da578063a47c7696146105e2578063a4c0ed361461060557600080fd5b80638da5cb5b146105a95780639f87fad7146105c757600080fd5b80636f64f03f146105685780637341c10c1461057b57806379ba50971461058e578063823597401461059657600080fd5b8063356dac71116101d85780635fbbc0d2116101a757806366316d8d1161018c57806366316d8d1461050e578063689c45171461052157806369bcdb7d1461054857600080fd5b80635fbbc0d21461040057806364d51a2a1461050657600080fd5b8063356dac71146103b457806340d6bb82146103bc5780634cb48a54146103da5780635d3b1d30146103ed57600080fd5b806308821d581161022f57806315c48b841161021457806315c48b841461030e578063181f5a77146103295780631b6b6d231461036857600080fd5b806308821d58146102cf57806312b58349146102e257600080fd5b80620122911461026057806302bcc5b61461028057806304c357cb1461029557806306bfa637146102a8575b600080fd5b610268610743565b60405161027793929190615964565b60405180910390f35b61029361028e366004615792565b6107bf565b005b6102936102a33660046157ad565b61086b565b60055467ffffffffffffffff165b60405167ffffffffffffffff9091168152602001610277565b6102936102dd3660046154a3565b610a60565b6005546801000000000000000090046bffffffffffffffffffffffff165b604051908152602001610277565b61031660c881565b60405161ffff9091168152602001610277565b604080518082018252601681527f565246436f6f7264696e61746f72563220312e302e30000000000000000000006020820152905161027791906158f1565b61038f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610277565b600a54610300565b6103c56101f481565b60405163ffffffff9091168152602001610277565b6102936103e836600461563c565b610c3f565b6103006103fb366004615516565b611036565b600c546040805163ffffffff80841682526401000000008404811660208301526801000000000000000084048116928201929092526c010000000000000000000000008304821660608201527001000000000000000000000000000000008304909116608082015262ffffff740100000000000000000000000000000000000000008304811660a0830152770100000000000000000000000000000000000000000000008304811660c08301527a0100000000000000000000000000000000000000000000000000008304811660e08301527d01000000000000000000000000000000000000000000000000000000000090920490911661010082015261012001610277565b610316606481565b61029361051c36600461545b565b611444565b61038f7f000000000000000000000000000000000000000000000000000000000000000081565b610300610556366004615779565b60009081526009602052604090205490565b6102936105763660046153a0565b6116ad565b6102936105893660046157ad565b6117f7565b610293611a85565b6102936105a4366004615792565b611b82565b60005473ffffffffffffffffffffffffffffffffffffffff1661038f565b6102936105d53660046157ad565b611d7c565b6102b66121fd565b6105f56105f0366004615792565b6123ed565b6040516102779493929190615b02565b6102936106133660046153d4565b612537565b61038f7f000000000000000000000000000000000000000000000000000000000000000081565b61065261064d366004615574565b6127a8565b6040516bffffffffffffffffffffffff9091168152602001610277565b600b546040805161ffff8316815263ffffffff6201000084048116602083015267010000000000000084048116928201929092526b010000000000000000000000909204166060820152608001610277565b6103006106cf3660046154bf565b612c6d565b6103c56106e2366004615792565b612c9d565b6102936106f53660046157ad565b612e92565b610293610708366004615385565b612ff3565b61072061071b366004615792565b613257565b6040519015158152602001610277565b61029361073e366004615385565b6134ae565b600b546007805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff169391928391908301828280156107ad57602002820191906000526020600020905b815481526020019060010190808311610799575b50505050509050925092509250909192565b6107c76134bf565b67ffffffffffffffff811660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1661082d576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526003602052604090205461086890829073ffffffffffffffffffffffffffffffffffffffff16613542565b50565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff16806108d4576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821614610940576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b600b546601000000000000900460ff1615610987576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff841660009081526003602052604090206001015473ffffffffffffffffffffffffffffffffffffffff848116911614610a5a5767ffffffffffffffff841660008181526003602090815260409182902060010180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88169081179091558251338152918201527f69436ea6df009049404f564eff6622cd00522b0bd6a89efd9e52a355c4a879be91015b60405180910390a25b50505050565b610a686134bf565b604080518082018252600091610a97919084906002908390839080828437600092019190915250612c6d915050565b60008181526006602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1680610af9576040517f77f5b84c00000000000000000000000000000000000000000000000000000000815260048101839052602401610937565b600082815260066020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b600754811015610be9578260078281548110610b4c57610b4c615dbc565b90600052602060002001541415610bd7576007805460009190610b7190600190615c76565b81548110610b8157610b81615dbc565b906000526020600020015490508060078381548110610ba257610ba2615dbc565b6000918252602090912001556007805480610bbf57610bbf615d8d565b60019003818190600052602060002001600090559055505b80610be181615cba565b915050610b2e565b508073ffffffffffffffffffffffffffffffffffffffff167f72be339577868f868798bac2c93e52d6f034fef4689a9848996c14ebb7416c0d83604051610c3291815260200190565b60405180910390a2505050565b610c476134bf565b60c861ffff87161115610c9a576040517fa738697600000000000000000000000000000000000000000000000000000000815261ffff871660048201819052602482015260c86044820152606401610937565b60008213610cd7576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610937565b6040805160a0808201835261ffff891680835263ffffffff89811660208086018290526000868801528a831660608088018290528b85166080988901819052600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001690971762010000909502949094177fffffffffffffffffffffffffffffffffff000000000000000000ffffffffffff166701000000000000009092027fffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffff16919091176b010000000000000000000000909302929092179093558651600c80549489015189890151938a0151978a0151968a015160c08b015160e08c01516101008d01519588167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009099169890981764010000000093881693909302929092177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff1668010000000000000000958716959095027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16949094176c0100000000000000000000000098861698909802979097177fffffffffffffffffff00000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000096909416959095027fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff16929092177401000000000000000000000000000000000000000062ffffff92831602177fffffff000000000000ffffffffffffffffffffffffffffffffffffffffffffff1677010000000000000000000000000000000000000000000000958216959095027fffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffff16949094177a01000000000000000000000000000000000000000000000000000092851692909202919091177cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167d0100000000000000000000000000000000000000000000000000000000009390911692909202919091178155600a84905590517fc21e3bd2e0b339d2848f0dd956947a88966c242c0c0c582a33137a5c1ceb5cb2916110269189918991899189918991906159c3565b60405180910390a1505050505050565b600b546000906601000000000000900460ff1615611080576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff851660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff166110e6576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260026020908152604080832067ffffffffffffffff808a1685529252909120541680611156576040517ff0019fe600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152336024820152604401610937565b600b5461ffff9081169086161080611172575060c861ffff8616115b156111c257600b546040517fa738697600000000000000000000000000000000000000000000000000000000815261ffff8088166004830152909116602482015260c86044820152606401610937565b600b5463ffffffff620100009091048116908516111561122957600b546040517ff5d7e01e00000000000000000000000000000000000000000000000000000000815263ffffffff8087166004830152620100009092049091166024820152604401610937565b6101f463ffffffff8416111561127b576040517f47386bec00000000000000000000000000000000000000000000000000000000815263ffffffff841660048201526101f46024820152604401610937565b6000611288826001615bd2565b6040805160208082018c9052338284015267ffffffffffffffff808c16606084015284166080808401919091528351808403909101815260a08301845280519082012060c083018d905260e080840182905284518085039091018152610100909301909352815191012091925060009182916040805160208101849052439181019190915267ffffffffffffffff8c16606082015263ffffffff808b166080830152891660a08201523360c0820152919350915060e001604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160209182012060008681526009835283902055848352820183905261ffff8a169082015263ffffffff808916606083015287166080820152339067ffffffffffffffff8b16908c907f63373d1c4696214b898952999c9aaec57dac1ee2723cec59bea6888f489a97729060a00160405180910390a45033600090815260026020908152604080832067ffffffffffffffff808d16855292529091208054919093167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009091161790915591505095945050505050565b600b546601000000000000900460ff161561148b576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600860205260409020546bffffffffffffffffffffffff808316911610156114e5576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260086020526040812080548392906115129084906bffffffffffffffffffffffff16615c8d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555080600560088282829054906101000a90046bffffffffffffffffffffffff166115699190615c8d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b815260040161162192919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b602060405180830381600087803b15801561163b57600080fd5b505af115801561164f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167391906154db565b6116a9576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b6116b56134bf565b6040805180820182526000916116e4919084906002908390839080828437600092019190915250612c6d915050565b60008181526006602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1615611746576040517f4a0b8fa700000000000000000000000000000000000000000000000000000000815260048101829052602401610937565b600081815260066020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88169081179091556007805460018101825594527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688909301849055518381527fe729ae16526293f74ade739043022254f1489f616295a25bf72dfb4511ed73b89101610c32565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff1680611860576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8216146118c7576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610937565b600b546601000000000000900460ff161561190e576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff841660009081526003602052604090206002015460641415611965576040517f05a48e0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020908152604080832067ffffffffffffffff808916855292529091205416156119ac57610a5a565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260026020818152604080842067ffffffffffffffff8a1680865290835281852080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001908117909155600384528286209094018054948501815585529382902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001685179055905192835290917f43dc749a04ac8fb825cbd514f7c0e13f13bc6f2ee66043b76629d51776cff8e09101610a51565b60015473ffffffffffffffffffffffffffffffffffffffff163314611b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610937565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600b546601000000000000900460ff1615611bc9576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16611c2f576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526003602052604090206001015473ffffffffffffffffffffffffffffffffffffffff163314611cd15767ffffffffffffffff8116600090815260036020526040908190206001015490517fd084e97500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610937565b67ffffffffffffffff81166000818152600360209081526040918290208054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560019093018054909316909255835173ffffffffffffffffffffffffffffffffffffffff909116808252928101919091529092917f6f1dc65165ffffedfd8e507b4a0f1fcfdada045ed11f6c26ba27cedfe87802f0910160405180910390a25050565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff1680611de5576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821614611e4c576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610937565b600b546601000000000000900460ff1615611e93576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020908152604080832067ffffffffffffffff808916855292529091205416611f2e576040517ff0019fe600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff84166024820152604401610937565b67ffffffffffffffff8416600090815260036020908152604080832060020180548251818502810185019093528083529192909190830182828015611fa957602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611f7e575b50505050509050600060018251611fc09190615c76565b905060005b825181101561215f578573ffffffffffffffffffffffffffffffffffffffff16838281518110611ff757611ff7615dbc565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16141561214d57600083838151811061202f5761202f615dbc565b6020026020010151905080600360008a67ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600201838154811061207557612075615dbc565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff949094169390931790925567ffffffffffffffff8a1681526003909152604090206002018054806120ef576120ef615d8d565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555061215f565b8061215781615cba565b915050611fc5565b5073ffffffffffffffffffffffffffffffffffffffff8516600081815260026020908152604080832067ffffffffffffffff8b168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001690555192835290917f182bff9831466789164ca77075fffd84916d35a8180ba73c27e45634549b445b91015b60405180910390a2505050505050565b600b546000906601000000000000900460ff1615612247576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005805467ffffffffffffffff1690600061226183615cf3565b82546101009290920a67ffffffffffffffff8181021990931691831602179091556005541690506000806040519080825280602002602001820160405280156122b4578160200160208202803683370190505b506040805180820182526000808252602080830182815267ffffffffffffffff888116808552600484528685209551865493516bffffffffffffffffffffffff9091167fffffffffffffffffffffffff0000000000000000000000000000000000000000948516176c010000000000000000000000009190931602919091179094558451606081018652338152808301848152818701888152958552600384529590932083518154831673ffffffffffffffffffffffffffffffffffffffff918216178255955160018201805490931696169590951790559151805194955090936123a592600285019201906150c5565b505060405133815267ffffffffffffffff841691507f464722b4166576d3dcbba877b999bc35cf911f4eaf434b7eba68fa113951d0bf9060200160405180910390a250905090565b67ffffffffffffffff81166000908152600360205260408120548190819060609073ffffffffffffffffffffffffffffffffffffffff1661245a576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff80861660009081526004602090815260408083205460038352928190208054600290910180548351818602810186019094528084526bffffffffffffffffffffffff8616966c010000000000000000000000009096049095169473ffffffffffffffffffffffffffffffffffffffff90921693909291839183018282801561252157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116124f6575b5050505050905093509350935093509193509193565b600b546601000000000000900460ff161561257e576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146125ed576040517f44b0e3c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114612627576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061263582840184615792565b67ffffffffffffffff811660009081526003602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1661269e576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8116600090815260046020526040812080546bffffffffffffffffffffffff16918691906126d58385615bfe565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555084600560088282829054906101000a90046bffffffffffffffffffffffff1661272c9190615bfe565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508167ffffffffffffffff167fd39ec07f4e209f627a4c427971473820dc129761ba28de8906bd56f57101d4f88287846127939190615bba565b604080519283526020830191909152016121ed565b600b546000906601000000000000900460ff16156127f2576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005a9050600080600061280687876139b5565b9250925092506000866060015163ffffffff1667ffffffffffffffff81111561283157612831615deb565b60405190808252806020026020018201604052801561285a578160200160208202803683370190505b50905060005b876060015163ffffffff168110156128ce5760408051602081018590529081018290526060016040516020818303038152906040528051906020012060001c8282815181106128b1576128b1615dbc565b6020908102919091010152806128c681615cba565b915050612860565b506000838152600960205260408082208290555181907f1fe543e300000000000000000000000000000000000000000000000000000000906129169087908690602401615ab4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252600b80547fffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffff166601000000000000179055908a015160808b01519192506000916129e49163ffffffff169084613d04565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffff1690556020808c01805167ffffffffffffffff9081166000908152600490935260408084205492518216845290922080549394506c01000000000000000000000000918290048316936001939192600c92612a68928692900416615bd2565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000612abf8a600b600001600b9054906101000a900463ffffffff1663ffffffff16612ab985612c9d565b3a613d52565b6020808e015167ffffffffffffffff166000908152600490915260409020549091506bffffffffffffffffffffffff80831691161015612b2b576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808d015167ffffffffffffffff1660009081526004909152604081208054839290612b679084906bffffffffffffffffffffffff16615c8d565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008b81526006602090815260408083205473ffffffffffffffffffffffffffffffffffffffff1683526008909152812080548594509092612bd091859116615bfe565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550877f7dffc5ae5ee4e2e4df1651cf6ad329a73cebdb728f37ea0187b9b17e036756e4888386604051612c53939291909283526bffffffffffffffffffffffff9190911660208301521515604082015260600190565b60405180910390a299505050505050505050505b92915050565b600081604051602001612c8091906158e3565b604051602081830303815290604052805190602001209050919050565b6040805161012081018252600c5463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c010000000000000000000000008104831660608301527001000000000000000000000000000000008104909216608082015262ffffff740100000000000000000000000000000000000000008304811660a08301819052770100000000000000000000000000000000000000000000008404821660c08401527a0100000000000000000000000000000000000000000000000000008404821660e08401527d0100000000000000000000000000000000000000000000000000000000009093041661010082015260009167ffffffffffffffff841611612dbb575192915050565b8267ffffffffffffffff168160a0015162ffffff16108015612df057508060c0015162ffffff168367ffffffffffffffff1611155b15612dff576020015192915050565b8267ffffffffffffffff168160c0015162ffffff16108015612e3457508060e0015162ffffff168367ffffffffffffffff1611155b15612e43576040015192915050565b8267ffffffffffffffff168160e0015162ffffff16108015612e79575080610100015162ffffff168367ffffffffffffffff1611155b15612e88576060015192915050565b6080015192915050565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff1680612efb576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821614612f62576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610937565b600b546601000000000000900460ff1615612fa9576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb284613257565b15612fe9576040517fb42f66e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a5a8484613542565b612ffb6134bf565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a082319060240160206040518083038186803b15801561308357600080fd5b505afa158015613097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130bb91906154fd565b6005549091506801000000000000000090046bffffffffffffffffffffffff168181111561311f576040517fa99da3020000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610937565b818110156132525760006131338284615c76565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb90604401602060405180830381600087803b1580156131c857600080fd5b505af11580156131dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061320091906154db565b506040805173ffffffffffffffffffffffffffffffffffffffff86168152602081018390527f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b436600910160405180910390a1505b505050565b67ffffffffffffffff811660009081526003602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561330657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116132db575b505050505081525050905060005b8160400151518110156134a45760005b60075481101561349157600061345a6007838154811061334657613346615dbc565b90600052602060002001548560400151858151811061336757613367615dbc565b602002602001015188600260008960400151898151811061338a5761338a615dbc565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040908101600090812067ffffffffffffffff808f168352935220541660408051602080820187905273ffffffffffffffffffffffffffffffffffffffff959095168183015267ffffffffffffffff9384166060820152919092166080808301919091528251808303909101815260a08201835280519084012060c082019490945260e080820185905282518083039091018152610100909101909152805191012091565b506000818152600960205260409020549091501561347e5750600195945050505050565b508061348981615cba565b915050613324565b508061349c81615cba565b915050613314565b5060009392505050565b6134b66134bf565b61086881613e5a565b60005473ffffffffffffffffffffffffffffffffffffffff163314613540576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610937565b565b600b546601000000000000900460ff1615613589576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff821660009081526003602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff90811682526001830154168185015260028201805484518187028101870186528181529295939486019383018282801561363457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311613609575b5050509190925250505067ffffffffffffffff80851660009081526004602090815260408083208151808301909252546bffffffffffffffffffffffff81168083526c01000000000000000000000000909104909416918101919091529293505b83604001515181101561373b5760026000856040015183815181106136bc576136bc615dbc565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040908101600090812067ffffffffffffffff8a168252909252902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001690558061373381615cba565b915050613695565b5067ffffffffffffffff8516600090815260036020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590613796600283018261514f565b505067ffffffffffffffff8516600090815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600580548291906008906138069084906801000000000000000090046bffffffffffffffffffffffff16615c8d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85836bffffffffffffffffffffffff166040518363ffffffff1660e01b81526004016138be92919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b602060405180830381600087803b1580156138d857600080fd5b505af11580156138ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391091906154db565b613946576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff861681526bffffffffffffffffffffffff8316602082015267ffffffffffffffff8716917fe8ed5b475a5b5987aa9165e8731bb78043f39eee32ec5a1169a89e27fcd49815910160405180910390a25050505050565b60008060006139c78560000151612c6d565b60008181526006602052604090205490935073ffffffffffffffffffffffffffffffffffffffff1680613a29576040517f77f5b84c00000000000000000000000000000000000000000000000000000000815260048101859052602401610937565b6080860151604051613a48918691602001918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600990935291205490935080613ac5576040517f3688124a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85516020808801516040808a015160608b015160808c01519251613b3e968b96909594910195865267ffffffffffffffff948516602087015292909316604085015263ffffffff908116606085015291909116608083015273ffffffffffffffffffffffffffffffffffffffff1660a082015260c00190565b604051602081830303815290604052805190602001208114613b8c576040517fd529142c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855167ffffffffffffffff164080613cb05786516040517fe9413d3800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9413d389060240160206040518083038186803b158015613c3057600080fd5b505afa158015613c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c6891906154fd565b905080613cb05786516040517f175dadad00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610937565b6000886080015182604051602001613cd2929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c9050613cf78982613f50565b9450505050509250925092565b60005a611388811015613d1657600080fd5b611388810390508460408204820311613d2e57600080fd5b50823b613d3a57600080fd5b60008083516020850160008789f190505b9392505050565b600080613d5d613fd9565b905060008113613d9c576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101829052602401610937565b6000815a613daa8989615bba565b613db49190615c76565b613dc686670de0b6b3a7640000615c39565b613dd09190615c39565b613dda9190615c25565b90506000613df363ffffffff871664e8d4a51000615c39565b9050613e0b816b033b2e3c9fd0803ce8000000615c76565b821115613e44576040517fe80fa38100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e4e8183615bba565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116331415613eda576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610937565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000613f848360000151846020015185604001518660600151868860a001518960c001518a60e001518b61010001516140ed565b60038360200151604051602001613f9c929190615aa0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209392505050565b600b54604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051600092670100000000000000900463ffffffff169182151591849182917f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163feaf968c9160048083019260a0929190829003018186803b15801561407f57600080fd5b505afa158015614093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b791906157d7565b5094509092508491505080156140db57506140d28242615c76565b8463ffffffff16105b156140e55750600a545b949350505050565b6140f6896143c4565b61415c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f7075626c6963206b6579206973206e6f74206f6e2063757276650000000000006044820152606401610937565b614165886143c4565b6141cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f67616d6d61206973206e6f74206f6e20637572766500000000000000000000006044820152606401610937565b6141d4836143c4565b61423a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e2063757276650000006044820152606401610937565b614243826143c4565b6142a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f73486173685769746e657373206973206e6f74206f6e206375727665000000006044820152606401610937565b6142b5878a888761451f565b61431b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f6164647228632a706b2b732a6729213d5f755769746e657373000000000000006044820152606401610937565b60006143278a876146c2565b9050600061433a898b878b868989614726565b9050600061434b838d8d8a866148ae565b9050808a146143b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f696e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610937565b505050505050505050505050565b80516000907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f11614451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e76616c696420782d6f7264696e61746500000000000000000000000000006044820152606401610937565b60208201517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f116144de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e76616c696420792d6f7264696e61746500000000000000000000000000006044820152606401610937565b60208201517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f9080096145188360005b602002015161490c565b1492915050565b600073ffffffffffffffffffffffffffffffffffffffff821661459e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f626164207769746e6573730000000000000000000000000000000000000000006044820152606401610937565b6020840151600090600116156145b557601c6145b8565b601b5b905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641418587600060200201510986517ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141918203925060009190890987516040805160008082526020820180845287905260ff88169282019290925260608101929092526080820183905291925060019060a0016020604051602081039080840390855afa15801561466f573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff9081169088161495505050505050949350505050565b6146ca61516d565b6146f7600184846040516020016146e3939291906158c2565b604051602081830303815290604052614964565b90505b614703816143c4565b612c6757805160408051602081019290925261471f91016146e3565b90506146fa565b61472e61516d565b825186517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f90819006910614156147c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e637400006044820152606401610937565b6147cc8789886149cd565b614832576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4669727374206d756c20636865636b206661696c6564000000000000000000006044820152606401610937565b61483d8486856149cd565b6148a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5365636f6e64206d756c20636865636b206661696c65640000000000000000006044820152606401610937565b613e4e868484614b5a565b6000600286868685876040516020016148cc96959493929190615850565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209695505050505050565b6000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80848509840990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f600782089392505050565b61496c61516d565b61497582614c89565b815261498a61498582600061450e565b614cde565b6020820181905260029006600114156149c8576020810180517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0390525b919050565b600082614a36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f7a65726f207363616c61720000000000000000000000000000000000000000006044820152606401610937565b83516020850151600090614a4c90600290615d1b565b15614a5857601c614a5b565b601b5b905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641418387096040805160008082526020820180845281905260ff86169282019290925260608101869052608081018390529192509060019060a0016020604051602081039080840390855afa158015614adb573d6000803e3d6000fd5b505050602060405103519050600086604051602001614afa919061583e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012073ffffffffffffffffffffffffffffffffffffffff92831692169190911498975050505050505050565b614b6261516d565b835160208086015185519186015160009384938493614b8393909190614d18565b919450925090507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f858209600114614c17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e765a206d75737420626520696e7665727365206f66207a000000000000006044820152606401610937565b60405180604001604052807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80614c5057614c50615d5e565b87860981526020017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8785099052979650505050505050565b805160208201205b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f81106149c857604080516020808201939093528151808203840181529082019091528051910120614c91565b6000612c67826002614d117ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f6001615bba565b901c614eae565b60008080600180827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f897ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f038808905060007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f038a0890506000614dc083838585614fa2565b9098509050614dd188828e88614ffa565b9098509050614de288828c87614ffa565b90985090506000614df58d878b85614ffa565b9098509050614e0688828686614fa2565b9098509050614e1788828e89614ffa565b9098509050818114614e9a577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f818a0998507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f82890997507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183099650614e9e565b8196505b5050505050509450945094915050565b600080614eb961518b565b6020808252818101819052604082015260608101859052608081018490527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f60a0820152614f056151a9565b60208160c08460057ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa925082614f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6269674d6f64457870206661696c7572652100000000000000000000000000006044820152606401610937565b5195945050505050565b6000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8487097ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8487099097909650945050505050565b600080807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f878509905060007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f87877ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f030990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183087ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f86890990999098509650505050505050565b82805482825590600052602060002090810192821561513f579160200282015b8281111561513f57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906150e5565b5061514b9291506151c7565b5090565b508054600082559060005260206000209081019061086891906151c7565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b8082111561514b57600081556001016151c8565b803573ffffffffffffffffffffffffffffffffffffffff811681146149c857600080fd5b8060408101831015612c6757600080fd5b600082601f83011261522257600080fd5b6040516040810181811067ffffffffffffffff8211171561524557615245615deb565b806040525080838560408601111561525c57600080fd5b60005b600281101561527e57813583526020928301929091019060010161525f565b509195945050505050565b600060a0828403121561529b57600080fd5b60405160a0810181811067ffffffffffffffff821117156152be576152be615deb565b6040529050806152cd83615353565b81526152db60208401615353565b60208201526152ec6040840161533f565b60408201526152fd6060840161533f565b606082015261530e608084016151dc565b60808201525092915050565b803561ffff811681146149c857600080fd5b803562ffffff811681146149c857600080fd5b803563ffffffff811681146149c857600080fd5b803567ffffffffffffffff811681146149c857600080fd5b805169ffffffffffffffffffff811681146149c857600080fd5b60006020828403121561539757600080fd5b613d4b826151dc565b600080606083850312156153b357600080fd5b6153bc836151dc565b91506153cb8460208501615200565b90509250929050565b600080600080606085870312156153ea57600080fd5b6153f3856151dc565b935060208501359250604085013567ffffffffffffffff8082111561541757600080fd5b818701915087601f83011261542b57600080fd5b81358181111561543a57600080fd5b88602082850101111561544c57600080fd5b95989497505060200194505050565b6000806040838503121561546e57600080fd5b615477836151dc565b915060208301356bffffffffffffffffffffffff8116811461549857600080fd5b809150509250929050565b6000604082840312156154b557600080fd5b613d4b8383615200565b6000604082840312156154d157600080fd5b613d4b8383615211565b6000602082840312156154ed57600080fd5b81518015158114613d4b57600080fd5b60006020828403121561550f57600080fd5b5051919050565b600080600080600060a0868803121561552e57600080fd5b8535945061553e60208701615353565b935061554c6040870161531a565b925061555a6060870161533f565b91506155686080870161533f565b90509295509295909350565b60008082840361024081121561558957600080fd5b6101a08082121561559957600080fd5b6155a1615b90565b91506155ad8686615211565b82526155bc8660408701615211565b60208301526080850135604083015260a0850135606083015260c085013560808301526155eb60e086016151dc565b60a08301526101006155ff87828801615211565b60c0840152615612876101408801615211565b60e0840152610180860135818401525081935061563186828701615289565b925050509250929050565b6000806000806000808688036101c081121561565757600080fd5b6156608861531a565b965061566e6020890161533f565b955061567c6040890161533f565b945061568a6060890161533f565b935060808801359250610120807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60830112156156c557600080fd5b6156cd615b90565b91506156db60a08a0161533f565b82526156e960c08a0161533f565b60208301526156fa60e08a0161533f565b604083015261010061570d818b0161533f565b606084015261571d828b0161533f565b608084015261572f6101408b0161532c565b60a08401526157416101608b0161532c565b60c08401526157536101808b0161532c565b60e08401526157656101a08b0161532c565b818401525050809150509295509295509295565b60006020828403121561578b57600080fd5b5035919050565b6000602082840312156157a457600080fd5b613d4b82615353565b600080604083850312156157c057600080fd5b6157c983615353565b91506153cb602084016151dc565b600080600080600060a086880312156157ef57600080fd5b6157f88661536b565b94506020860151935060408601519250606086015191506155686080870161536b565b8060005b6002811015610a5a57815184526020938401939091019060010161581f565b615848818361581b565b604001919050565b868152615860602082018761581b565b61586d606082018661581b565b61587a60a082018561581b565b61588760e082018461581b565b60609190911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166101208201526101340195945050505050565b8381526158d2602082018461581b565b606081019190915260800192915050565b60408101612c67828461581b565b600060208083528351808285015260005b8181101561591e57858101830151858201604001528201615902565b81811115615930576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b818110156159b557845183529383019391830191600101615999565b509098975050505050505050565b60006101c08201905061ffff8816825263ffffffff808816602084015280871660408401528086166060840152846080840152835481811660a0850152615a1760c08501838360201c1663ffffffff169052565b615a2e60e08501838360401c1663ffffffff169052565b615a466101008501838360601c1663ffffffff169052565b615a5e6101208501838360801c1663ffffffff169052565b62ffffff60a082901c811661014086015260b882901c811661016086015260d082901c1661018085015260e81c6101a090930192909252979650505050505050565b82815260608101613d4b602083018461581b565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015615af557845183529383019391830191600101615ad9565b5090979650505050505050565b6000608082016bffffffffffffffffffffffff87168352602067ffffffffffffffff87168185015273ffffffffffffffffffffffffffffffffffffffff80871660408601526080606086015282865180855260a087019150838801945060005b81811015615b80578551841683529484019491840191600101615b62565b50909a9950505050505050505050565b604051610120810167ffffffffffffffff81118282101715615bb457615bb4615deb565b60405290565b60008219821115615bcd57615bcd615d2f565b500190565b600067ffffffffffffffff808316818516808303821115615bf557615bf5615d2f565b01949350505050565b60006bffffffffffffffffffffffff808316818516808303821115615bf557615bf5615d2f565b600082615c3457615c34615d5e565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c7157615c71615d2f565b500290565b600082821015615c8857615c88615d2f565b500390565b60006bffffffffffffffffffffffff83811690831681811015615cb257615cb2615d2f565b039392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615cec57615cec615d2f565b5060010190565b600067ffffffffffffffff80831681811415615d1157615d11615d2f565b6001019392505050565b600082615d2a57615d2a615d5e565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a") - ctorArgs, err := utils.ABIEncode(`[{"type":"address"}, {"type":"address"}, {"type":"address"}]`, linkAddress, bhsAddress, linkEthFeed) + ctorArgs, err := evmutils.ABIEncode(`[{"type":"address"}, {"type":"address"}, {"type":"address"}]`, linkAddress, bhsAddress, linkEthFeed) require.NoError(t, err) bytecode = append(bytecode, ctorArgs...) nonce, err := backend.PendingNonceAt(ctx, neil.From) @@ -1175,7 +1177,7 @@ func TestVRFV2Integration_SingleConsumer_Wrapper(t *testing.T) { require.NoError(t, err) // Fund Subscription. - b, err := utils.ABIEncode(`[{"type":"uint64"}]`, wrapperSubID) + b, err := evmutils.ABIEncode(`[{"type":"uint64"}]`, wrapperSubID) require.NoError(t, err) _, err = uni.linkContract.TransferAndCall(uni.sergey, uni.rootContractAddress, assets.Ether(100).ToInt(), b) require.NoError(t, err) @@ -1257,7 +1259,7 @@ func TestVRFV2Integration_Wrapper_High_Gas(t *testing.T) { require.NoError(t, err) // Fund Subscription. - b, err := utils.ABIEncode(`[{"type":"uint64"}]`, wrapperSubID) + b, err := evmutils.ABIEncode(`[{"type":"uint64"}]`, wrapperSubID) require.NoError(t, err) _, err = uni.linkContract.TransferAndCall(uni.sergey, uni.rootContractAddress, assets.Ether(100).ToInt(), b) require.NoError(t, err) @@ -1483,8 +1485,13 @@ func registerProvingKeyHelper(t *testing.T, uni coordinatorV2UniverseCommon, coo // Register a proving key associated with the VRF job. p, err := vrfkey.PublicKey.Point() require.NoError(t, err) - _, err = coordinator.RegisterProvingKey( - uni.neil, uni.nallory.From, pair(secp256k1.Coordinates(p))) + if uni.rootContract.Version() == vrfcommon.V2Plus { + _, err = coordinator.RegisterProvingKey( + uni.neil, nil, pair(secp256k1.Coordinates(p))) + } else { + _, err = coordinator.RegisterProvingKey( + uni.neil, &uni.nallory.From, pair(secp256k1.Coordinates(p))) + } require.NoError(t, err) uni.backend.Commit() } @@ -1530,7 +1537,7 @@ func TestExternalOwnerConsumerExample(t *testing.T) { _, err = coordinator.CreateSubscription(owner) require.NoError(t, err) backend.Commit() - b, err := utils.ABIEncode(`[{"type":"uint64"}]`, uint64(1)) + b, err := evmutils.ABIEncode(`[{"type":"uint64"}]`, uint64(1)) require.NoError(t, err) _, err = linkContract.TransferAndCall(owner, coordinatorAddress, big.NewInt(0), b) require.NoError(t, err) @@ -1804,13 +1811,7 @@ func TestRequestCost(t *testing.T) { vrfkey, err := app.GetKeyStore().VRF().Create() require.NoError(t, err) - p, err := vrfkey.PublicKey.Point() - require.NoError(t, err) - _, err = uni.rootContract.RegisterProvingKey( - uni.neil, uni.neil.From, pair(secp256k1.Coordinates(p))) - require.NoError(t, err) - uni.backend.Commit() - + registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey) t.Run("non-proxied consumer", func(tt *testing.T) { carol := uni.vrfConsumers[0] carolContract := uni.consumerContracts[0] @@ -1913,18 +1914,10 @@ func TestFulfillmentCost(t *testing.T) { app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, cfg, uni.backend, key) require.NoError(t, app.Start(testutils.Context(t))) - var vrfkey vrfkey.KeyV2 - { - var err error - vrfkey, err = app.GetKeyStore().VRF().Create() - require.NoError(t, err) - p, err := vrfkey.PublicKey.Point() - require.NoError(t, err) - _, err = uni.rootContract.RegisterProvingKey( - uni.neil, uni.neil.From, pair(secp256k1.Coordinates(p))) - require.NoError(t, err) - uni.backend.Commit() - } + vrfkey, err := app.GetKeyStore().VRF().Create() + require.NoError(t, err) + registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey) + var ( nonProxiedConsumerGasEstimate uint64 proxiedConsumerGasEstimate uint64 @@ -2044,14 +2037,14 @@ func TestStartingCountsV1(t *testing.T) { require.NoError(t, err) b := time.Now() n1, n2, n3, n4 := evmtypes.Nonce(0), evmtypes.Nonce(1), evmtypes.Nonce(2), evmtypes.Nonce(3) - reqID := utils.PadByteToHash(0x10) + reqID := evmutils.PadByteToHash(0x10) m1 := txmgr.TxMeta{ RequestID: &reqID, } md1, err := json.Marshal(&m1) require.NoError(t, err) md1SQL := sqlutil.JSON(md1) - reqID2 := utils.PadByteToHash(0x11) + reqID2 := evmutils.PadByteToHash(0x11) m2 := txmgr.TxMeta{ RequestID: &reqID2, } @@ -2112,7 +2105,7 @@ func TestStartingCountsV1(t *testing.T) { // add unconfirmed txes unconfirmedTxes := []txmgr.Tx{} for i := int64(4); i < 6; i++ { - reqID3 := utils.PadByteToHash(0x12) + reqID3 := evmutils.PadByteToHash(0x12) md, err2 := json.Marshal(&txmgr.TxMeta{ RequestID: &reqID3, }) @@ -2146,7 +2139,7 @@ func TestStartingCountsV1(t *testing.T) { TxID: int64(i + 1), TxFee: gas.EvmFee{Legacy: assets.NewWeiI(100)}, SignedRawTx: []byte(`blah`), - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), BroadcastBeforeBlockNum: &broadcastBlock, State: txmgrtypes.TxAttemptBroadcast, CreatedAt: time.Now(), @@ -2159,7 +2152,7 @@ func TestStartingCountsV1(t *testing.T) { TxID: int64(i + 1 + len(confirmedTxes)), TxFee: gas.EvmFee{Legacy: assets.NewWeiI(100)}, SignedRawTx: []byte(`blah`), - Hash: utils.NewHash(), + Hash: evmutils.NewHash(), State: txmgrtypes.TxAttemptInProgress, CreatedAt: time.Now(), ChainSpecificFeeLimit: uint32(100), @@ -2177,7 +2170,7 @@ func TestStartingCountsV1(t *testing.T) { receipts := []evmtypes.Receipt{} for i := 0; i < 4; i++ { receipts = append(receipts, evmtypes.Receipt{ - BlockHash: utils.NewHash(), + BlockHash: evmutils.NewHash(), TxHash: txAttempts[i].Hash, BlockNumber: big.NewInt(broadcastBlock), TransactionIndex: 1, @@ -2191,9 +2184,9 @@ func TestStartingCountsV1(t *testing.T) { counts, err = listenerV1.GetStartingResponseCountsV1(testutils.Context(t)) require.NoError(t, err) assert.Equal(t, 3, len(counts)) - assert.Equal(t, uint64(1), counts[utils.PadByteToHash(0x10)]) - assert.Equal(t, uint64(2), counts[utils.PadByteToHash(0x11)]) - assert.Equal(t, uint64(2), counts[utils.PadByteToHash(0x12)]) + assert.Equal(t, uint64(1), counts[evmutils.PadByteToHash(0x10)]) + assert.Equal(t, uint64(2), counts[evmutils.PadByteToHash(0x11)]) + assert.Equal(t, uint64(2), counts[evmutils.PadByteToHash(0x12)]) countsV2, err := listenerV2.GetStartingResponseCountsV2(testutils.Context(t)) require.NoError(t, err) diff --git a/core/services/vrf/v2/listener_v2_log_processor.go b/core/services/vrf/v2/listener_v2_log_processor.go index 004ab4c4905..eebe9038c0c 100644 --- a/core/services/vrf/v2/listener_v2_log_processor.go +++ b/core/services/vrf/v2/listener_v2_log_processor.go @@ -20,6 +20,7 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -1182,7 +1183,13 @@ func (lsn *listenerV2) simulateFulfillment( res.err = errors.New("expected []uint8 final result") return res } - res.maxFee = utils.HexToBig(hexutil.Encode(b)[2:]) + + res.maxFee, err = hex.ParseBig(hexutil.Encode(b)[2:]) + if err != nil { + res.err = err + return res + } + for _, trr := range trrs { if trr.Task.Type() == pipeline.TaskTypeVRFV2 { m := trr.Result.Value.(map[string]interface{}) diff --git a/core/sessions/ldapauth/sync.go b/core/sessions/ldapauth/sync.go index 67f101b62a4..74c606a9684 100644 --- a/core/sessions/ldapauth/sync.go +++ b/core/sessions/ldapauth/sync.go @@ -9,11 +9,11 @@ import ( "github.com/jmoiron/sqlx" "github.com/lib/pq" + "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" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type LDAPServerStateSyncer struct { @@ -30,7 +30,7 @@ func NewLDAPServerStateSync( pgCfg pg.QConfig, config config.LDAP, lggr logger.Logger, -) utils.SleeperTask { +) *utils.SleeperTask { namedLogger := lggr.Named("LDAPServerStateSync") serverSync := LDAPServerStateSyncer{ q: pg.NewQ(db, namedLogger, pgCfg), diff --git a/core/sessions/localauth/reaper.go b/core/sessions/localauth/reaper.go index 77d1b1abef2..48112456418 100644 --- a/core/sessions/localauth/reaper.go +++ b/core/sessions/localauth/reaper.go @@ -4,9 +4,9 @@ import ( "database/sql" "time" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type sessionReaper struct { @@ -21,7 +21,7 @@ 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(db *sql.DB, config SessionReaperConfig, lggr logger.Logger) *utils.SleeperTask { return utils.NewSleeperTask(&sessionReaper{ db, config, diff --git a/core/store/migrate/migrations/0215_functions_subscriptions.sql b/core/store/migrate/migrations/0215_functions_subscriptions.sql new file mode 100644 index 00000000000..c3859d42f63 --- /dev/null +++ b/core/store/migrate/migrations/0215_functions_subscriptions.sql @@ -0,0 +1,19 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE functions_subscriptions( + router_contract_address bytea, + subscription_id bigint, + owner bytea CHECK (octet_length(owner) = 20) NOT NULL, + balance bigint, + blocked_balance bigint, + proposed_owner bytea, + consumers bytea[], + flags bytea, + PRIMARY KEY(router_contract_address, subscription_id) +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE IF EXISTS functions_subscriptions; +-- +goose StatementEnd diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go index e9dd25fa0f7..f2a40ff332a 100644 --- a/core/testdata/testspecs/v2_specs.go +++ b/core/testdata/testspecs/v2_specs.go @@ -9,9 +9,9 @@ import ( "github.com/google/uuid" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( diff --git a/core/utils/config/toml.go b/core/utils/config/toml.go deleted file mode 100644 index f51db76365e..00000000000 --- a/core/utils/config/toml.go +++ /dev/null @@ -1,22 +0,0 @@ -package config - -import ( - "errors" - "io" - - "github.com/pelletier/go-toml/v2" -) - -// DecodeTOML decodes toml from r in to v. -// Requires strict field matches and returns full toml.StrictMissingError details. -func DecodeTOML(r io.Reader, v any) error { - d := toml.NewDecoder(r).DisallowUnknownFields() - if err := d.Decode(v); err != nil { - var strict *toml.StrictMissingError - if errors.As(err, &strict) { - return errors.New(strict.String()) - } - return err - } - return nil -} diff --git a/core/utils/hash_helpers.go b/core/utils/hash_helpers.go deleted file mode 100644 index b0a284be716..00000000000 --- a/core/utils/hash_helpers.go +++ /dev/null @@ -1,24 +0,0 @@ -package utils - -import ( - "crypto/rand" - - "github.com/ethereum/go-ethereum/common" -) - -// NewHash return random Keccak256 -func NewHash() common.Hash { - b := make([]byte, 32) - _, err := rand.Read(b) - if err != nil { - panic(err) - } - return common.BytesToHash(b) -} - -// PadByteToHash returns a hash with zeros padded on the left of the given byte. -func PadByteToHash(b byte) common.Hash { - var h [32]byte - h[31] = b - return h -} diff --git a/core/utils/hash_helpers_test.go b/core/utils/hash_helpers_test.go deleted file mode 100644 index 8fc864dc407..00000000000 --- a/core/utils/hash_helpers_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package utils_test - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -func TestNewHash(t *testing.T) { - t.Parallel() - - h1 := utils.NewHash() - h2 := utils.NewHash() - assert.NotEqual(t, h1, h2) - assert.NotEqual(t, h1, common.HexToHash("0x0")) - assert.NotEqual(t, h2, common.HexToHash("0x0")) -} - -func TestPadByteToHash(t *testing.T) { - t.Parallel() - - h := utils.PadByteToHash(1) - assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000001", h.String()) -} diff --git a/core/utils/sleeper_task.go b/core/utils/sleeper_task.go deleted file mode 100644 index d84457e9325..00000000000 --- a/core/utils/sleeper_task.go +++ /dev/null @@ -1,129 +0,0 @@ -package utils - -import ( - "fmt" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -// SleeperTask represents a task that waits in the background to process some work. -type SleeperTask interface { - Stop() error - WakeUp() - WakeUpIfStarted() -} - -// Worker is a simple interface that represents some work to do repeatedly -type Worker interface { - Work() - Name() string -} - -type sleeperTask struct { - services.StateMachine - worker Worker - chQueue chan struct{} - chStop chan struct{} - chDone chan struct{} - chWorkDone chan struct{} -} - -// NewSleeperTask takes a worker and returns a SleeperTask. -// -// SleeperTask is guaranteed to call Work on the worker at least once for every -// WakeUp call. -// If the Worker is busy when WakeUp is called, the Worker will be called again -// immediately after it is finished. For this reason you should take care to -// make sure that Worker is idempotent. -// WakeUp does not block. -func NewSleeperTask(worker Worker) SleeperTask { - s := &sleeperTask{ - worker: worker, - chQueue: make(chan struct{}, 1), - chStop: make(chan struct{}), - chDone: make(chan struct{}), - chWorkDone: make(chan struct{}, 10), - } - - _ = s.StartOnce("SleeperTask-"+worker.Name(), func() error { - go s.workerLoop() - return nil - }) - - return s -} - -// Stop stops the SleeperTask -func (s *sleeperTask) Stop() error { - return s.StopOnce("SleeperTask-"+s.worker.Name(), func() error { - close(s.chStop) - select { - case <-s.chDone: - case <-time.After(15 * time.Second): - return fmt.Errorf("SleeperTask-%s took too long to stop", s.worker.Name()) - } - return nil - }) -} - -func (s *sleeperTask) WakeUpIfStarted() { - s.IfStarted(func() { - select { - case s.chQueue <- struct{}{}: - default: - } - }) -} - -// WakeUp wakes up the sleeper task, asking it to execute its Worker. -func (s *sleeperTask) WakeUp() { - if !s.IfStarted(func() { - select { - case s.chQueue <- struct{}{}: - default: - } - }) { - panic("cannot wake up stopped sleeper task") - } -} - -func (s *sleeperTask) workDone() { - select { - case s.chWorkDone <- struct{}{}: - default: - } -} - -// WorkDone isn't part of the SleeperTask interface, but can be -// useful in tests to assert that the work has been done. -func (s *sleeperTask) WorkDone() <-chan struct{} { - return s.chWorkDone -} - -func (s *sleeperTask) workerLoop() { - defer close(s.chDone) - - for { - select { - case <-s.chQueue: - s.worker.Work() - s.workDone() - case <-s.chStop: - return - } - } -} - -type sleeperTaskWorker struct { - name string - work func() -} - -// SleeperFuncTask returns a Worker to execute the given work function. -func SleeperFuncTask(work func(), name string) Worker { - return &sleeperTaskWorker{name: name, work: work} -} - -func (w *sleeperTaskWorker) Name() string { return w.name } -func (w *sleeperTaskWorker) Work() { w.work() } diff --git a/core/utils/sleeper_task_test.go b/core/utils/sleeper_task_test.go deleted file mode 100644 index 8c09350f523..00000000000 --- a/core/utils/sleeper_task_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package utils_test - -import ( - "sync/atomic" - "testing" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/utils" - - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" -) - -type countingWorker struct { - numJobsPerformed atomic.Int32 - delay time.Duration -} - -func (t *countingWorker) Name() string { - return "CountingWorker" -} - -func (t *countingWorker) Work() { - if t.delay != 0 { - time.Sleep(t.delay) - } - // Without an atomic, the race detector fails - t.numJobsPerformed.Add(1) -} - -func (t *countingWorker) getNumJobsPerformed() int { - return int(t.numJobsPerformed.Load()) -} - -func TestSleeperTask_WakeupAfterStopPanics(t *testing.T) { - t.Parallel() - - worker := &countingWorker{} - sleeper := utils.NewSleeperTask(worker) - - require.NoError(t, sleeper.Stop()) - - require.Panics(t, func() { - sleeper.WakeUp() - }) - gomega.NewWithT(t).Eventually(worker.getNumJobsPerformed).Should(gomega.Equal(0)) -} - -func TestSleeperTask_CallingStopTwiceFails(t *testing.T) { - t.Parallel() - - worker := &countingWorker{} - sleeper := utils.NewSleeperTask(worker) - require.NoError(t, sleeper.Stop()) - require.Error(t, sleeper.Stop()) -} - -func TestSleeperTask_WakeupPerformsWork(t *testing.T) { - t.Parallel() - - worker := &countingWorker{} - sleeper := utils.NewSleeperTask(worker) - - sleeper.WakeUp() - gomega.NewWithT(t).Eventually(worker.getNumJobsPerformed).Should(gomega.Equal(1)) - require.NoError(t, sleeper.Stop()) -} - -type controllableWorker struct { - countingWorker - awaitWorkStarted chan struct{} - allowResumeWork chan struct{} - ignoreSignals bool -} - -func (w *controllableWorker) Work() { - if !w.ignoreSignals { - w.awaitWorkStarted <- struct{}{} - <-w.allowResumeWork - } - w.countingWorker.Work() -} - -func TestSleeperTask_WakeupEnqueuesMaxTwice(t *testing.T) { - t.Parallel() - - worker := &controllableWorker{awaitWorkStarted: make(chan struct{}), allowResumeWork: make(chan struct{})} - sleeper := utils.NewSleeperTask(worker) - - sleeper.WakeUp() - <-worker.awaitWorkStarted - sleeper.WakeUp() - sleeper.WakeUp() - sleeper.WakeUp() - sleeper.WakeUp() - sleeper.WakeUp() - worker.ignoreSignals = true - worker.allowResumeWork <- struct{}{} - - gomega.NewWithT(t).Eventually(worker.getNumJobsPerformed).Should(gomega.Equal(2)) - gomega.NewWithT(t).Consistently(worker.getNumJobsPerformed).Should(gomega.BeNumerically("<", 3)) - require.NoError(t, sleeper.Stop()) -} - -func TestSleeperTask_StopWaitsUntilWorkFinishes(t *testing.T) { - t.Parallel() - - worker := &controllableWorker{awaitWorkStarted: make(chan struct{}), allowResumeWork: make(chan struct{})} - sleeper := utils.NewSleeperTask(worker) - - sleeper.WakeUp() - <-worker.awaitWorkStarted - require.Equal(t, 0, worker.getNumJobsPerformed()) - worker.allowResumeWork <- struct{}{} - - require.NoError(t, sleeper.Stop()) - require.Equal(t, worker.getNumJobsPerformed(), 1) -} diff --git a/core/utils/utils.go b/core/utils/utils.go index 4f3f9212337..78151517c62 100644 --- a/core/utils/utils.go +++ b/core/utils/utils.go @@ -2,6 +2,7 @@ package utils import ( + "bytes" "context" "crypto/ed25519" "crypto/rand" @@ -11,7 +12,6 @@ import ( "errors" "fmt" "math" - "math/big" mrand "math/rand" "sort" "strings" @@ -19,8 +19,6 @@ import ( "sync/atomic" "time" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/google/uuid" "github.com/jpillora/backoff" pkgerrors "github.com/pkg/errors" @@ -33,34 +31,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" ) -const ( - // DefaultSecretSize is the entropy in bytes to generate a base64 string of 64 characters. - DefaultSecretSize = 48 - // EVMWordByteLen the length of an EVM Word Byte - EVMWordByteLen = 32 -) - -// ZeroAddress is an address of all zeroes, otherwise in Ethereum as -// 0x0000000000000000000000000000000000000000 -var ZeroAddress = common.Address{} - -func RandomAddress() common.Address { - b := make([]byte, 20) - _, _ = rand.Read(b) // Assignment for errcheck. Only used in tests so we can ignore. - return common.BytesToAddress(b) -} - -func RandomBytes32() (r [32]byte) { - b := make([]byte, 32) - _, _ = rand.Read(b[:]) // Assignment for errcheck. Only used in tests so we can ignore. - copy(r[:], b) - return -} - -func Bytes32ToSlice(a [32]byte) (r []byte) { - r = append(r, a[:]...) - return -} +// DefaultSecretSize is the entropy in bytes to generate a base64 string of 64 characters. +const DefaultSecretSize = 48 func MustNewPeerID() string { pubKey, _, err := ed25519.GenerateKey(rand.Reader) @@ -74,22 +46,6 @@ func MustNewPeerID() string { return peerID.String() } -// EmptyHash is a hash of all zeroes, otherwise in Ethereum as -// 0x0000000000000000000000000000000000000000000000000000000000000000 -var EmptyHash = common.Hash{} - -// Uint256ToBytes is x represented as the bytes of a uint256 -func Uint256ToBytes(x *big.Int) (uint256 []byte, err error) { - if x.Cmp(MaxUint256) > 0 { - return nil, fmt.Errorf("too large to convert to uint256") - } - uint256 = common.LeftPadBytes(x.Bytes(), EVMWordByteLen) - if x.Cmp(big.NewInt(0).SetBytes(uint256)) != 0 { - panic("failed to round-trip uint256 back to source big.Int") - } - return uint256, err -} - // ISO8601UTC formats given time to ISO8601. func ISO8601UTC(t time.Time) string { return t.UTC().Format(time.RFC3339) @@ -125,29 +81,6 @@ func NewSecret(n int) string { return base64.StdEncoding.EncodeToString(b) } -// RemoveHexPrefix removes the prefix (0x) of a given hex string. -func RemoveHexPrefix(str string) string { - if HasHexPrefix(str) { - return str[2:] - } - return str -} - -// HasHexPrefix returns true if the string starts with 0x. -func HasHexPrefix(str string) bool { - return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') -} - -// IsEmptyAddress checks that the address is empty, synonymous with the zero -// account/address. No logs can come from this address, as there is no contract -// present there. -// -// See https://stackoverflow.com/questions/48219716/what-is-address0-in-solidity -// for the more info on the zero address. -func IsEmptyAddress(addr common.Address) bool { - return addr == ZeroAddress -} - // StringToHex converts a standard string to a hex encoded string. func StringToHex(in string) string { return AddHexPrefix(hex.EncodeToString([]byte(in))) @@ -171,82 +104,6 @@ func IsEmpty(bytes []byte) bool { return true } -// Sleeper interface is used for tasks that need to be done on some -// interval, excluding Cron, like reconnecting. -type Sleeper interface { - Reset() - Sleep() - After() time.Duration - Duration() time.Duration -} - -// BackoffSleeper is a sleeper that backs off on subsequent attempts. -type BackoffSleeper struct { - backoff.Backoff - beenRun atomic.Bool -} - -// NewBackoffSleeper returns a BackoffSleeper that is configured to -// sleep for 0 seconds initially, then backs off from 1 second minimum -// to 10 seconds maximum. -func NewBackoffSleeper() *BackoffSleeper { - return &BackoffSleeper{ - Backoff: backoff.Backoff{ - Min: 1 * time.Second, - Max: 10 * time.Second, - }, - } -} - -// Sleep waits for the given duration, incrementing the back off. -func (bs *BackoffSleeper) Sleep() { - if bs.beenRun.CompareAndSwap(false, true) { - return - } - time.Sleep(bs.Backoff.Duration()) -} - -// After returns the duration for the next stop, and increments the backoff. -func (bs *BackoffSleeper) After() time.Duration { - if bs.beenRun.CompareAndSwap(false, true) { - return 0 - } - return bs.Backoff.Duration() -} - -// Duration returns the current duration value. -func (bs *BackoffSleeper) Duration() time.Duration { - if !bs.beenRun.Load() { - return 0 - } - return bs.ForAttempt(bs.Attempt()) -} - -// Reset resets the backoff intervals. -func (bs *BackoffSleeper) Reset() { - bs.beenRun.Store(false) - bs.Backoff.Reset() -} - -// RetryWithBackoff retries the sleeper and backs off if not Done -func RetryWithBackoff(ctx context.Context, fn func() (retry bool)) { - sleeper := NewBackoffSleeper() - sleeper.Reset() - for { - retry := fn() - if !retry { - return - } - - select { - case <-ctx.Done(): - return - case <-time.After(sleeper.After()): - continue - } - } -} - // UnmarshalToMap takes an input json string and returns a map[string]interface i.e. a raw object func UnmarshalToMap(input string) (map[string]interface{}, error) { var output map[string]interface{} @@ -275,24 +132,6 @@ func CheckPasswordHash(password, hash string) bool { return err == nil } -// Keccak256 is a simplified interface for the legacy SHA3 implementation that -// Ethereum uses. -func Keccak256(in []byte) ([]byte, error) { - hash := sha3.NewLegacyKeccak256() - _, err := hash.Write(in) - return hash.Sum(nil), err -} - -func Keccak256Fixed(in []byte) [32]byte { - hash := sha3.NewLegacyKeccak256() - // Note this Keccak256 cannot error https://github.com/golang/crypto/blob/master/sha3/sha3.go#L126 - // if we start supporting hashing algos which do, we can change this API to include an error. - hash.Write(in) - var h [32]byte - copy(h[:], hash.Sum(nil)) - return h -} - // Sha256 returns a hexadecimal encoded string of a hashed input func Sha256(in string) (string, error) { hasher := sha3.New256() @@ -303,99 +142,6 @@ func Sha256(in string) (string, error) { return hex.EncodeToString(hasher.Sum(nil)), nil } -// EIP55CapitalizedAddress returns true iff possibleAddressString has the correct -// capitalization for an Ethereum address, per EIP 55 -func EIP55CapitalizedAddress(possibleAddressString string) bool { - if !HasHexPrefix(possibleAddressString) { - possibleAddressString = "0x" + possibleAddressString - } - EIP55Capitalized := common.HexToAddress(possibleAddressString).Hex() - return possibleAddressString == EIP55Capitalized -} - -// ParseEthereumAddress returns addressString as a go-ethereum Address, or an -// error if it's invalid, e.g. if EIP 55 capitalization check fails -func ParseEthereumAddress(addressString string) (common.Address, error) { - if !common.IsHexAddress(addressString) { - return common.Address{}, fmt.Errorf( - "not a valid Ethereum address: %s", addressString) - } - address := common.HexToAddress(addressString) - if !EIP55CapitalizedAddress(addressString) { - return common.Address{}, fmt.Errorf( - "%s treated as Ethereum address, but it has an invalid capitalization! "+ - "The correctly-capitalized address would be %s, but "+ - "check carefully before copying and pasting! ", - addressString, address.Hex()) - } - return address, nil -} - -// MustHash returns the keccak256 hash, or panics on failure. -func MustHash(in string) common.Hash { - out, err := Keccak256([]byte(in)) - if err != nil { - panic(err) - } - return common.BytesToHash(out) -} - -// JustError takes a tuple and returns the last entry, the error. -func JustError(_ interface{}, err error) error { - return err -} - -var zero = big.NewInt(0) - -// CheckUint256 returns an error if n is out of bounds for a uint256 -func CheckUint256(n *big.Int) error { - if n.Cmp(zero) < 0 || n.Cmp(MaxUint256) >= 0 { - return fmt.Errorf("number out of range for uint256") - } - return nil -} - -// HexToUint256 returns the uint256 represented by s, or an error if it doesn't -// represent one. -func HexToUint256(s string) (*big.Int, error) { - rawNum, err := hexutil.Decode(s) - if err != nil { - return nil, pkgerrors.Wrapf(err, "while parsing %s as hex: ", s) - } - rv := big.NewInt(0).SetBytes(rawNum) // can't be negative number - if err := CheckUint256(rv); err != nil { - return nil, err - } - return rv, nil -} - -// HexToBig parses the given hex string or panics if it is invalid. -func HexToBig(s string) *big.Int { - n, ok := new(big.Int).SetString(s, 16) - if !ok { - panic(fmt.Errorf(`failed to convert "%s" as hex to big.Int`, s)) - } - return n -} - -// Uint256ToBytes32 returns the bytes32 encoding of the big int provided -func Uint256ToBytes32(n *big.Int) []byte { - if n.BitLen() > 256 { - panic("vrf.uint256ToBytes32: too big to marshal to uint256") - } - return common.LeftPadBytes(n.Bytes(), 32) -} - -// WaitGroupChan creates a channel that closes when the provided sync.WaitGroup is done. -func WaitGroupChan(wg *sync.WaitGroup) <-chan struct{} { - chAwait := make(chan struct{}) - go func() { - defer close(chAwait) - wg.Wait() - }() - return chAwait -} - // WithCloseChan wraps a context so that it is canceled if the passed in channel is closed. // Deprecated: Call [services.StopChan.Ctx] directly func WithCloseChan(parentCtx context.Context, chStop chan struct{}) (context.Context, context.CancelFunc) { @@ -420,40 +166,6 @@ type StopChan = services.StopChan // Deprecated: use services.StopRChan type StopRChan = services.StopRChan -// DependentAwaiter contains Dependent funcs -type DependentAwaiter interface { - AwaitDependents() <-chan struct{} - AddDependents(n int) - DependentReady() -} - -type dependentAwaiter struct { - wg *sync.WaitGroup - ch <-chan struct{} -} - -// NewDependentAwaiter creates a new DependentAwaiter -func NewDependentAwaiter() DependentAwaiter { - return &dependentAwaiter{ - wg: &sync.WaitGroup{}, - } -} - -func (da *dependentAwaiter) AwaitDependents() <-chan struct{} { - if da.ch == nil { - da.ch = WaitGroupChan(da.wg) - } - return da.ch -} - -func (da *dependentAwaiter) AddDependents(n int) { - da.wg.Add(n) -} - -func (da *dependentAwaiter) DependentReady() { - da.wg.Done() -} - // BoundedQueue is a FIFO queue that discards older items when it reaches its capacity. type BoundedQueue[T any] struct { capacity int @@ -574,20 +286,6 @@ func (q *BoundedPriorityQueue[T]) Empty() bool { return true } -// WrapIfError decorates an error with the given message. It is intended to -// be used with `defer` statements, like so: -// -// func SomeFunction() (err error) { -// defer WrapIfError(&err, "error in SomeFunction:") -// -// ... -// } -func WrapIfError(err *error, msg string) { - if *err != nil { - *err = pkgerrors.Wrap(*err, msg) - } -} - // TickerBase is an interface for pausable tickers. type TickerBase interface { Resume() @@ -750,16 +448,6 @@ func (t *ResettableTimer) Reset(duration time.Duration) { t.timer = time.NewTimer(duration) } -// EVMBytesToUint64 converts -// a bytebuffer to uint64 -func EVMBytesToUint64(buf []byte) uint64 { - var result uint64 - for _, b := range buf { - result = result<<8 + uint64(b) - } - return result -} - var ( ErrAlreadyStopped = errors.New("already stopped") ErrCannotStopUnstarted = errors.New("cannot stop unstarted service") @@ -836,23 +524,9 @@ func BoxOutput(errorMsgTemplate string, errorMsgValues ...interface{}) string { "\n\n" } -// AllEqual returns true iff all the provided elements are equal to each other. -func AllEqual[T comparable](elems ...T) bool { - for i := 1; i < len(elems); i++ { - if elems[i] != elems[0] { - return false - } - } - return true -} - -// RandUint256 generates a random bigNum up to 2 ** 256 - 1 -func RandUint256() *big.Int { - n, err := rand.Int(rand.Reader, MaxUint256) - if err != nil { - panic(err) - } - return n +// ConcatBytes appends a bunch of byte arrays into a single byte array +func ConcatBytes(bufs ...[]byte) []byte { + return bytes.Join(bufs, []byte{}) } func LeftPadBitString(input string, length int) string { @@ -862,22 +536,6 @@ func LeftPadBitString(input string, length int) string { return strings.Repeat("0", length-len(input)) + input } -// TryParseHex parses the given hex string to bytes, -// it can return error if the hex string is invalid. -// Follows the semantic of ethereum's FromHex. -func TryParseHex(s string) (b []byte, err error) { - if !HasHexPrefix(s) { - err = errors.New("hex string must have 0x prefix") - } else { - s = s[2:] - if len(s)%2 == 1 { - s = "0" + s - } - b, err = hex.DecodeString(s) - } - return -} - // ErrorBuffer uses joinedErrors interface to join multiple errors into a single error. // This is useful to track the most recent N errors in a service and flush them as a single error. type ErrorBuffer struct { diff --git a/core/utils/utils_test.go b/core/utils/utils_test.go index e11c01a8e4f..c08983ff4b8 100644 --- a/core/utils/utils_test.go +++ b/core/utils/utils_test.go @@ -4,9 +4,6 @@ import ( "context" "encoding/hex" "fmt" - "math/big" - "strings" - "sync" "sync/atomic" "testing" "time" @@ -17,11 +14,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.uber.org/multierr" ) func TestUtils_NewBytes32ID(t *testing.T) { @@ -52,30 +46,6 @@ func TestUtils_NewSecret(t *testing.T) { } } -func TestUtils_IsEmptyAddress(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - addr common.Address - want bool - }{ - {"zero address", common.Address{}, true}, - {"non-zero address", testutils.NewAddress(), false}, - } - - for _, test := range tests { - test := test - - t.Run(test.name, func(t *testing.T) { - t.Parallel() - - actual := utils.IsEmptyAddress(test.addr) - assert.Equal(t, test.want, actual) - }) - } -} - func TestUtils_StringToHex(t *testing.T) { t.Parallel() @@ -99,26 +69,6 @@ func TestUtils_StringToHex(t *testing.T) { } } -func TestUtils_BackoffSleeper(t *testing.T) { - t.Parallel() - - bs := utils.NewBackoffSleeper() - assert.Equal(t, time.Duration(0), bs.Duration(), "should initially return immediately") - bs.Sleep() - - d := 1 * time.Nanosecond - bs.Min = d - bs.Factor = 2 - assert.Equal(t, d, bs.Duration()) - bs.Sleep() - - d2 := 2 * time.Nanosecond - assert.Equal(t, d2, bs.Duration()) - - bs.Reset() - assert.Equal(t, time.Duration(0), bs.Duration(), "should initially return immediately") -} - func TestUtils_DurationFromNow(t *testing.T) { t.Parallel() @@ -127,138 +77,6 @@ func TestUtils_DurationFromNow(t *testing.T) { assert.True(t, 0 < duration) } -func TestKeccak256(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - input string - want string - }{ - {"basic", "0xf00b", "0x2433bb36d5f9b14e4fea87c2d32d79abfe34e56808b891e471f4400fca2a336c"}, - {"long input", "0xf00b2433bb36d5f9b14e4fea87c2d32d79abfe34e56808b891e471f4400fca2a336c", "0x6b917c56ad7bea7d09132b9e1e29bb5d9aa7d32d067c638dfa886bbbf6874cdf"}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - input, err := hexutil.Decode(test.input) - assert.NoError(t, err) - result, err := utils.Keccak256(input) - assert.NoError(t, err) - - assert.Equal(t, test.want, hexutil.Encode(result)) - }) - } -} - -// From https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md#test-cases -var testAddresses = []string{ - "0x52908400098527886E0F7030069857D2E4169EE7", - "0x8617E340B3D01FA5F11F306F4090FD50E238070D", - "0xde709f2102306220921060314715629080e2fb77", - "0x27b1fdb04752bbc536007a920d24acb045561c26", - "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", - "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", - "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", - "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", -} - -func TestClient_EIP55CapitalizedAddress(t *testing.T) { - t.Parallel() - - valid := utils.EIP55CapitalizedAddress - for _, address := range testAddresses { - assert.True(t, valid(address)) - assert.False(t, valid(strings.ToLower(address)) && - valid(strings.ToUpper(address))) - } -} - -func TestClient_ParseEthereumAddress(t *testing.T) { - t.Parallel() - - parse := utils.ParseEthereumAddress - for _, address := range testAddresses { - a1, err := parse(address) - assert.NoError(t, err) - no0xPrefix := address[2:] - a2, err := parse(no0xPrefix) - assert.NoError(t, err) - assert.True(t, a1 == a2) - _, lowerErr := parse(strings.ToLower(address)) - _, upperErr := parse(strings.ToUpper(address)) - shouldBeError := multierr.Combine(lowerErr, upperErr) - assert.Error(t, shouldBeError) - assert.True(t, strings.Contains(shouldBeError.Error(), no0xPrefix)) - } - _, notHexErr := parse("0xCeci n'est pas une chaîne hexadécimale") - assert.Error(t, notHexErr) - _, tooLongErr := parse("0x0123456789abcdef0123456789abcdef0123456789abcdef") - assert.Error(t, tooLongErr) -} - -func TestWaitGroupChan(t *testing.T) { - t.Parallel() - - wg := &sync.WaitGroup{} - wg.Add(2) - - ch := utils.WaitGroupChan(wg) - - select { - case <-ch: - t.Fatal("should not fire immediately") - default: - } - - wg.Done() - - select { - case <-ch: - t.Fatal("should not fire until finished") - default: - } - - go func() { - time.Sleep(2 * time.Second) - wg.Done() - }() - - cltest.CallbackOrTimeout(t, "WaitGroupChan fires", func() { - <-ch - }, 5*time.Second) -} - -func TestDependentAwaiter(t *testing.T) { - t.Parallel() - - da := utils.NewDependentAwaiter() - da.AddDependents(2) - - select { - case <-da.AwaitDependents(): - t.Fatal("should not fire immediately") - default: - } - - da.DependentReady() - - select { - case <-da.AwaitDependents(): - t.Fatal("should not fire until finished") - default: - } - - go func() { - time.Sleep(2 * time.Second) - da.DependentReady() - }() - - cltest.CallbackOrTimeout(t, "dependents are now ready", func() { - <-da.AwaitDependents() - }, 5*time.Second) -} - func TestBoundedQueue(t *testing.T) { t.Parallel() @@ -351,17 +169,6 @@ func TestBoundedPriorityQueue(t *testing.T) { require.Zero(t, q.Take()) } -func TestEVMBytesToUint64(t *testing.T) { - t.Parallel() - - require.Equal(t, uint64(257), utils.EVMBytesToUint64([]byte{0x01, 0x01})) - require.Equal(t, uint64(257), utils.EVMBytesToUint64([]byte{0x00, 0x00, 0x01, 0x01})) - require.Equal(t, uint64(299140445700113), utils.EVMBytesToUint64([]byte{0x00, 0x01, 0x10, 0x11, 0x10, 0x01, 0x00, 0x11})) - - // overflows without erroring - require.Equal(t, uint64(17), utils.EVMBytesToUint64([]byte{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11})) -} - func Test_WithJitter(t *testing.T) { t.Parallel() @@ -374,14 +181,6 @@ func Test_WithJitter(t *testing.T) { } } -func TestAllEqual(t *testing.T) { - t.Parallel() - - require.False(t, utils.AllEqual(1, 2, 3, 4, 5)) - require.True(t, utils.AllEqual(1, 1, 1, 1, 1)) - require.False(t, utils.AllEqual(1, 1, 1, 2, 1, 1, 1)) -} - func TestIsEmpty(t *testing.T) { t.Parallel() @@ -424,26 +223,6 @@ func TestBoxOutput(t *testing.T) { assert.Equal(t, expected, output) } -func TestUint256ToBytes(t *testing.T) { - t.Parallel() - - v := big.NewInt(0).Sub(utils.MaxUint256, big.NewInt(1)) - uint256, err := utils.Uint256ToBytes(v) - assert.NoError(t, err) - - b32 := utils.Uint256ToBytes32(v) - assert.Equal(t, uint256, b32) - - large := big.NewInt(0).Add(utils.MaxUint256, big.NewInt(1)) - _, err = utils.Uint256ToBytes(large) - assert.Error(t, err, "too large to convert to uint256") - - negative := big.NewInt(-1) - assert.Panics(t, func() { - _, _ = utils.Uint256ToBytes(negative) - }, "failed to round-trip uint256 back to source big.Int") -} - func TestISO8601UTC(t *testing.T) { t.Parallel() @@ -461,32 +240,6 @@ func TestFormatJSON(t *testing.T) { assert.Equal(t, "\"{\\\"foo\\\":123}\"", string(formatted)) } -func TestRetryWithBackoff(t *testing.T) { - t.Parallel() - - var counter atomic.Int32 - ctx, cancel := context.WithCancel(testutils.Context(t)) - - utils.RetryWithBackoff(ctx, func() bool { - return false - }) - - retry := func() bool { - return counter.Add(1) < 3 - } - - go utils.RetryWithBackoff(ctx, retry) - - assert.Eventually(t, func() bool { - return counter.Load() == 3 - }, testutils.WaitTimeout(t), testutils.TestInterval) - - cancel() - - utils.RetryWithBackoff(ctx, retry) - assert.Equal(t, int32(4), counter.Load()) -} - func TestMustUnmarshalToMap(t *testing.T) { t.Parallel() @@ -516,42 +269,6 @@ func TestSha256(t *testing.T) { assert.Len(t, hash, 32) } -func TestCheckUint256(t *testing.T) { - t.Parallel() - - large := big.NewInt(0).Add(utils.MaxUint256, big.NewInt(1)) - err := utils.CheckUint256(large) - assert.Error(t, err, "number out of range for uint256") - - negative := big.NewInt(-123) - err = utils.CheckUint256(negative) - assert.Error(t, err, "number out of range for uint256") - - err = utils.CheckUint256(big.NewInt(123)) - assert.NoError(t, err) -} - -func TestRandUint256(t *testing.T) { - t.Parallel() - - for i := 0; i < 1000; i++ { - uint256 := utils.RandUint256() - assert.NoError(t, utils.CheckUint256(uint256)) - } -} - -func TestHexToUint256(t *testing.T) { - t.Parallel() - - b, err := utils.HexToUint256("0x00") - assert.NoError(t, err) - assert.Zero(t, b.Cmp(big.NewInt(0))) - - b, err = utils.HexToUint256("0xFFFFFFFF") - assert.NoError(t, err) - assert.Zero(t, b.Cmp(big.NewInt(4294967295))) -} - func TestWithCloseChan(t *testing.T) { t.Parallel() @@ -772,40 +489,6 @@ func TestCronTicker(t *testing.T) { assert.Equal(t, c, counter.Load()) } -func TestTryParseHex(t *testing.T) { - t.Parallel() - - t.Run("0x prefix missing", func(t *testing.T) { - t.Parallel() - - _, err := utils.TryParseHex("abcd") - assert.Error(t, err) - }) - - t.Run("wrong hex characters", func(t *testing.T) { - t.Parallel() - - _, err := utils.TryParseHex("0xabcdzzz") - assert.Error(t, err) - }) - - t.Run("valid hex string", func(t *testing.T) { - t.Parallel() - - b, err := utils.TryParseHex("0x1234") - assert.NoError(t, err) - assert.Equal(t, []byte{0x12, 0x34}, b) - }) - - t.Run("prepend odd length with zero", func(t *testing.T) { - t.Parallel() - - b, err := utils.TryParseHex("0x123") - assert.NoError(t, err) - assert.Equal(t, []byte{0x1, 0x23}, b) - }) -} - func TestErrorBuffer(t *testing.T) { t.Parallel() diff --git a/core/web/cosmos_keys_controller_test.go b/core/web/cosmos_keys_controller_test.go index af421416388..3b777de7b7c 100644 --- a/core/web/cosmos_keys_controller_test.go +++ b/core/web/cosmos_keys_controller_test.go @@ -5,10 +5,10 @@ import ( "net/http" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" diff --git a/core/web/dkgencrypt_keys_controller_test.go b/core/web/dkgencrypt_keys_controller_test.go index 41d7eb4a752..7100cbbb1cd 100644 --- a/core/web/dkgencrypt_keys_controller_test.go +++ b/core/web/dkgencrypt_keys_controller_test.go @@ -8,10 +8,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/web/dkgsign_keys_controller_test.go b/core/web/dkgsign_keys_controller_test.go index 611c5b3ef0a..ed67d71a0d5 100644 --- a/core/web/dkgsign_keys_controller_test.go +++ b/core/web/dkgsign_keys_controller_test.go @@ -8,10 +8,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go index d0ad27262f2..739af5820c9 100644 --- a/core/web/eth_keys_controller_test.go +++ b/core/web/eth_keys_controller_test.go @@ -16,6 +16,7 @@ import ( "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/evmtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" webpresenters "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -411,10 +412,12 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { }) assert.NoError(t, err) - var count int - err = app.GetSqlxDB().Get(&count, `SELECT count(*) FROM evm.txes WHERE from_address = $1 AND state = 'fatal_error'`, addr) + db := app.GetSqlxDB() + txStore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg.Database()) + + txes, err := txStore.FindTxesByFromAddressAndState(testutils.Context(t), addr, "fatal_error") require.NoError(t, err) - assert.Equal(t, 0, count) + require.Len(t, txes, 0) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -437,10 +440,12 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { assert.Equal(t, cltest.FixtureChainID.String(), updatedKey.EVMChainID.String()) assert.Equal(t, false, updatedKey.Disabled) - var s string - err = app.GetSqlxDB().Get(&s, `SELECT error FROM evm.txes WHERE from_address = $1 AND state = 'fatal_error'`, addr) + txes, err = txStore.FindTxesByFromAddressAndState(testutils.Context(t), addr, "fatal_error") require.NoError(t, err) - assert.Equal(t, "abandoned", s) + require.Len(t, txes, 1) + + tx := txes[0] + assert.Equal(t, "abandoned", tx.Error.String) } func TestETHKeysController_ChainFailure_InvalidAbandon(t *testing.T) { diff --git a/core/web/evm_forwarders_controller_test.go b/core/web/evm_forwarders_controller_test.go index 49671157cbd..031a1a61c03 100644 --- a/core/web/evm_forwarders_controller_test.go +++ b/core/web/evm_forwarders_controller_test.go @@ -11,12 +11,12 @@ import ( "github.com/stretchr/testify/require" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "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/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/web/evm_transfer_controller.go b/core/web/evm_transfer_controller.go index 6ab621661a6..4a1bf46feea 100644 --- a/core/web/evm_transfer_controller.go +++ b/core/web/evm_transfer_controller.go @@ -13,11 +13,11 @@ import ( commontxmgr "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" "github.com/gin-gonic/gin" diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index dd083a8cd63..cff996dd21c 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -10,6 +10,8 @@ import ( "testing" "time" + "github.com/jmoiron/sqlx" + "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" @@ -18,6 +20,8 @@ import ( "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/evmtest" + "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/store/models" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -68,7 +72,7 @@ func TestTransfersController_CreateSuccess_From(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - cltest.AssertCount(t, app.GetSqlxDB(), "evm.txes", 1) + validateTxCount(t, app.GetSqlxDB(), 1) } func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { @@ -109,7 +113,7 @@ func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - cltest.AssertCount(t, app.GetSqlxDB(), "evm.txes", 1) + validateTxCount(t, app.GetSqlxDB(), 1) } func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testing.T) { @@ -155,7 +159,7 @@ func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testin assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - cltest.AssertCount(t, app.GetSqlxDB(), "evm.txes", 1) + validateTxCount(t, app.GetSqlxDB(), 1) } func TestTransfersController_TransferZeroAddressError(t *testing.T) { @@ -323,7 +327,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { err = web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource) assert.NoError(t, err) - cltest.AssertCount(t, app.GetSqlxDB(), "evm.txes", 1) + validateTxCount(t, app.GetSqlxDB(), 1) // check returned data assert.NotEmpty(t, resource.Hash) @@ -393,3 +397,12 @@ func TestTransfersController_FindTxAttempt(t *testing.T) { assert.ErrorContains(t, err, "context canceled") }) } + +func validateTxCount(t *testing.T, db *sqlx.DB, count int) { + cfg := pgtest.NewQConfig(false) + txStore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg) + + txes, err := txStore.GetAllTxes(testutils.Context(t)) + require.NoError(t, err) + require.Len(t, txes, count) +} diff --git a/core/web/health_controller.go b/core/web/health_controller.go index d6490e5542a..7ab07291b58 100644 --- a/core/web/health_controller.go +++ b/core/web/health_controller.go @@ -1,12 +1,15 @@ package web import ( - "cmp" + "bytes" + "fmt" + "io" "net/http" "slices" - "testing" + "strings" "github.com/gin-gonic/gin" + "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -73,13 +76,12 @@ func (hc *HealthController) Health(c *gin.Context) { healthy, errors := checker.IsHealthy() if !healthy { - status = http.StatusServiceUnavailable + status = http.StatusMultiStatus } c.Status(status) checks := make([]presenters.Check, 0, len(errors)) - for name, err := range errors { status := HealthStatusPassing var output string @@ -97,12 +99,188 @@ func (hc *HealthController) Health(c *gin.Context) { }) } - if testing.Testing() { - slices.SortFunc(checks, func(a, b presenters.Check) int { - return cmp.Compare(a.Name, b.Name) - }) + switch c.NegotiateFormat(gin.MIMEJSON, gin.MIMEHTML, gin.MIMEPlain) { + case gin.MIMEJSON: + break // default + + case gin.MIMEHTML: + if err := newCheckTree(checks).WriteHTMLTo(c.Writer); err != nil { + hc.App.GetLogger().Errorw("Failed to write HTML health report", "err", err) + c.AbortWithStatus(http.StatusInternalServerError) + } + return + + case gin.MIMEPlain: + if err := writeTextTo(c.Writer, checks); err != nil { + hc.App.GetLogger().Errorw("Failed to write plaintext health report", "err", err) + c.AbortWithStatus(http.StatusInternalServerError) + } + return } - // return a json description of all the checks + slices.SortFunc(checks, presenters.CmpCheckName) jsonAPIResponseWithStatus(c, checks, "checks", status) } + +func writeTextTo(w io.Writer, checks []presenters.Check) error { + slices.SortFunc(checks, presenters.CmpCheckName) + for _, ch := range checks { + status := "?" + switch ch.Status { + case HealthStatusPassing: + status = "-" + case HealthStatusFailing: + status = "!" + } + if _, err := fmt.Fprintf(w, "%s%s\n", status, ch.Name); err != nil { + return err + } + if ch.Output != "" { + if _, err := fmt.Fprintf(newLinePrefixWriter(w, "\t"), "\t%s", ch.Output); err != nil { + return err + } + if _, err := fmt.Fprintln(w); err != nil { + return err + } + } + } + return nil +} + +type checkNode struct { + Name string // full + Status string + Output string + + Subs checkTree +} + +type checkTree map[string]checkNode + +func newCheckTree(checks []presenters.Check) checkTree { + slices.SortFunc(checks, presenters.CmpCheckName) + root := make(checkTree) + for _, c := range checks { + parts := strings.Split(c.Name, ".") + node := root + for _, short := range parts[:len(parts)-1] { + n, ok := node[short] + if !ok { + n = checkNode{Subs: make(checkTree)} + node[short] = n + } + node = n.Subs + } + p := parts[len(parts)-1] + node[p] = checkNode{ + Name: c.Name, + Status: c.Status, + Output: c.Output, + Subs: make(checkTree), + } + } + return root +} + +func (t checkTree) WriteHTMLTo(w io.Writer) error { + if _, err := io.WriteString(w, ``); err != nil { + return err + } + return t.writeHTMLTo(newLinePrefixWriter(w, "")) +} + +func (t checkTree) writeHTMLTo(w *linePrefixWriter) error { + keys := maps.Keys(t) + slices.Sort(keys) + for _, short := range keys { + node := t[short] + if _, err := io.WriteString(w, ` +
`); err != nil { + return err + } + var expand string + if node.Output == "" && len(node.Subs) == 0 { + expand = ` class="noexpand"` + } + if _, err := fmt.Fprintf(w, ` + %s`, node.Name, expand, node.Status, short); err != nil { + return err + } + if node.Output != "" { + if _, err := w.WriteRawLinef("
%s
", node.Output); err != nil { + return err + } + } + if len(node.Subs) > 0 { + if err := node.Subs.writeHTMLTo(w.new(" ")); err != nil { + return err + } + } + if _, err := io.WriteString(w, "\n
"); err != nil { + return err + } + } + return nil +} + +type linePrefixWriter struct { + w io.Writer + prefix string + prefixB []byte +} + +func newLinePrefixWriter(w io.Writer, prefix string) *linePrefixWriter { + prefix = "\n" + prefix + return &linePrefixWriter{w: w, prefix: prefix, prefixB: []byte(prefix)} +} + +func (w *linePrefixWriter) new(prefix string) *linePrefixWriter { + prefix = w.prefix + prefix + return &linePrefixWriter{w: w.w, prefix: prefix, prefixB: []byte(prefix)} +} + +func (w *linePrefixWriter) Write(b []byte) (int, error) { + return w.w.Write(bytes.ReplaceAll(b, []byte("\n"), w.prefixB)) +} + +func (w *linePrefixWriter) WriteString(s string) (n int, err error) { + return io.WriteString(w.w, strings.ReplaceAll(s, "\n", w.prefix)) +} + +// WriteRawLinef writes a new newline with prefix, followed by s without modification. +func (w *linePrefixWriter) WriteRawLinef(s string, args ...any) (n int, err error) { + return fmt.Fprintf(w.w, w.prefix+s, args...) +} diff --git a/core/web/health_controller_test.go b/core/web/health_controller_test.go index 7e7c42141ca..547186e33fb 100644 --- a/core/web/health_controller_test.go +++ b/core/web/health_controller_test.go @@ -8,6 +8,7 @@ import ( "net/http" "testing" + "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -61,7 +62,7 @@ func TestHealthController_Health_status(t *testing.T) { { name: "not ready", ready: false, - status: http.StatusServiceUnavailable, + status: http.StatusMultiStatus, }, { name: "ready", @@ -90,24 +91,43 @@ func TestHealthController_Health_status(t *testing.T) { var ( //go:embed testdata/body/health.json - healthJSON string + bodyJSON string + //go:embed testdata/body/health.html + bodyHTML string + //go:embed testdata/body/health.txt + bodyTXT string ) func TestHealthController_Health_body(t *testing.T) { - app := cltest.NewApplicationWithKey(t) - require.NoError(t, app.Start(testutils.Context(t))) - - client := app.NewHTTPClient(nil) - resp, cleanup := client.Get("/health") - t.Cleanup(cleanup) - assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - - // pretty print for comparison - var b bytes.Buffer - require.NoError(t, json.Indent(&b, body, "", " ")) - body = b.Bytes() + for _, tc := range []struct { + name string + path string + headers map[string]string + expBody string + }{ + {"default", "/health", nil, bodyJSON}, + {"json", "/health", map[string]string{"Accept": gin.MIMEJSON}, bodyJSON}, + {"html", "/health", map[string]string{"Accept": gin.MIMEHTML}, bodyHTML}, + {"text", "/health", map[string]string{"Accept": gin.MIMEPlain}, bodyTXT}, + {".txt", "/health.txt", nil, bodyTXT}, + } { + t.Run(tc.name, func(t *testing.T) { + app := cltest.NewApplicationWithKey(t) + require.NoError(t, app.Start(testutils.Context(t))) - assert.Equal(t, healthJSON, string(body)) + client := app.NewHTTPClient(nil) + resp, cleanup := client.Get(tc.path, tc.headers) + t.Cleanup(cleanup) + assert.Equal(t, http.StatusMultiStatus, resp.StatusCode) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + if tc.expBody == bodyJSON { + // pretty print for comparison + var b bytes.Buffer + require.NoError(t, json.Indent(&b, body, "", " ")) + body = b.Bytes() + } + assert.Equal(t, tc.expBody, string(body)) + }) + } } diff --git a/core/web/health_template_test.go b/core/web/health_template_test.go new file mode 100644 index 00000000000..fa9750fed22 --- /dev/null +++ b/core/web/health_template_test.go @@ -0,0 +1,53 @@ +package web + +import ( + "bytes" + _ "embed" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +var ( + //go:embed testdata/health.html + healthHTML string + + //go:embed testdata/health.txt + healthTXT string +) + +func checks() []presenters.Check { + const passing, failing = HealthStatusPassing, HealthStatusFailing + return []presenters.Check{ + {Name: "foo", Status: passing}, + {Name: "foo.bar", Status: failing, Output: "example error message"}, + {Name: "foo.bar.1", Status: passing}, + {Name: "foo.bar.1.A", Status: passing}, + {Name: "foo.bar.1.B", Status: passing}, + {Name: "foo.bar.2", Status: failing, Output: `error: +this is a multi-line error: +new line: +original error`}, + {Name: "foo.bar.2.A", Status: failing, Output: "failure!"}, + {Name: "foo.bar.2.B", Status: passing}, + {Name: "foo.baz", Status: passing}, + } + //TODO truncated error +} + +func Test_checkTree_WriteHTMLTo(t *testing.T) { + ct := newCheckTree(checks()) + var b bytes.Buffer + require.NoError(t, ct.WriteHTMLTo(&b)) + got := b.String() + require.Equalf(t, healthHTML, got, "got: %s", got) +} + +func Test_writeTextTo(t *testing.T) { + var b bytes.Buffer + require.NoError(t, writeTextTo(&b, checks())) + got := b.String() + require.Equalf(t, healthTXT, got, "got: %s", got) +} diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 27d4433b63c..0a40c8a9c71 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -26,6 +26,7 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -37,7 +38,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/tomlutils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go index cbd73a575a9..a039834997e 100644 --- a/core/web/loader/loader_test.go +++ b/core/web/loader/loader_test.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtxmgrmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" coremocks "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -27,7 +28,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" jobORMMocks "github.com/smartcontractkit/chainlink/v2/core/services/job/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestLoader_Chains(t *testing.T) { diff --git a/core/web/ocr2_keys_controller_test.go b/core/web/ocr2_keys_controller_test.go index c7549cd2da5..815ae3ac20b 100644 --- a/core/web/ocr2_keys_controller_test.go +++ b/core/web/ocr2_keys_controller_test.go @@ -5,11 +5,11 @@ import ( "net/http" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" diff --git a/core/web/ocr_keys_controller_test.go b/core/web/ocr_keys_controller_test.go index ebb671bc1e2..31422f47c0c 100644 --- a/core/web/ocr_keys_controller_test.go +++ b/core/web/ocr_keys_controller_test.go @@ -4,10 +4,10 @@ import ( "net/http" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" diff --git a/core/web/p2p_keys_controller_test.go b/core/web/p2p_keys_controller_test.go index af15e21a0f6..df6f556fcb8 100644 --- a/core/web/p2p_keys_controller_test.go +++ b/core/web/p2p_keys_controller_test.go @@ -5,11 +5,11 @@ import ( "net/http" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" diff --git a/core/web/presenters/check.go b/core/web/presenters/check.go index 52e4aa68005..4e1a2147a8c 100644 --- a/core/web/presenters/check.go +++ b/core/web/presenters/check.go @@ -1,5 +1,7 @@ package presenters +import "cmp" + type Check struct { JAID Name string `json:"name"` @@ -10,3 +12,7 @@ type Check struct { func (c Check) GetName() string { return "checks" } + +func CmpCheckName(a, b Check) int { + return cmp.Compare(a.Name, b.Name) +} diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index 9efad05c03a..cc4dddcf8af 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -227,3 +227,6 @@ TLSCertPath = '' LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' + +[Mercury.TLS] +CertFile = '' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 45504d62596..957ffdc968e 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -238,6 +238,9 @@ LatestReportTTL = '1m40s' MaxStaleAge = '1m41s' LatestReportDeadline = '1m42s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' Enabled = false diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 40c18f28eb9..d5352a685c4 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -228,6 +228,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/core/web/router.go b/core/web/router.go index 28bd4f2170c..5c5e86a12b6 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -215,6 +215,9 @@ func healthRoutes(app chainlink.Application, r *gin.RouterGroup) { hc := HealthController{app} r.GET("/readyz", hc.Readyz) r.GET("/health", hc.Health) + r.GET("/health.txt", func(context *gin.Context) { + context.Request.Header.Set("Accept", gin.MIMEPlain) + }, hc.Health) } func loopRoutes(app chainlink.Application, r *gin.RouterGroup) { diff --git a/core/web/solana_keys_controller_test.go b/core/web/solana_keys_controller_test.go index 3dfbcfd252a..94b11207c92 100644 --- a/core/web/solana_keys_controller_test.go +++ b/core/web/solana_keys_controller_test.go @@ -5,10 +5,10 @@ import ( "net/http" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" diff --git a/core/web/starknet_keys_controller_test.go b/core/web/starknet_keys_controller_test.go index a633b4f16c9..9215fb8f9c5 100644 --- a/core/web/starknet_keys_controller_test.go +++ b/core/web/starknet_keys_controller_test.go @@ -5,10 +5,10 @@ import ( "net/http" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" diff --git a/core/web/testdata/body/health.html b/core/web/testdata/body/health.html new file mode 100644 index 00000000000..d1b208f4a0d --- /dev/null +++ b/core/web/testdata/body/health.html @@ -0,0 +1,101 @@ + +
+ EVM +
+ 0 +
+ BalanceMonitor +
+
+ HeadBroadcaster +
+
+ HeadTracker +
+ HeadListener +
Listener is not connected
+
+
+
+ LogBroadcaster +
+
+ Txm +
+ BlockHistoryEstimator +
+
+ Broadcaster +
+
+ Confirmer +
+
+ WrappedEvmEstimator +
+
+
+
+
+ JobSpawner +
+
+ Mailbox +
+ Monitor +
+
+
+ Mercury +
+ WSRPCPool +
+ CacheSet +
+
+
+
+ PipelineORM +
+
+ PipelineRunner +
+
+ PromReporter +
+
+ TelemetryManager +
\ No newline at end of file diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json index d8418560543..3c0117de7ec 100644 --- a/core/web/testdata/body/health.json +++ b/core/web/testdata/body/health.json @@ -108,6 +108,15 @@ "output": "" } }, + { + "type": "checks", + "id": "Mailbox.Monitor", + "attributes": { + "name": "Mailbox.Monitor", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "Mercury.WSRPCPool", @@ -119,9 +128,9 @@ }, { "type": "checks", - "id": "Monitor", + "id": "Mercury.WSRPCPool.CacheSet", "attributes": { - "name": "Monitor", + "name": "Mercury.WSRPCPool.CacheSet", "status": "passing", "output": "" } diff --git a/core/web/testdata/body/health.txt b/core/web/testdata/body/health.txt new file mode 100644 index 00000000000..59f63c26413 --- /dev/null +++ b/core/web/testdata/body/health.txt @@ -0,0 +1,20 @@ +-EVM.0 +-EVM.0.BalanceMonitor +-EVM.0.HeadBroadcaster +-EVM.0.HeadTracker +!EVM.0.HeadTracker.HeadListener + Listener is not connected +-EVM.0.LogBroadcaster +-EVM.0.Txm +-EVM.0.Txm.BlockHistoryEstimator +-EVM.0.Txm.Broadcaster +-EVM.0.Txm.Confirmer +-EVM.0.Txm.WrappedEvmEstimator +-JobSpawner +-Mailbox.Monitor +-Mercury.WSRPCPool +-Mercury.WSRPCPool.CacheSet +-PipelineORM +-PipelineRunner +-PromReporter +-TelemetryManager diff --git a/core/web/testdata/health.html b/core/web/testdata/health.html new file mode 100644 index 00000000000..3c007bef96f --- /dev/null +++ b/core/web/testdata/health.html @@ -0,0 +1,67 @@ + +
+ foo +
+ bar +
example error message
+
+ 1 +
+ A +
+
+ B +
+
+
+ 2 +
error:
+this is a multi-line error:
+new line:
+original error
+
+ A +
failure!
+
+
+ B +
+
+
+
+ baz +
+
\ No newline at end of file diff --git a/core/web/testdata/health.txt b/core/web/testdata/health.txt new file mode 100644 index 00000000000..f155d6c0212 --- /dev/null +++ b/core/web/testdata/health.txt @@ -0,0 +1,15 @@ +-foo +!foo.bar + example error message +-foo.bar.1 +-foo.bar.1.A +-foo.bar.1.B +!foo.bar.2 + error: + this is a multi-line error: + new line: + original error +!foo.bar.2.A + failure! +-foo.bar.2.B +-foo.baz diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 62236558c4c..2ba80927256 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,7 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [dev] -... +### Added + +- `chainlink health` CLI command and HTML `/health` endpoint, to provide human-readable views of the underlying JSON health data. + +### Fixed + +- Fixed the encoding used for transactions when resending in batches ## 2.8.0 - UNRELEASED @@ -58,7 +64,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Two new prom metrics for mercury, nops should consider adding alerting on these: - `mercury_insufficient_blocks_count` - `mercury_zero_blocks_count` - +- Added new `Mercury.TLS` TOML config field `CertFile` for configuring transport credentials when the node acts as a client and initiates a TLS handshake. + ### Changed - `PromReporter` no longer directly reads txm related status from the db, and instead uses the txStore API. diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 2bb32b58252..421b0ea9dad 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1589,6 +1589,19 @@ LatestReportDeadline = "5s" # Default LatestReportDeadline controls how long to wait for a response from the mercury server before retrying. Setting this to zero will wait indefinitely. +## Mercury.TLS +```toml +[Mercury.TLS] +CertFile = "/path/to/client/certs.pem" # Example +``` +Mercury.TLS controls client settings for when the node talks to traditional web servers or load balancers. + +### CertFile +```toml +CertFile = "/path/to/client/certs.pem" # Example +``` +CertFile is the path to a PEM file of trusted root certificate authority certificates + ## EVM EVM defaults depend on ChainID: diff --git a/docs/Mercury.md b/docs/Mercury.md new file mode 100644 index 00000000000..610605ddbc6 --- /dev/null +++ b/docs/Mercury.md @@ -0,0 +1,350 @@ +# Mercury Documentation + +## Contracts + +Use this tool to configure contracts: + +https://github.com/smartcontractkit/the-most-amazing-mercury-contract-configuration-tool + +TODO: updated process here @Austin Born + +[Reference contract](https://github.com/smartcontractkit/reference-data-directory/blob/master/ethereum-testnet-goerli-arbitrum-1/contracts/0x535051166466D159da8742167c9CA1eFe9e82613.json) + +[OCR2 config documentation](https://github.com/smartcontractkit/libocr/blob/master/offchainreporting2/internal/config/public_config.go) + +**🚨 Important config** + +`s` - transmission schedule. This should be set to the number of oracles on the feed - meaning that every oracle will attempt to transmit to the mercury server in the first stage of transmission. eg `[4]` if there are 4 node in the DON, excluding the bootstrap node. + +`f` - set this to `n//3` (where `//` denotes integer division), e.g. if you have 16 oracles, set `f` to 5. + +`deltaRound` - report generation frequency. This determines how frequently a new round should be started at most (if rounds take longer than this due to network latency, there will be fewer rounds per second than this parameter would suggest). `100ms` is a good starting point (10 rounds/s). + +`reportingPluginConfig.alphaAccept` - set this to `0`, because our mercury ContractTransmitter doesn't know the latest report that's been sent to the mercury server and we therefore always have a "pending" report which we compare against before accepting a report for transmission. + +`reportingPluginConfig.deltaC` - set this to `0` so every round will result in a report. + +
Example `verifier/<0xaddress>.json` + +```json +{ + "contractVersion": 1001, + "digests": { + "0x0006c67c0374ab0dcfa45c63b37df2ea8d16fb903c043caa98065033e9c15666": { + "feedId": "0x14e044f932bb959cc2aa8dc1ba110c09224e639aae00264c1ffc2a0830904a3c", + "proxyEnabled": true, + "status": "active" + } + }, + "feeds": { + "0x14e044f932bb959cc2aa8dc1ba110c09224e639aae00264c1ffc2a0830904a3c": { + "digests": [ + "0x0006c67c0374ab0dcfa45c63b37df2ea8d16fb903c043caa98065033e9c15666" + ], + "docs": { + "assetName": "Chainlink", + "feedCategory": "verified", + "feedType": "Crypto", + "hidden": true + }, + "externalAdapterRequestParams": { + "endpoint": "cryptolwba", + "from": "LINK", + "to": "USD" + }, + "feedId": "0x14e044f932bb959cc2aa8dc1ba110c09224e639aae00264c1ffc2a0830904a3c", + "latestConfig": { + "offchainConfig": { + "deltaGrace": "0", + "deltaProgress": "2s", + "deltaResend": "20s", + "deltaRound": "250ms", + "deltaStage": "60s", + "f": 1, + "maxDurationObservation": "250ms", + "maxDurationQuery": "0s", + "maxDurationReport": "250ms", + "maxDurationShouldAcceptFinalizedReport": "250ms", + "maxDurationShouldTransmitAcceptedReport": "250ms", + "rMax": 100, + "reportingPluginConfig": { + "alphaAcceptInfinite": false, + "alphaAcceptPpb": "0", + "alphaReportInfinite": false, + "alphaReportPpb": "0", + "deltaC": "0s" + }, + "s": [ + 4 + ] + }, + "offchainConfigVersion": 30, + "onchainConfig": { + "max": "99999999999999999999999999999", + "min": "1" + }, + "onchainConfigVersion": 1, + "oracles": [ + { + "api": [ + "coinmetrics", + "ncfx", + "tiingo-test" + ], + "operator": "clc-ocr-mercury-arbitrum-goerli-nodes-0" + }, + { + "api": [ + "coinmetrics", + "ncfx", + "tiingo-test" + ], + "operator": "clc-ocr-mercury-arbitrum-goerli-nodes-1" + }, + { + "api": [ + "coinmetrics", + "ncfx", + "tiingo-test" + ], + "operator": "clc-ocr-mercury-arbitrum-goerli-nodes-2" + }, + { + "api": [ + "coinmetrics", + "ncfx", + "tiingo-test" + ], + "operator": "clc-ocr-mercury-arbitrum-goerli-nodes-3" + } + ] + }, + "marketing": { + "category": "crypto", + "history": true, + "pair": [ + "LINK", + "USD" + ], + "path": "link-usd-verifier" + }, + "name": "LINK/USD-RefPricePlus-ArbitrumGoerli-002", + "reportFields": { + "ask": { + "decimals": 8, + "maxSubmissionValue": "99999999999999999999999999999", + "minSubmissionValue": "1", + "resultPath": "data,ask" + }, + "bid": { + "decimals": 8, + "maxSubmissionValue": "99999999999999999999999999999", + "minSubmissionValue": "1", + "resultPath": "data,bid" + }, + "median": { + "decimals": 8, + "maxSubmissionValue": "99999999999999999999999999999", + "minSubmissionValue": "1", + "resultPath": "data,mid" + } + }, + "status": "testing" + } + }, + "name": "Mercury v0.2 - Production Testnet Verifier (v1.0.0)", + "status": "testing" +} +``` +
+ +## Jobs + +### Bootstrap + +**🚨 Important config** + +`relayConfig.chainID` - target chain id. (the chain we pull block numbers from) + +`contractID` - the contract address of the verifier contract. + +
Example bootstrap TOML + +```toml +type = "bootstrap" +relay = "evm" +schemaVersion = 1 +name = "$feed_name" +contractID = "$verifier_contract_address" +feedID = "$feed_id" # IMPORTANT - DON'T FORGET THIS OR IT WON'T WORK +contractConfigTrackerPollInterval = "15s" + +[relayConfig] +chainID = $evm_chain_id +fromBlock = $from_block +``` +
+ +### OCR2 + +
Example OCR2 Mercury TOML + +```toml +type = "offchainreporting2" +schemaVersion = 1 +name = "$feed_name" +forwardingAllowed = false +maxTaskDuration = "1s" +contractID = "$verifier_contract_address" +feedID = "$feed_id" +contractConfigTrackerPollInterval = "15s" +ocrKeyBundleID = "$key_bundle_id" +p2pv2Bootstrappers = [ + "$bootstrapper_address>" +] +relay = "evm" +pluginType = "mercury" +transmitterID = "$csa_public_key" + +observationSource = """ + // ncfx + ds1_payload [type=bridge name="ncfx" timeout="50ms" requestData="{\\"data\\":{\\"endpoint\\":\\"crypto-lwba\\",\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; + ds1_median [type=jsonparse path="data,mid"]; + ds1_bid [type=jsonparse path="data,bid"]; + ds1_ask [type=jsonparse path="data,ask"]; + + ds1_median_multiply [type=multiply times=100000000]; + ds1_bid_multiply [type=multiply times=100000000]; + ds1_ask_multiply [type=multiply times=100000000]; + + // tiingo + ds2_payload [type=bridge name="tiingo" timeout="50ms" requestData="{\\"data\\":{\\"endpoint\\":\\"crypto-lwba\\",\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; + ds2_median [type=jsonparse path="data,mid"]; + ds2_bid [type=jsonparse path="data,bid"]; + ds2_ask [type=jsonparse path="data,ask"]; + + ds2_median_multiply [type=multiply times=100000000]; + ds2_bid_multiply [type=multiply times=100000000]; + ds2_ask_multiply [type=multiply times=100000000]; + + // coinmetrics + ds3_payload [type=bridge name="coinmetrics" timeout="50ms" requestData="{\\"data\\":{\\"endpoint\\":\\"crypto-lwba\\",\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; + ds3_median [type=jsonparse path="data,mid"]; + ds3_bid [type=jsonparse path="data,bid"]; + ds3_ask [type=jsonparse path="data,ask"]; + + ds3_median_multiply [type=multiply times=100000000]; + ds3_bid_multiply [type=multiply times=100000000]; + ds3_ask_multiply [type=multiply times=100000000]; + + ds1_payload -> ds1_median -> ds1_median_multiply -> benchmark_price; + ds2_payload -> ds2_median -> ds2_median_multiply -> benchmark_price; + ds3_payload -> ds3_median -> ds3_median_multiply -> benchmark_price; + + benchmark_price [type=median allowedFaults=2 index=0]; + + ds1_payload -> ds1_bid -> ds1_bid_multiply -> bid_price; + ds2_payload -> ds2_bid -> ds2_bid_multiply -> bid_price; + ds3_payload -> ds3_bid -> ds3_bid_multiply -> bid_price; + + bid_price [type=median allowedFaults=2 index=1]; + + ds1_payload -> ds1_ask -> ds1_ask_multiply -> ask_price; + ds2_payload -> ds2_ask -> ds2_ask_multiply -> ask_price; + ds3_payload -> ds3_ask -> ds3_ask_multiply -> ask_price; + + ask_price [type=median allowedFaults=2 index=2]; +""" + +[pluginConfig] +serverURL = "$mercury_server_url" +serverPubKey = "$mercury_server_public_key" + +[relayConfig] +chainID = $evm_chain_id +fromBlock = $from_block +``` +
+ +## Nodes + +**🚨 Important config** + +`OCR2.Enabled` - must be `true` - Mercury uses OCR2. + +`P2P.V2.Enabled` - required in order for OCR2 to work. + +`Feature.LogPoller` - required in order for OCR2 to work. You will get fatal errors if not set. + +`JobPipeline.MaxSuccessfulRuns` - set to `0` to disable saving pipeline runs to reduce load on the db. Obviously this means you won’t see anything in the UI. + +`TelemetryIngress.SendInterval` - How frequently to send telemetry batches. Mercury generates a lot of telemetry data due to the throughput. `100ms` has been tested for a single feed with 5 nodes - this will need to be monitored (along with relevant config) as we add more feeds to a node. + +`Database` - **must** increase connection limits above the standard defaults + +
Example node config TOML + +```toml +RootDir = '$ROOT_DIR' + +[JobPipeline] +MaxSuccessfulRuns = 0 # you may set to some small value like '10' or similar if you like looking at job runs in the UI + +[Feature] +UICSAKeys = true # required +LogPoller = true # required + +[Log] +Level = 'info' # this should be 'debug' for chainlink internal deployments, nops may use 'info' to reduce log volume + +[Log.File] +< standard values > + +[WebServer] +< standard values > + +[WebServer.TLS] +< standard values > + +[[EVM]] +ChainID = '42161' # change as needed based on target chain + +[OCR] +Enabled = false # turn off OCR 1 + +[P2P] +TraceLogging = false # this should be 'true' for chainlink internal deployments, we may ask nops to set this to true for debugging +PeerID = '$PEERID' + +[P2P.V2] +Enabled = true # required +DefaultBootstrappers = < mercury bootstrap nodes > # Note that this should ideally be set in the job spec, this is just a fallback +# Make sure these IPs are properly configured in the firewall. May not be necessary for internal nodes +AnnounceAddresses = ['$EXTERNAL_IP:$EXTERNAL_PORT'] # Use whichever port you like, pls randomize, MAKE SURE ITS CONFIGURED IN THE FIREWALL +ListenAddresses = ['0.0.0.0:$INTERNAL_PORT'] # Use whichever port you like, pls randomize, MAKE SURE ITS CONFIGURED IN THE FIREWALL + +[OCR2] +Enabled = true # required +KeyBundleID = '$KEY_BUNDLE_ID' # Note that this should ideally be set in the job spec, this is just a fallback +CaptureEATelemetry = true + +[TelemetryIngress] +UniConn = false +SendInterval = '250ms' +BufferSize = 300 +MaxBatchSize = 100 + +[[TelemetryIngress.Endpoints]] +Network = 'EVM' +ChainID = '42161' # change as needed based on target chain +URL = '$TELEMETRY_ENDPOINT_URL' # Provided by Chainlink Labs RSTP team +ServerPubKey = '$TELEMETRY_PUB_KEY' # Provided by Chainlink Labs RSTP team + +[Database] +MaxIdleConns = 100 # should equal or greater than total number of mercury jobs +MaxOpenConns = 400 # caution! ensure postgres is configured to support this + +[[EVM.Nodes]] +< put RPC nodes here > +``` +
diff --git a/go.mod b/go.mod index c71705d9c92..7fe535a425e 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/cosmos/cosmos-sdk v0.47.4 github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e github.com/esote/minmaxheap v1.0.0 - github.com/ethereum/go-ethereum v1.12.0 + github.com/ethereum/go-ethereum v1.12.2 github.com/fatih/color v1.16.0 github.com/fxamacker/cbor/v2 v2.5.0 github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 @@ -65,12 +65,12 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 github.com/smartcontractkit/chainlink-automation v1.0.1 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725 + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312 + github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/libocr v0.0.0-20231130143053-c5102a9c0fb7 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 @@ -127,8 +127,8 @@ require ( github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -142,6 +142,8 @@ require ( github.com/cockroachdb/redact v1.1.3 // indirect github.com/cometbft/cometbft-db v0.7.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.10.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect @@ -151,6 +153,7 @@ require ( github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab // indirect github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.3.0 // indirect @@ -162,6 +165,7 @@ require ( github.com/docker/distribution v2.8.2+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/ethereum/c-kzg-4844 v0.3.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gagliardetto/binary v0.7.1 // indirect @@ -212,6 +216,7 @@ require ( github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce // indirect + github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.3 // indirect github.com/huandu/skiplist v1.2.0 // indirect @@ -243,6 +248,7 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect @@ -270,6 +276,7 @@ require ( github.com/status-im/keycard-go v0.2.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/go-amino v0.16.0 // indirect @@ -313,6 +320,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect pgregory.net/rapid v0.5.5 // indirect + rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index b38b7ac2632..38eaa89993a 100644 --- a/go.sum +++ b/go.sum @@ -168,6 +168,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= @@ -176,8 +178,8 @@ github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= @@ -244,6 +246,10 @@ github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0 github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= +github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -282,6 +288,8 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= +github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -353,8 +361,10 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7 github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= -github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= +github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= +github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.12.2 h1:eGHJ4ij7oyVqUQn48LBz3B7pvQ8sV0wGJiIE6gDq/6Y= +github.com/ethereum/go-ethereum v1.12.2/go.mod h1:1cRAEV+rp/xX0zraSCBnu9Py3HQ+geRMj3HdR+k0wfI= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= @@ -597,6 +607,7 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -703,6 +714,8 @@ github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce h1:7UnVY3T/ZnHUrfv github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= @@ -943,6 +956,9 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1134,18 +1150,18 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 h1:lSYiaiIfAA+5ac45/UD8ciytlNw/S6fnhK7bxFHYI88= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e h1:xvqffqFec2HkEcUKrCkm4FDJRnn/+gHmvrE/dz3Zlw8= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e/go.mod h1:soVgcl4CbfR6hC9UptjuCQhz19HJaFEjwnOpiySkxg0= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a h1:ViX8kP1/WYW1dLG85Frqpvus1nRGif/1QiK7qeyS+Rc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5 h1:kBnmjv3fxU7krVIqZFvo1m4F6qBc4vPURQFX/mcChhI= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5/go.mod h1:EoM7wQ81mov7wsUzG4zEnnr0EH0POEo/I0hRDg433TU= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1/go.mod h1:GuPvyXryvbiUZIHmPeLBz4L+yJKeyGUjrDfd1KNne+o= github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d h1:w4MsbOtNk6nD/mcXLstHWk9hB6g7QLtcAfhPjhwvOaQ= github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d/go.mod h1:YPAfLNowdBwiKiYOwgwtbJHi8AJWbcxkbOY0ItAvkfc= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e h1:/tCHhoAJM+ittEHPZTtJsAgXmYujKiDW0ub9HXW9qtY= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e/go.mod h1:9YIi413QRRytafTzpWm+Z+5NWBNxSqokhKyeEZ3ynlA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725 h1:NbhPVwxx+53WN/Uld1V6c4iLgoGvUYFOsVd2kfcexe8= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725/go.mod h1:vHrPBipRL52NdPp77KXNU2k1IoCUa1B33N9otZQPYko= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312 h1:ziqC+WW/2/UI6w3DShy7HGzJMWWLIYHT5ev2Qaa3h6I= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312/go.mod h1:vqnojBNdzHNI6asWezJlottUiVEXudMEGf2Mz5R+xps= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a h1:atCXqF8e5U2zfEaA87cKJs+K1MAbOVh3V05gEd60fR0= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a/go.mod h1:YWKpf+hO9XMlzIWQT8yGoky3aeFLzMUVsjbs80LD77M= 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= @@ -1212,6 +1228,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= @@ -1941,5 +1959,7 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/integration-tests/Makefile b/integration-tests/Makefile index 86a266a996a..d1e9bdd89ef 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -74,12 +74,12 @@ build_test_image: #Build a chainlink docker image for local testing and push to k3d registry .PHONY: build_push_docker_image build_push_docker_image: - docker build -f ../core/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t localhost:5000/chainlink:develop ../ ; docker push localhost:5000/chainlink:develop + docker build -f ../core/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t 127.0.0.1:5000/chainlink:develop ../ ; docker push 127.0.0.1:5000/chainlink:develop #Build a chainlink docker image in plugin mode for local testing and push to k3d registry .PHONY: build_push_plugin_docker_image build_push_plugin_docker_image: - docker build -f ../plugins/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t localhost:5000/chainlink:develop ../ ; docker push localhost:5000/chainlink:develop + docker build -f ../plugins/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t 127.0.0.1:5000/chainlink:develop ../ ; docker push 127.0.0.1:5000/chainlink:develop # Spins up containers needed to collect traces for local testing .PHONY: run_tracing @@ -196,8 +196,8 @@ build_docker_image: # tag: the tag for the chainlink image being built, example: tag=latest # example usage: make build_docker_image image=chainlink tag=latest .PHONY: build_plugin_docker_image -build_docker_image: - docker build -f ../plugins/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t localhost:5000/chainlink:develop ../ +build_plugin_docker_image: + docker build -f ../plugins/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t 127.0.0.1:5000/chainlink:develop ../ # image: the name for the chainlink image being built, example: image=chainlink # tag: the tag for the chainlink image being built, example: tag=latest diff --git a/integration-tests/README.md b/integration-tests/README.md index c0b673fa92b..37a8fa19ed3 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -26,10 +26,16 @@ e.g. `make build_docker_image image=chainlink tag=test-tag` +You'll want to set the `CHAINLINK_IMAGE` and `CHAINLINK_VERSION` env values appropriately as well. See [example.env](./example.env) for more details. + ## Run `go test ./smoke/_test.go` +Most test files have a couple of tests, it's recommended to look into the file and focus on a specific one if possible. 90% of the time this will probably be the `Basic` test. See [ocr_test.go](./smoke/ocr_test.go) for example, which contains the `TestOCRBasic` test. + +`go test ./smoke/ocr_test.go -run TestOCRBasic` + It's generally recommended to run only one test at a time on a local machine as it needs a lot of docker containers and can peg your resources otherwise. You will see docker containers spin up on your machine for each component of the test where you can inspect logs. ## Analyze diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index febdd892150..bccd3ef1675 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -32,12 +32,12 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper2_0" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" ) diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index c4bc30c7c5e..37db348815b 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -391,6 +391,26 @@ func StartNewOCR2Round( return nil } +// WatchNewOCR2Round is the same as StartNewOCR2Round but does NOT explicitly request a new round +// as that can cause odd behavior in tandem with changing adapter values in OCR2 +func WatchNewOCR2Round( + roundNumber int64, + ocrInstances []contracts.OffchainAggregatorV2, + client blockchain.EVMClient, + timeout time.Duration, + logger zerolog.Logger, +) error { + for i := 0; i < len(ocrInstances); i++ { + ocrRound := contracts.NewOffchainAggregatorV2RoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), timeout, logger) + client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) + err := client.WaitForEvents() + if err != nil { + return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) + } + } + return nil +} + // SetOCR2AdapterResponse sets a single adapter response that correlates with an ocr contract and a chainlink node // used for OCR2 tests func SetOCR2AdapterResponse( diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go index c3add16ec67..dd51e302744 100644 --- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go +++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go @@ -16,8 +16,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants" diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index 17e536ec839..dd0e6606e43 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -343,6 +343,25 @@ func StartNewRound( return nil } +// WatchNewRound watches for a new OCR round, similarly to StartNewRound, but it does not explicitly request a new +// round from the contract, as this can cause some odd behavior in some cases +func WatchNewRound( + roundNumber int64, + ocrInstances []contracts.OffchainAggregator, + client blockchain.EVMClient, + logger zerolog.Logger, +) error { + for i := 0; i < len(ocrInstances); i++ { + ocrRound := contracts.NewOffchainAggregatorRoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), client.GetNetworkConfig().Timeout.Duration, logger) + client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) + err := client.WaitForEvents() + if err != nil { + return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) + } + } + return nil +} + // SetAdapterResponse sets a single adapter response that correlates with an ocr contract and a chainlink node func SetAdapterResponse( response int, diff --git a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go index 4ea4a4a8534..17c3948b340 100644 --- a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go +++ b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go @@ -20,7 +20,7 @@ import ( "github.com/google/uuid" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" + chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go index 70320530aa8..d0c83e85841 100644 --- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go +++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go @@ -23,9 +23,9 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" + chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" - chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -147,7 +147,6 @@ func CreateVRFV2PlusJob( func VRFV2_5RegisterProvingKey( vrfKey *client.VRFKey, - oracleAddress string, coordinator contracts.VRFCoordinatorV2_5, ) (VRFV2PlusEncodedProvingKey, error) { provingKey, err := actions.EncodeOnChainVRFProvingKey(*vrfKey) @@ -155,7 +154,6 @@ func VRFV2_5RegisterProvingKey( return VRFV2PlusEncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrEncodingProvingKey, err) } err = coordinator.RegisterProvingKey( - oracleAddress, provingKey, ) if err != nil { @@ -166,7 +164,6 @@ func VRFV2_5RegisterProvingKey( func VRFV2PlusUpgradedVersionRegisterProvingKey( vrfKey *client.VRFKey, - oracleAddress string, coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, ) (VRFV2PlusEncodedProvingKey, error) { provingKey, err := actions.EncodeOnChainVRFProvingKey(*vrfKey) @@ -174,7 +171,6 @@ func VRFV2PlusUpgradedVersionRegisterProvingKey( return VRFV2PlusEncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrEncodingProvingKey, err) } err = coordinator.RegisterProvingKey( - oracleAddress, provingKey, ) if err != nil { @@ -207,7 +203,6 @@ func SetupVRFV2_5Environment( vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, - registerProvingKeyAgainstAddress string, numberOfTxKeysToCreate int, numberOfConsumers int, numberOfSubToCreate int, @@ -265,7 +260,7 @@ func SetupVRFV2_5Environment( pubKeyCompressed := vrfKey.Data.ID l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Registering Proving Key") - provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, registerProvingKeyAgainstAddress, vrfv2_5Contracts.Coordinator) + provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, vrfv2_5Contracts.Coordinator) if err != nil { return nil, nil, nil, fmt.Errorf("%s, err %w", ErrRegisteringProvingKey, err) } @@ -848,9 +843,8 @@ func ReturnFundsForFulfilledRequests(client blockchain.EVMClient, coordinator co Str("LINK amount", linkTotalBalance.String()). Str("Returning to", defaultWallet). Msg("Returning LINK for fulfilled requests") - err = coordinator.OracleWithdraw( + err = coordinator.Withdraw( common.HexToAddress(defaultWallet), - linkTotalBalance, ) if err != nil { return fmt.Errorf("Error withdrawing LINK from coordinator to default wallet, err: %w", err) @@ -860,12 +854,11 @@ func ReturnFundsForFulfilledRequests(client blockchain.EVMClient, coordinator co return fmt.Errorf("Error getting NATIVE total balance, err: %w", err) } l.Info(). - Str("Native Token amount", linkTotalBalance.String()). + Str("Native Token amount", nativeTotalBalance.String()). Str("Returning to", defaultWallet). Msg("Returning Native Token for fulfilled requests") - err = coordinator.OracleWithdrawNative( + err = coordinator.WithdrawNative( common.HexToAddress(defaultWallet), - nativeTotalBalance, ) if err != nil { return fmt.Errorf("Error withdrawing NATIVE from coordinator to default wallet, err: %w", err) diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go index 464ae7a340b..ef1eb34e4ea 100644 --- a/integration-tests/contracts/contract_deployer.go +++ b/integration-tests/contracts/contract_deployer.go @@ -1,11 +1,15 @@ package contracts import ( + "context" "errors" "fmt" "math/big" + "strings" "time" + "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" @@ -145,6 +149,7 @@ type ContractDeployer interface { DeployMercuryFeeManager(linkAddress common.Address, nativeAddress common.Address, proxyAddress common.Address, rewardManagerAddress common.Address) (MercuryFeeManager, error) DeployMercuryRewardManager(linkAddress common.Address) (MercuryRewardManager, error) DeployLogEmitterContract() (LogEmitter, error) + DeployMultiCallContract() (common.Address, error) } // NewContractDeployer returns an instance of a contract deployer based on the client type @@ -1711,3 +1716,32 @@ func (e *EthereumContractDeployer) DeployLogEmitterContract() (LogEmitter, error l: e.l, }, err } + +func (e *EthereumContractDeployer) DeployMultiCallContract() (common.Address, error) { + multiCallABI, err := abi.JSON(strings.NewReader(MultiCallABI)) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := e.client.DeployContract("MultiCall Contract", func( + auth *bind.TransactOpts, + backend bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + address, tx, contract, err := bind.DeployContract(auth, multiCallABI, common.FromHex(MultiCallBIN), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, contract, err + }) + if err != nil { + return common.Address{}, err + } + r, err := bind.WaitMined(context.Background(), e.client.DeployBackend(), tx) + if err != nil { + return common.Address{}, err + } + if r.Status != types.ReceiptStatusSuccessful { + return common.Address{}, fmt.Errorf("deploy multicall failed") + } + return *address, nil + +} diff --git a/integration-tests/contracts/contract_models.go b/integration-tests/contracts/contract_models.go index 4c8d610fa1b..3d738033d68 100644 --- a/integration-tests/contracts/contract_models.go +++ b/integration-tests/contracts/contract_models.go @@ -405,6 +405,7 @@ type LogEmitter interface { Address() common.Address EmitLogInts(ints []int) (*types.Transaction, error) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) + EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) EmitLogStrings(strings []string) (*types.Transaction, error) EmitLogInt(payload int) (*types.Transaction, error) EmitLogIntIndexed(payload int) (*types.Transaction, error) diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index 548cac252b1..898abb521b3 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -54,10 +54,13 @@ type VRFCoordinatorV2 interface { Address() string GetSubscription(ctx context.Context, subID uint64) (vrf_coordinator_v2.GetSubscription, error) PendingRequestsExist(ctx context.Context, subID uint64) (bool, error) + OwnerCancelSubscription(subID uint64) (*types.Transaction, error) CancelSubscription(subID uint64, to common.Address) (*types.Transaction, error) FindSubscriptionID(subID uint64) (uint64, error) WaitForRandomWordsFulfilledEvent(requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []uint64, sender []common.Address, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) + WaitForSubscriptionCanceledEvent(subID []uint64, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionCanceled, error) + OracleWithdraw(recipient common.Address, amount *big.Int) error } type VRFCoordinatorV2_5 interface { @@ -74,7 +77,6 @@ type VRFCoordinatorV2_5 interface { feeConfig vrf_coordinator_v2_5.VRFCoordinatorV25FeeConfig, ) error RegisterProvingKey( - oracleAddr string, publicProvingKey [2]*big.Int, ) error HashOfKey(ctx context.Context, pubKey [2]*big.Int) ([32]byte, error) @@ -89,8 +91,8 @@ type VRFCoordinatorV2_5 interface { GetSubscription(ctx context.Context, subID *big.Int) (vrf_coordinator_v2_5.GetSubscription, error) OwnerCancelSubscription(subID *big.Int) (*types.Transaction, error) CancelSubscription(subID *big.Int, to common.Address) (*types.Transaction, error) - OracleWithdraw(recipient common.Address, amount *big.Int) error - OracleWithdrawNative(recipient common.Address, amount *big.Int) error + Withdraw(recipient common.Address) error + WithdrawNative(recipient common.Address) error GetNativeTokenTotalBalance(ctx context.Context) (*big.Int, error) GetLinkTotalBalance(ctx context.Context) (*big.Int, error) FindSubscriptionID(subID *big.Int) (*big.Int, error) @@ -115,7 +117,6 @@ type VRFCoordinatorV2PlusUpgradedVersion interface { feeConfig vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionFeeConfig, ) error RegisterProvingKey( - oracleAddr string, publicProvingKey [2]*big.Int, ) error HashOfKey(ctx context.Context, pubKey [2]*big.Int) ([32]byte, error) diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 7519b5de4cf..ad191d65d16 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/testreporters" cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" @@ -39,7 +40,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_performance_wrapper" diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index d1637c93c87..5d22167158a 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -224,6 +224,37 @@ func (v *EthereumVRFCoordinatorV2) PendingRequestsExist(ctx context.Context, sub return pendingRequestExists, nil } +func (v *EthereumVRFCoordinatorV2) OracleWithdraw(recipient common.Address, amount *big.Int) error { + opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) + if err != nil { + return err + } + tx, err := v.coordinator.OracleWithdraw(opts, recipient, amount) + if err != nil { + return err + } + return v.client.ProcessTransaction(tx) +} + +// OwnerCancelSubscription cancels subscription, +// return funds to the subscription owner, +// down not check if pending requests for a sub exist, +// outstanding requests may fail onchain +func (v *EthereumVRFCoordinatorV2) OwnerCancelSubscription(subID uint64) (*types.Transaction, error) { + opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) + if err != nil { + return nil, err + } + tx, err := v.coordinator.OwnerCancelSubscription( + opts, + subID, + ) + if err != nil { + return nil, err + } + return tx, v.client.ProcessTransaction(tx) +} + // CancelSubscription cancels subscription by Sub owner, // return funds to specified address, // checks if pending requests for a sub exist @@ -300,6 +331,26 @@ func (v *EthereumVRFCoordinatorV2) WaitForRandomWordsRequestedEvent(keyHash [][3 } } +func (v *EthereumVRFCoordinatorV2) WaitForSubscriptionCanceledEvent(subID []uint64, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionCanceled, error) { + eventsChannel := make(chan *vrf_coordinator_v2.VRFCoordinatorV2SubscriptionCanceled) + subscription, err := v.coordinator.WatchSubscriptionCanceled(nil, eventsChannel, subID) + if err != nil { + return nil, err + } + defer subscription.Unsubscribe() + + for { + select { + case err := <-subscription.Err(): + return nil, err + case <-time.After(timeout): + return nil, fmt.Errorf("timeout waiting for SubscriptionCanceled event") + case sub := <-eventsChannel: + return sub, nil + } + } +} + // GetAllRandomWords get all VRFv2 randomness output words func (v *EthereumVRFConsumerV2) GetAllRandomWords(ctx context.Context, num int) ([]*big.Int, error) { words := make([]*big.Int, 0) diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 330166dc79d..31c7f1e4f42 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -180,15 +180,14 @@ func (v *EthereumVRFCoordinatorV2_5) CancelSubscription(subID *big.Int, to commo return tx, v.client.ProcessTransaction(tx) } -func (v *EthereumVRFCoordinatorV2_5) OracleWithdraw(recipient common.Address, amount *big.Int) error { +func (v *EthereumVRFCoordinatorV2_5) Withdraw(recipient common.Address) error { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return err } - tx, err := v.coordinator.OracleWithdraw( + tx, err := v.coordinator.Withdraw( opts, recipient, - amount, ) if err != nil { return err @@ -196,15 +195,14 @@ func (v *EthereumVRFCoordinatorV2_5) OracleWithdraw(recipient common.Address, am return v.client.ProcessTransaction(tx) } -func (v *EthereumVRFCoordinatorV2_5) OracleWithdrawNative(recipient common.Address, amount *big.Int) error { +func (v *EthereumVRFCoordinatorV2_5) WithdrawNative(recipient common.Address) error { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return err } - tx, err := v.coordinator.OracleWithdrawNative( + tx, err := v.coordinator.WithdrawNative( opts, recipient, - amount, ) if err != nil { return err @@ -249,14 +247,13 @@ func (v *EthereumVRFCoordinatorV2_5) SetLINKAndLINKNativeFeed(linkAddress string } func (v *EthereumVRFCoordinatorV2_5) RegisterProvingKey( - oracleAddr string, publicProvingKey [2]*big.Int, ) error { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return err } - tx, err := v.coordinator.RegisterProvingKey(opts, common.HexToAddress(oracleAddr), publicProvingKey) + tx, err := v.coordinator.RegisterProvingKey(opts, publicProvingKey) if err != nil { return err } @@ -638,14 +635,13 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) SetLINKAndLINKNativeFeed(l } func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) RegisterProvingKey( - oracleAddr string, publicProvingKey [2]*big.Int, ) error { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return err } - tx, err := v.coordinator.RegisterProvingKey(opts, common.HexToAddress(oracleAddr), publicProvingKey) + tx, err := v.coordinator.RegisterProvingKey(opts, publicProvingKey) if err != nil { return err } diff --git a/integration-tests/contracts/multicall.go b/integration-tests/contracts/multicall.go new file mode 100644 index 00000000000..b809c20021d --- /dev/null +++ b/integration-tests/contracts/multicall.go @@ -0,0 +1,95 @@ +package contracts + +import ( + "context" + "fmt" + "math/big" + "strings" + + "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/pkg/errors" + "github.com/rs/zerolog/log" + + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" +) + +const ( + MultiCallABI = "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Call3[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Call3Value[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3Value\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"basefee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainid\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]" + MultiCallBIN = "0x608060405234801561001057600080fd5b50610ee0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033" +) + +type CallWithValue struct { + Target common.Address + AllowFailure bool + Value *big.Int + CallData []byte +} + +type Call struct { + Target common.Address + AllowFailure bool + CallData []byte +} + +type Result struct { + Success bool + ReturnData []byte +} + +func WaitForSuccessfulTxMined(evmClient blockchain.EVMClient, tx *types.Transaction) error { + log.Debug().Str("tx", tx.Hash().Hex()).Msg("waiting for tx to be mined") + receipt, err := bind.WaitMined(context.Background(), evmClient.DeployBackend(), tx) + if err != nil { + return err + } + if receipt.Status != types.ReceiptStatusSuccessful { + return fmt.Errorf("tx failed %s", tx.Hash().Hex()) + } + log.Debug().Str("tx", tx.Hash().Hex()).Str("Network", evmClient.GetNetworkName()).Msg("tx mined successfully") + return nil +} + +func MultiCallLogTriggerLoadGen( + evmClient blockchain.EVMClient, + multiCallAddress string, + logTriggerAddress []string, + logTriggerData [][]byte, +) (*types.Transaction, error) { + + contractAddress := common.HexToAddress(multiCallAddress) + multiCallABI, err := abi.JSON(strings.NewReader(MultiCallABI)) + if err != nil { + return nil, err + } + boundContract := bind.NewBoundContract(contractAddress, multiCallABI, evmClient.Backend(), evmClient.Backend(), evmClient.Backend()) + + var call []Call + for i, d := range logTriggerData { + data := Call{Target: common.HexToAddress(logTriggerAddress[i]), AllowFailure: false, CallData: d} + call = append(call, data) + } + + opts, err := evmClient.TransactionOpts(evmClient.GetDefaultWallet()) + if err != nil { + return nil, err + } + + // call aggregate3 to group all msg call data and send them in a single transaction + tx, err := boundContract.Transact(opts, "aggregate3", call) + if err != nil { + return nil, err + } + err = evmClient.MarkTxAsSentOnL2(tx) + if err != nil { + return nil, err + } + err = WaitForSuccessfulTxMined(evmClient, tx) + if err != nil { + return nil, errors.Wrapf(err, "multicall failed for log trigger load gen; multicall %s", contractAddress.Hex()) + } + return tx, nil + +} diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go index 3080668da69..8a6d0b5be02 100644 --- a/integration-tests/contracts/test_contracts.go +++ b/integration-tests/contracts/test_contracts.go @@ -55,6 +55,18 @@ func (e *LogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, return tx, e.client.ProcessTransaction(tx) } +func (e *LogEmitterContract) EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) { + opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) + if err != nil { + return nil, err + } + tx, err := e.instance.EmitLog4(opts, big.NewInt(int64(ints)), big.NewInt(int64(ints2)), big.NewInt(int64(count))) + if err != nil { + return nil, err + } + return tx, e.client.ProcessTransaction(tx) +} + func (e *LogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) { opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index d6ab22957a2..a00dea3a35a 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -3,9 +3,12 @@ package test_env import ( "context" "fmt" + "io" + "maps" "math/big" "net/url" "os" + "regexp" "strings" "testing" "time" @@ -14,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/pelletier/go-toml/v2" + "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" tc "github.com/testcontainers/testcontainers-go" @@ -47,6 +51,7 @@ type ClNode struct { PostgresDb *test_env.PostgresDb `json:"postgresDb"` UserEmail string `json:"userEmail"` UserPassword string `json:"userPassword"` + AlwaysPullImage bool t *testing.T l zerolog.Logger ls *logstream.LogStream @@ -60,6 +65,15 @@ func WithSecrets(secretsTOML string) ClNodeOption { } } +func WithNodeEnvVars(ev map[string]string) ClNodeOption { + return func(n *ClNode) { + if n.ContainerEnvs == nil { + n.ContainerEnvs = map[string]string{} + } + maps.Copy(n.ContainerEnvs, ev) + } +} + // Sets custom node container name if name is not empty func WithNodeContainerName(name string) ClNodeOption { return func(c *ClNode) { @@ -153,8 +167,15 @@ func (n *ClNode) UpgradeVersion(newImage, newVersion string) error { return fmt.Errorf("new version is empty") } if newImage == "" { - return fmt.Errorf("new image name is empty") + newImage = os.Getenv("CHAINLINK_IMAGE") } + n.l.Info(). + Str("Name", n.ContainerName). + Str("Old Image", os.Getenv("CHAINLINK_IMAGE")). + Str("Old Version", os.Getenv("CHAINLINK_VERSION")). + Str("New Image", newImage). + Str("New Version", newVersion). + Msg("Upgrading Chainlink Node") n.ContainerImage = newImage n.ContainerVersion = newVersion return n.Restart(n.NodeConfig) @@ -344,6 +365,28 @@ func (n *ClNode) StartContainer() error { return nil } +func (n *ClNode) ExecGetVersion() (string, error) { + cmd := []string{"chainlink", "--version"} + _, output, err := n.Container.Exec(context.Background(), cmd) + if err != nil { + return "", errors.Wrapf(err, "could not execute cmd %s", cmd) + } + outputBytes, err := io.ReadAll(output) + if err != nil { + return "", err + } + outputString := strings.TrimSpace(string(outputBytes)) + + // Find version in cmd output + re := regexp.MustCompile("@(.*)") + matches := re.FindStringSubmatch(outputString) + + if len(matches) > 1 { + return matches[1], nil + } + return "", errors.Errorf("could not find chainlink version in command output '%'", output) +} + func (n *ClNode) getContainerRequest(secrets string) ( *tc.ContainerRequest, error) { configFile, err := os.CreateTemp("", "node_config") @@ -393,9 +436,10 @@ func (n *ClNode) getContainerRequest(secrets string) ( apiCredsPath := "/home/api-credentials.txt" return &tc.ContainerRequest{ - Name: n.ContainerName, - Image: fmt.Sprintf("%s:%s", n.ContainerImage, n.ContainerVersion), - ExposedPorts: []string{"6688/tcp"}, + Name: n.ContainerName, + AlwaysPullImage: n.AlwaysPullImage, + Image: fmt.Sprintf("%s:%s", n.ContainerImage, n.ContainerVersion), + ExposedPorts: []string{"6688/tcp"}, Entrypoint: []string{"chainlink", "-c", configPath, "-s", secretsPath, diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index 20e231e5985..b928bc9e664 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -8,7 +8,6 @@ import ( "os" "runtime/debug" "testing" - "time" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/rs/zerolog" @@ -194,7 +193,6 @@ func (te *CLClusterTestEnv) FundChainlinkNodes(amount *big.Float) error { if err := cl.Fund(te.EVMClient, amount); err != nil { return fmt.Errorf("%s, err: %w", ErrFundCLNode, err) } - time.Sleep(5 * time.Second) } return te.EVMClient.WaitForEvents() } diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 7358d76f2af..bd73d33d9bf 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -59,7 +59,8 @@ type CLTestEnvBuilder struct { func NewCLTestEnvBuilder() *CLTestEnvBuilder { return &CLTestEnvBuilder{ - l: log.Logger, + l: log.Logger, + hasLogStream: true, } } @@ -101,8 +102,9 @@ func (b *CLTestEnvBuilder) WithTestInstance(t *testing.T) *CLTestEnvBuilder { return b } -func (b *CLTestEnvBuilder) WithLogStream() *CLTestEnvBuilder { - b.hasLogStream = true +// WithoutLogStream disables LogStream logging component +func (b *CLTestEnvBuilder) WithoutLogStream() *CLTestEnvBuilder { + b.hasLogStream = false return b } diff --git a/integration-tests/example.env b/integration-tests/example.env index 3e27ac2c7ab..bbc76bb0c09 100644 --- a/integration-tests/example.env +++ b/integration-tests/example.env @@ -30,15 +30,16 @@ export TEST_UPGRADE_VERSION="2.0.0" # Version of the Chainlink image to upgrade ########## Network Settings ########## +# If running on a live network, you must set the following values # Select a pre-defined network(s) export SELECTED_NETWORKS="SIMULATED" - # General private values that will be retrieved when running on non-simulated networks export EVM_URLS="wss://evm.url,wss://other.url" # Comma-sparated list of websocket URLs to use when running on live networks export EVM_HTTP_URLS="https://evm.url,https://other.url" # Comma-sparated list of HTTP URLs to use when running on live networks export EVM_KEYS="private,funding,keys" # Comma-separated list of private keys to use when running on live networks # Specific private values retrieved when running on specified chains +# Will override the general values above if the SELECTED_NETWORKS contains the network name # Goerli export GOERLI_URLS="wss://goerli.io/ws" export GOERLI_HTTP_URLS="http://goerli.io/ws" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 9f0ff1b384c..673fbf4dbd5 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -9,7 +9,7 @@ require ( cosmossdk.io/errors v1.0.0 github.com/K-Phoen/grabana v0.21.17 github.com/cli/go-gh/v2 v2.0.0 - github.com/ethereum/go-ethereum v1.12.0 + github.com/ethereum/go-ethereum v1.12.2 github.com/go-resty/resty/v2 v2.7.0 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.4.0 @@ -19,18 +19,19 @@ require ( github.com/manifoldco/promptui v0.9.0 github.com/onsi/gomega v1.30.0 github.com/pelletier/go-toml/v2 v2.1.1 + github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.30.0 github.com/scylladb/go-reflectx v1.0.1 github.com/segmentio/ksuid v1.0.4 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.1 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 - github.com/smartcontractkit/chainlink-testing-framework v1.22.0 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a + github.com/smartcontractkit/chainlink-testing-framework v1.22.1 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-20231130143053-c5102a9c0fb7 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 - github.com/smartcontractkit/wasp v0.3.7 + github.com/smartcontractkit/wasp v0.4.0 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 @@ -45,9 +46,10 @@ require ( // avoids ambigious imports of indirect dependencies exclude github.com/hashicorp/consul v1.2.1 -// Pin K8s versions as their updates are highly disruptive and go mod keeps wanting to update them replace ( + // Required until https://github.com/testcontainers/testcontainers-go/pull/1971 is merged github.com/testcontainers/testcontainers-go => github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56 + // Pin K8s versions as their updates are highly disruptive and go mod keeps wanting to update them k8s.io/api => k8s.io/api v0.25.11 k8s.io/client-go => k8s.io/client-go v0.25.11 k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d @@ -75,7 +77,9 @@ require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/K-Phoen/sdk v0.12.2 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.1 // indirect github.com/VictoriaMetrics/fastcache v1.10.0 // indirect @@ -91,9 +95,10 @@ require ( github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect @@ -115,6 +120,8 @@ require ( github.com/cometbft/cometbft v0.37.2 // indirect github.com/cometbft/cometbft-db v0.7.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.10.0 // indirect github.com/containerd/containerd v1.7.7 // indirect github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect @@ -129,6 +136,7 @@ require ( github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab // indirect github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.3.0 // indirect @@ -138,6 +146,7 @@ require ( github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/docker v24.0.7+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -147,9 +156,11 @@ require ( github.com/edsrzf/mmap-go v1.1.0 // indirect github.com/emicklei/go-restful/v3 v3.10.2 // indirect github.com/esote/minmaxheap v1.0.0 // indirect + github.com/ethereum/c-kzg-4844 v0.3.1 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect github.com/fatih/camelcase v1.0.0 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect @@ -187,6 +198,7 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.15.5 // indirect + github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect @@ -216,7 +228,8 @@ require ( github.com/gosimple/slug v1.13.1 // indirect github.com/gosimple/unidecode v1.0.1 // indirect github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f // indirect - github.com/grafana/loki v1.6.2-0.20231201111602-11ef833ed3e4 // indirect + github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 // indirect + github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect github.com/grafana/pyroscope-go v1.0.4 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.4 // indirect @@ -249,6 +262,7 @@ require ( github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.3 // indirect github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/xstrings v1.4.0 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -286,10 +300,13 @@ require ( github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/miekg/dns v1.1.56 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect @@ -320,7 +337,6 @@ require ( github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/alertmanager v0.26.0 // indirect @@ -345,14 +361,15 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.7.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect + github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -361,6 +378,7 @@ require ( github.com/status-im/keycard-go v0.2.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/go-amino v0.16.0 // indirect @@ -406,6 +424,7 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect + go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.6.0 // indirect golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect @@ -444,6 +463,7 @@ require ( k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect nhooyr.io/websocket v1.8.7 // indirect pgregory.net/rapid v0.5.5 // indirect + rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/controller-runtime v0.13.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.12.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index f8a9529a4cc..9977ed84b8b 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -124,9 +124,14 @@ github.com/K-Phoen/sdk v0.12.2 h1:0QofDlKE+lloyBOzhjEEMW21061zts/WIpfpQ5NLLAs= github.com/K-Phoen/sdk v0.12.2/go.mod h1:qmM0wO23CtoDux528MXPpYvS4XkRWkWX6rvX9Za8EVU= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= @@ -145,6 +150,8 @@ github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40wo github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/Workiva/go-datastructures v1.1.0 h1:hu20UpgZneBhQ3ZvwiOGlqJSKIosin2Rd5wAKUHEO/k= +github.com/Workiva/go-datastructures v1.1.0/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= @@ -158,6 +165,11 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= +github.com/alicebob/miniredis/v2 v2.30.4 h1:8S4/o1/KoUArAGbGwPxcwf0krlzceva2XVOSchFS7Eo= +github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6uH3VlUfb/HS5zKg= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= @@ -202,6 +214,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= @@ -210,10 +224,11 @@ github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= @@ -301,6 +316,10 @@ github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0 github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= +github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= @@ -349,6 +368,8 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= +github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -391,6 +412,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/digitalocean/godo v1.104.1 h1:SZNxjAsskM/su0YW9P8Wx3gU0W1Z13b6tZlYNpl5BnA= github.com/digitalocean/godo v1.104.1/go.mod h1:VAI/L5YDzMuPRU01lEEUSQ/sp5Z//1HnnFv/RBTEdbg= @@ -430,8 +453,10 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7 github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= -github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= +github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= +github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.12.2 h1:eGHJ4ij7oyVqUQn48LBz3B7pvQ8sV0wGJiIE6gDq/6Y= +github.com/ethereum/go-ethereum v1.12.2/go.mod h1:1cRAEV+rp/xX0zraSCBnu9Py3HQ+geRMj3HdR+k0wfI= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -445,6 +470,8 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojt github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= @@ -591,6 +618,8 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91 github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -764,6 +793,7 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -801,8 +831,10 @@ github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6 github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f h1:gyojr97YeWZ70pKNakWv5/tKwBHuLy3icnIeCo9gQr4= github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f/go.mod h1:8dsy5tQOkeNQyjXpm5mQsbCu3H5uzeBD35MzRQFznKU= -github.com/grafana/loki v1.6.2-0.20231201111602-11ef833ed3e4 h1:YbfISHhpbiDvoFNxDPCicPOU/+9s4rdv9Fq/V3iRvTo= -github.com/grafana/loki v1.6.2-0.20231201111602-11ef833ed3e4/go.mod h1:Tx2uhmS+H0pGmtqX94/KaDkRHWhIowt4iYtJLctAbEY= +github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 h1:/of8Z8taCPftShATouOrBVy6GaTTjgQd/VfNiZp/VXQ= +github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU= +github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qvPwZO5DC6QjnAW7uKJ9YXnoUmV8c= +github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= github.com/grafana/pyroscope-go v1.0.4 h1:oyQX0BOkL+iARXzHuCdIF5TQ7/sRSel1YFViMHC7Bm0= @@ -915,6 +947,8 @@ github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTx github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo= github.com/hetznercloud/hcloud-go/v2 v2.4.0 h1:MqlAE+w125PLvJRCpAJmEwrIxoVdUdOyuFUhE/Ukbok= github.com/hetznercloud/hcloud-go/v2 v2.4.0/go.mod h1:l7fA5xsncFBzQTyw29/dw5Yr88yEGKKdc6BHf24ONS0= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= @@ -924,11 +958,15 @@ github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3 github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -1159,6 +1197,9 @@ github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -1178,6 +1219,12 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= @@ -1285,6 +1332,8 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= @@ -1432,20 +1481,20 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 h1:lSYiaiIfAA+5ac45/UD8ciytlNw/S6fnhK7bxFHYI88= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e h1:xvqffqFec2HkEcUKrCkm4FDJRnn/+gHmvrE/dz3Zlw8= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e/go.mod h1:soVgcl4CbfR6hC9UptjuCQhz19HJaFEjwnOpiySkxg0= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a h1:ViX8kP1/WYW1dLG85Frqpvus1nRGif/1QiK7qeyS+Rc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231222010926-795676d23c7a/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5 h1:kBnmjv3fxU7krVIqZFvo1m4F6qBc4vPURQFX/mcChhI= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231218175426-6e0427c661e5/go.mod h1:EoM7wQ81mov7wsUzG4zEnnr0EH0POEo/I0hRDg433TU= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1/go.mod h1:GuPvyXryvbiUZIHmPeLBz4L+yJKeyGUjrDfd1KNne+o= github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d h1:w4MsbOtNk6nD/mcXLstHWk9hB6g7QLtcAfhPjhwvOaQ= github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d/go.mod h1:YPAfLNowdBwiKiYOwgwtbJHi8AJWbcxkbOY0ItAvkfc= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e h1:/tCHhoAJM+ittEHPZTtJsAgXmYujKiDW0ub9HXW9qtY= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e/go.mod h1:9YIi413QRRytafTzpWm+Z+5NWBNxSqokhKyeEZ3ynlA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725 h1:NbhPVwxx+53WN/Uld1V6c4iLgoGvUYFOsVd2kfcexe8= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725/go.mod h1:vHrPBipRL52NdPp77KXNU2k1IoCUa1B33N9otZQPYko= -github.com/smartcontractkit/chainlink-testing-framework v1.22.0 h1:Lur628wkrceWgcLmxGZe7Mauwxht4YO71hX9Jj5YslE= -github.com/smartcontractkit/chainlink-testing-framework v1.22.0/go.mod h1:yu6qqrppNJfutQV37fiSs4eS0uQP5QT0ebi3tlIgWN0= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312 h1:ziqC+WW/2/UI6w3DShy7HGzJMWWLIYHT5ev2Qaa3h6I= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231219140448-151a4725f312/go.mod h1:vqnojBNdzHNI6asWezJlottUiVEXudMEGf2Mz5R+xps= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a h1:atCXqF8e5U2zfEaA87cKJs+K1MAbOVh3V05gEd60fR0= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231219014050-0c4a7831293a/go.mod h1:YWKpf+hO9XMlzIWQT8yGoky3aeFLzMUVsjbs80LD77M= +github.com/smartcontractkit/chainlink-testing-framework v1.22.1 h1:2XDxU1CTWJruUZv15/VPdaBT1W9ym4OI3I5baRbDhFg= +github.com/smartcontractkit/chainlink-testing-framework v1.22.1/go.mod h1:yu6qqrppNJfutQV37fiSs4eS0uQP5QT0ebi3tlIgWN0= 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= @@ -1458,8 +1507,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wasp v0.3.7 h1:3toT+iMSHJ1EKQXE+jGnxfmtLlT0gwEl1A7xGyw0NZY= -github.com/smartcontractkit/wasp v0.3.7/go.mod h1:L/cyUGfpaWxy/2twOVJLRt2mySJEIqGrFj9nyvRLpSo= +github.com/smartcontractkit/wasp v0.4.0 h1:N8yPxlBvoJiyE6HaDkTkwRbuOHkGgQFGEHbw36oh4jA= +github.com/smartcontractkit/wasp v0.4.0/go.mod h1:3qiofyI3pkbrc48a3CVshbMfgl74SiuPL/tm30d9Wb4= github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ= github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -1467,6 +1516,8 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= +github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1474,6 +1525,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -1517,6 +1569,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= @@ -1615,6 +1669,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE= +github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= @@ -1707,6 +1763,8 @@ go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc= golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -1738,6 +1796,7 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= @@ -1845,6 +1904,7 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= @@ -1974,6 +2034,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1986,6 +2047,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= @@ -2314,6 +2376,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 5fde9befba5..d2bca2e670c 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -2,6 +2,7 @@ package automationv2_1 import ( "context" + "encoding/base64" "fmt" "math" "math/big" @@ -14,6 +15,7 @@ import ( geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/pelletier/go-toml/v2" "github.com/slack-go/slack" "github.com/stretchr/testify/require" @@ -31,16 +33,15 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" contractseth "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper" ) const ( @@ -77,16 +78,16 @@ ListenAddresses = ["0.0.0.0:6690"]` minimumDbSpec = map[string]interface{}{ "resources": map[string]interface{}{ "requests": map[string]interface{}{ - "cpu": "1000m", - "memory": "1Gi", + "cpu": "4000m", + "memory": "4Gi", }, "limits": map[string]interface{}{ - "cpu": "1000m", - "memory": "1Gi", + "cpu": "4000m", + "memory": "4Gi", }, }, "stateful": true, - "capacity": "5Gi", + "capacity": "10Gi", } recNodeSpec = map[string]interface{}{ @@ -102,58 +103,120 @@ ListenAddresses = ["0.0.0.0:6690"]` }, } - recDbSpec = map[string]interface{}{ - "resources": map[string]interface{}{ - "requests": map[string]interface{}{ - "cpu": "2000m", - "memory": "2Gi", - }, - "limits": map[string]interface{}{ - "cpu": "2000m", - "memory": "2Gi", - }, + recDbSpec = minimumDbSpec + + gethNodeSpec = map[string]interface{}{ + "requests": map[string]interface{}{ + "cpu": "8000m", + "memory": "8Gi", + }, + "limits": map[string]interface{}{ + "cpu": "16000m", + "memory": "16Gi", }, - "stateful": true, - "capacity": "10Gi", } ) var ( - numberofNodes, _ = strconv.Atoi(getEnv("NUMBEROFNODES", "6")) // Number of nodes in the DON - numberOfUpkeeps, _ = strconv.Atoi(getEnv("NUMBEROFUPKEEPS", "100")) // Number of log triggered upkeeps - duration, _ = strconv.Atoi(getEnv("DURATION", "900")) // Test duration in seconds - blockTime, _ = strconv.Atoi(getEnv("BLOCKTIME", "1")) // Block time in seconds for geth simulated dev network - numberOfEvents, _ = strconv.Atoi(getEnv("NUMBEROFEVENTS", "1")) // Number of events to emit per trigger - specType = getEnv("SPECTYPE", "minimum") // minimum, recommended, local specs for the test - logLevel = getEnv("LOGLEVEL", "info") // log level for the chainlink nodes - pyroscope, _ = strconv.ParseBool(getEnv("PYROSCOPE", "false")) // enable pyroscope for the chainlink nodes + numberofNodes, _ = strconv.Atoi(getEnv("NUMBEROFNODES", "6")) // Number of nodes in the DON + duration, _ = strconv.Atoi(getEnv("DURATION", "900")) // Test duration in seconds + blockTime, _ = strconv.Atoi(getEnv("BLOCKTIME", "1")) // Block time in seconds for geth simulated dev network + nodeFunding, _ = strconv.ParseFloat(getEnv("NODEFUNDING", "100"), 64) // Amount of native to fund each node with + + specType = getEnv("SPECTYPE", "minimum") // minimum, recommended, local specs for the test + logLevel = getEnv("LOGLEVEL", "info") // log level for the chainlink nodes + pyroscope, _ = strconv.ParseBool(getEnv("PYROSCOPE", "false")) // enable pyroscope for the chainlink nodes + prometheus, _ = strconv.ParseBool(getEnv("PROMETHEUS", "false")) // enable prometheus for the chainlink nodes + configOverride = os.Getenv("CONFIG_OVERRIDE") // config overrides for the load config ) +type Load struct { + NumberOfEvents int64 `toml:",omitempty"` + NumberOfSpamMatchingEvents int64 `toml:",omitempty"` + NumberOfSpamNonMatchingEvents int64 `toml:",omitempty"` + CheckBurnAmount *big.Int `toml:",omitempty"` + PerformBurnAmount *big.Int `toml:",omitempty"` + UpkeepGasLimit uint32 `toml:",omitempty"` + NumberOfUpkeeps int `toml:",omitempty"` + SharedTrigger bool `toml:",omitempty"` +} + +type LoadConfig struct { + Load []Load `toml:",omitempty"` +} + +var defaultLoadConfig = LoadConfig{ + Load: []Load{ + { + NumberOfEvents: 1, + NumberOfSpamMatchingEvents: 1, + NumberOfSpamNonMatchingEvents: 0, + CheckBurnAmount: big.NewInt(0), + PerformBurnAmount: big.NewInt(0), + UpkeepGasLimit: 1_000_000, + NumberOfUpkeeps: 5, + SharedTrigger: false, + }, + { + NumberOfEvents: 1, + NumberOfSpamMatchingEvents: 0, + NumberOfSpamNonMatchingEvents: 1, + CheckBurnAmount: big.NewInt(0), + PerformBurnAmount: big.NewInt(0), + UpkeepGasLimit: 1_000_000, + NumberOfUpkeeps: 5, + SharedTrigger: true, + }}, +} + func TestLogTrigger(t *testing.T) { ctx := tests.Context(t) l := logging.GetTestLogger(t) + loadConfig := &LoadConfig{} + if configOverride != "" { + d, err := base64.StdEncoding.DecodeString(configOverride) + require.NoError(t, err, "Error decoding config override") + l.Info().Str("CONFIG_OVERRIDE", configOverride).Bytes("Decoded value", d).Msg("Decoding config override") + err = toml.Unmarshal(d, &loadConfig) + require.NoError(t, err, "Error unmarshalling config override") + } else { + loadConfig = &defaultLoadConfig + } + + loadConfigBytes, err := toml.Marshal(loadConfig) + require.NoError(t, err, "Error marshalling load config") + l.Info().Msg("Starting automation v2.1 log trigger load test") l.Info().Str("TEST_INPUTS", os.Getenv("TEST_INPUTS")).Int("Number of Nodes", numberofNodes). - Int("Number of Upkeeps", numberOfUpkeeps). Int("Duration", duration). Int("Block Time", blockTime). - Int("Number of Events", numberOfEvents). Str("Spec Type", specType). Str("Log Level", logLevel). Str("Image", os.Getenv(config.EnvVarCLImage)). Str("Tag", os.Getenv(config.EnvVarCLTag)). + Bytes("Load Config", loadConfigBytes). Msg("Test Config") - testConfig := fmt.Sprintf("Number of Nodes: %d\nNumber of Upkeeps: %d\nDuration: %d\nBlock Time: %d\n"+ - "Number of Events: %d\nSpec Type: %s\nLog Level: %s\nImage: %s\nTag: %s\n", numberofNodes, numberOfUpkeeps, duration, - blockTime, numberOfEvents, specType, logLevel, os.Getenv(config.EnvVarCLImage), os.Getenv(config.EnvVarCLTag)) + testConfigFormat := `Number of Nodes: %d +Duration: %d +Block Time: %d +Spec Type: %s +Log Level: %s +Image: %s +Tag: %s + +Load Config: +%s` + + testConfig := fmt.Sprintf(testConfigFormat, numberofNodes, duration, + blockTime, specType, logLevel, os.Getenv(config.EnvVarCLImage), os.Getenv(config.EnvVarCLTag), string(loadConfigBytes)) + l.Info().Str("testConfig", testConfig).Msg("Test Config") testNetwork := networks.MustGetSelectedNetworksFromEnv()[0] testType := "load" loadDuration := time.Duration(duration) * time.Second automationDefaultLinkFunds := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(10000))) //10000 LINK - automationDefaultUpkeepGasLimit := uint32(1_000_000) registrySettings := &contracts.KeeperRegistrySettings{ PaymentPremiumPPB: uint32(0), @@ -198,6 +261,10 @@ func TestLogTrigger(t *testing.T) { key = "GRAFANA_DASHBOARD_URL" err = os.Setenv(fmt.Sprintf("TEST_%s", key), getEnv(key, "")) require.NoError(t, err, "failed to set the environment variable GRAFANA_DASHBOARD_URL for remote runner") + + key = "CONFIG_OVERRIDE" + err = os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key)) + require.NoError(t, err, "failed to set the environment variable CONFIG_OVERRIDE for remote runner") } testEnvironment. @@ -206,24 +273,15 @@ func TestLogTrigger(t *testing.T) { Simulated: testNetwork.Simulated, WsURLs: testNetwork.URLs, Values: map[string]interface{}{ - "resources": map[string]interface{}{ - "requests": map[string]interface{}{ - "cpu": "4000m", - "memory": "4Gi", - }, - "limits": map[string]interface{}{ - "cpu": "8000m", - "memory": "8Gi", - }, - }, + "resources": gethNodeSpec, "geth": map[string]interface{}{ "blocktime": blockTime, - "capacity": "10Gi", + "capacity": "20Gi", }, }, })) - err := testEnvironment.Run() + err = testEnvironment.Run() require.NoError(t, err, "Error launching test environment") if testEnvironment.WillUseRemoteRunner() { @@ -264,9 +322,10 @@ func TestLogTrigger(t *testing.T) { } nodeTOML = networks.AddNetworksConfig(nodeTOML, testNetwork) testEnvironment.AddHelm(chainlink.New(i, map[string]any{ - "toml": nodeTOML, - "chainlink": nodeSpec, - "db": dbSpec, + "toml": nodeTOML, + "chainlink": nodeSpec, + "db": dbSpec, + "prometheus": prometheus, })) } @@ -284,6 +343,9 @@ func TestLogTrigger(t *testing.T) { chainClient.ParallelTransactions(true) + multicallAddress, err := contractDeployer.DeployMultiCallContract() + require.NoError(t, err, "Error deploying multicall contract") + a := automationv2.NewAutomationTestK8s(chainClient, contractDeployer, chainlinkNodes) a.RegistrySettings = *registrySettings a.RegistrarSettings = contracts.KeeperRegistrarSettings{ @@ -316,13 +378,17 @@ func TestLogTrigger(t *testing.T) { F: 1, } + startTimeTestSetup := time.Now() + l.Info().Str("START_TIME", startTimeTestSetup.String()).Msg("Test setup started") + a.SetupAutomationDeployment(t) - err = actions.FundChainlinkNodesAddress(chainlinkNodes[1:], chainClient, big.NewFloat(100), 0) + err = actions.FundChainlinkNodesAddress(chainlinkNodes[1:], chainClient, big.NewFloat(nodeFunding), 0) require.NoError(t, err, "Error funding chainlink nodes") consumerContracts := make([]contracts.KeeperConsumer, 0) triggerContracts := make([]contracts.LogEmitter, 0) + triggerAddresses := make([]common.Address, 0) utilsABI, err := automation_utils_2_1.AutomationUtilsMetaData.GetAbi() require.NoError(t, err, "Error getting automation utils abi") @@ -335,43 +401,60 @@ func TestLogTrigger(t *testing.T) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } + var bytes1 = [32]byte{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + } + upkeepConfigs := make([]automationv2.UpkeepConfig, 0) + loadConfigs := make([]Load, 0) + cEVMClient, err := blockchain.ConcurrentEVMClient(testNetwork, testEnvironment, chainClient, l) + require.NoError(t, err, "Error building concurrent chain client") + + for _, u := range loadConfig.Load { + for i := 0; i < u.NumberOfUpkeeps; i++ { + consumerContract, err := contractDeployer.DeployAutomationSimpleLogTriggerConsumer() + require.NoError(t, err, "Error deploying automation consumer contract") + consumerContracts = append(consumerContracts, consumerContract) + l.Debug(). + Str("Contract Address", consumerContract.Address()). + Int("Number", i+1). + Int("Out Of", u.NumberOfUpkeeps). + Msg("Deployed Automation Log Trigger Consumer Contract") + loadCfg := Load{ + NumberOfEvents: u.NumberOfEvents, + NumberOfSpamMatchingEvents: u.NumberOfSpamMatchingEvents, + NumberOfSpamNonMatchingEvents: u.NumberOfSpamNonMatchingEvents, + CheckBurnAmount: u.CheckBurnAmount, + PerformBurnAmount: u.PerformBurnAmount, + UpkeepGasLimit: u.UpkeepGasLimit, + SharedTrigger: u.SharedTrigger, + } + loadConfigs = append(loadConfigs, loadCfg) - for i := 0; i < numberOfUpkeeps; i++ { - consumerContract, err := contractDeployer.DeployAutomationSimpleLogTriggerConsumer() - require.NoError(t, err, "Error deploying automation consumer contract") - consumerContracts = append(consumerContracts, consumerContract) - l.Debug(). - Str("Contract Address", consumerContract.Address()). - Int("Number", i+1). - Int("Out Of", numberOfUpkeeps). - Msg("Deployed Automation Log Trigger Consumer Contract") - - cEVMClient, err := blockchain.ConcurrentEVMClient(testNetwork, testEnvironment, chainClient, l) - require.NoError(t, err, "Error building concurrent chain client") - - cContractDeployer, err := contracts.NewContractDeployer(cEVMClient, l) - require.NoError(t, err, "Error building concurrent contract deployer") - - triggerContract, err := cContractDeployer.DeployLogEmitterContract() - require.NoError(t, err, "Error deploying log emitter contract") - triggerContracts = append(triggerContracts, triggerContract) - l.Debug(). - Str("Contract Address", triggerContract.Address().Hex()). - Int("Number", i+1). - Int("Out Of", numberOfUpkeeps). - Msg("Deployed Automation Log Trigger Emitter Contract") + if u.SharedTrigger && i > 0 { + triggerAddresses = append(triggerAddresses, triggerAddresses[len(triggerAddresses)-1]) + continue + } + triggerContract, err := contractDeployer.DeployLogEmitterContract() + require.NoError(t, err, "Error deploying log emitter contract") + triggerContracts = append(triggerContracts, triggerContract) + triggerAddresses = append(triggerAddresses, triggerContract.Address()) + l.Debug(). + Str("Contract Address", triggerContract.Address().Hex()). + Int("Number", i+1). + Int("Out Of", u.NumberOfUpkeeps). + Msg("Deployed Automation Log Trigger Emitter Contract") + } + err = chainClient.WaitForEvents() + require.NoError(t, err, "Failed waiting for contracts to deploy") } - err = chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for contracts to deploy") - for i, consumerContract := range consumerContracts { logTriggerConfigStruct := automation_utils_2_1.LogTriggerConfig{ - ContractAddress: triggerContracts[i].Address(), - FilterSelector: 0, - Topic0: emitterABI.Events["Log1"].ID, - Topic1: bytes0, + ContractAddress: triggerAddresses[i], + FilterSelector: 1, + Topic0: emitterABI.Events["Log4"].ID, + Topic1: bytes1, Topic2: bytes0, Topic3: bytes0, } @@ -379,18 +462,29 @@ func TestLogTrigger(t *testing.T) { require.NoError(t, err, "Error encoding log trigger config") l.Debug().Bytes("Encoded Log Trigger Config", encodedLogTriggerConfig).Msg("Encoded Log Trigger Config") + checkDataStruct := simple_log_upkeep_counter_wrapper.CheckData{ + CheckBurnAmount: loadConfigs[i].CheckBurnAmount, + PerformBurnAmount: loadConfigs[i].PerformBurnAmount, + EventSig: bytes1, + } + + encodedCheckDataStruct, err := consumerABI.Methods["_checkDataConfig"].Inputs.Pack(&checkDataStruct) + require.NoError(t, err, "Error encoding check data struct") + l.Debug().Bytes("Encoded Check Data Struct", encodedCheckDataStruct).Msg("Encoded Check Data Struct") + upkeepConfig := automationv2.UpkeepConfig{ UpkeepName: fmt.Sprintf("LogTriggerUpkeep-%d", i), EncryptedEmail: []byte("test@mail.com"), UpkeepContract: common.HexToAddress(consumerContract.Address()), - GasLimit: automationDefaultUpkeepGasLimit, + GasLimit: loadConfigs[i].UpkeepGasLimit, AdminAddress: common.HexToAddress(chainClient.GetDefaultWallet().Address()), TriggerType: uint8(1), - CheckData: []byte("0"), + CheckData: encodedCheckDataStruct, TriggerConfig: encodedLogTriggerConfig, OffchainConfig: []byte("0"), FundingAmount: automationDefaultLinkFunds, } + l.Debug().Interface("Upkeep Config", upkeepConfig).Msg("Upkeep Config") upkeepConfigs = append(upkeepConfigs, upkeepConfig) } @@ -413,35 +507,58 @@ func TestLogTrigger(t *testing.T) { p := wasp.NewProfile() + configs := make([]LogTriggerConfig, 0) + var numberOfEventsEmitted int64 + var numberOfEventsEmittedPerSec int64 + for i, triggerContract := range triggerContracts { - g, err := wasp.NewGenerator(&wasp.Config{ - T: t, - LoadType: wasp.RPS, - GenName: fmt.Sprintf("log_trigger_gen_%s", triggerContract.Address().String()), - CallTimeout: time.Second * 10, - Schedule: wasp.Plain( - 1, - loadDuration, - ), - Gun: NewLogTriggerUser( - triggerContract, - consumerContracts[i], - l, - numberOfEvents, - ), - CallResultBufLen: 1000000, - }) - p.Add(g, err) + c := LogTriggerConfig{ + Address: triggerContract.Address().String(), + NumberOfEvents: loadConfigs[i].NumberOfEvents, + NumberOfSpamMatchingEvents: loadConfigs[i].NumberOfSpamMatchingEvents, + NumberOfSpamNonMatchingEvents: loadConfigs[i].NumberOfSpamNonMatchingEvents, + } + numberOfEventsEmittedPerSec = numberOfEventsEmittedPerSec + loadConfigs[i].NumberOfEvents + configs = append(configs, c) } - l.Info().Msg("Starting load generators") - startTime := time.Now() - err = sendSlackNotification("Started", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes), - strconv.FormatInt(startTime.UnixMilli(), 10), "now", - []slack.Block{extraBlockWithText("\bTest Config\b\n```" + testConfig + "```")}) + endTimeTestSetup := time.Now() + testSetupDuration := endTimeTestSetup.Sub(startTimeTestSetup) + l.Info(). + Str("END_TIME", endTimeTestSetup.String()). + Str("Duration", testSetupDuration.String()). + Msg("Test setup ended") + + ts, err := sendSlackNotification("Started", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes), + strconv.FormatInt(startTimeTestSetup.UnixMilli(), 10), "now", + []slack.Block{extraBlockWithText("\bTest Config\b\n```" + testConfig + "```")}, slack.MsgOptionBlocks()) if err != nil { l.Error().Err(err).Msg("Error sending slack notification") } + + g, err := wasp.NewGenerator(&wasp.Config{ + T: t, + LoadType: wasp.RPS, + GenName: "log_trigger_gen", + CallTimeout: time.Minute * 3, + Schedule: wasp.Plain( + 1, + loadDuration, + ), + Gun: NewLogTriggerUser( + l, + configs, + cEVMClient, + multicallAddress.Hex(), + ), + CallResultBufLen: 1000, + }) + p.Add(g, err) + + startTimeTestEx := time.Now() + l.Info().Str("START_TIME", startTimeTestEx.String()).Msg("Test execution started") + + l.Info().Msg("Starting load generators") _, err = p.Run(true) require.NoError(t, err, "Error running load generators") @@ -449,22 +566,25 @@ func TestLogTrigger(t *testing.T) { l.Info().Str("STOP_WAIT_TIME", StopWaitTime.String()).Msg("Waiting for upkeeps to be performed") time.Sleep(StopWaitTime) l.Info().Msg("Finished waiting 60s for upkeeps to be performed") - endTime := time.Now() - testDuration := endTime.Sub(startTime) - l.Info().Str("Duration", testDuration.String()).Msg("Test Duration") + endTimeTestEx := time.Now() + testExDuration := endTimeTestEx.Sub(startTimeTestEx) + l.Info(). + Str("END_TIME", endTimeTestEx.String()). + Str("Duration", testExDuration.String()). + Msg("Test execution ended") + + l.Info().Str("Duration", testExDuration.String()).Msg("Test Execution Duration") endBlock, err := chainClient.LatestBlockNumber(ctx) require.NoError(t, err, "Error getting latest block number") l.Info().Uint64("Starting Block", startBlock).Uint64("Ending Block", endBlock).Msg("Test Block Range") - upkeepDelays := make([][]int64, 0) - var numberOfEventsEmitted int - var batchSize uint64 = 500 + startTimeTestReport := time.Now() + l.Info().Str("START_TIME", startTimeTestReport.String()).Msg("Test reporting started") - for _, gen := range p.Generators { - numberOfEventsEmitted += len(gen.GetData().OKData.Data) - } - numberOfEventsEmitted = numberOfEventsEmitted * numberOfEvents - l.Info().Int("Number of Events Emitted", numberOfEventsEmitted).Msg("Number of Events Emitted") + upkeepDelaysFast := make([][]int64, 0) + upkeepDelaysRecovery := make([][]int64, 0) + + var batchSize uint64 = 500 if endBlock-startBlock < batchSize { batchSize = endBlock - startBlock @@ -500,7 +620,7 @@ func TestLogTrigger(t *testing.T) { timeout = time.Duration(math.Min(float64(timeout)*2, float64(2*time.Minute))) continue } - l.Info(). + l.Debug(). Interface("FilterQuery", filterQuery). Str("Contract Address", consumerContract.Address()). Str("Timeout", timeout.String()). @@ -510,7 +630,8 @@ func TestLogTrigger(t *testing.T) { } if len(logs) > 0 { - delay := make([]int64, 0) + delayFast := make([]int64, 0) + delayRecovery := make([]int64, 0) for _, log := range logs { eventDetails, err := consumerABI.EventByID(log.Topics[0]) require.NoError(t, err, "Error getting event details") @@ -521,45 +642,137 @@ func TestLogTrigger(t *testing.T) { if eventDetails.Name == "PerformingUpkeep" { parsedLog, err := consumer.ParsePerformingUpkeep(log) require.NoError(t, err, "Error parsing log") - delay = append(delay, parsedLog.TimeToPerform.Int64()) + if parsedLog.IsRecovered { + delayRecovery = append(delayRecovery, parsedLog.TimeToPerform.Int64()) + } else { + delayFast = append(delayFast, parsedLog.TimeToPerform.Int64()) + } + } + } + upkeepDelaysFast = append(upkeepDelaysFast, delayFast) + upkeepDelaysRecovery = append(upkeepDelaysRecovery, delayRecovery) + } + } + + for _, triggerContract := range triggerContracts { + var ( + logs []types.Log + address = triggerContract.Address() + timeout = 5 * time.Second + ) + for fromBlock := startBlock; fromBlock < endBlock; fromBlock += batchSize + 1 { + filterQuery := geth.FilterQuery{ + Addresses: []common.Address{address}, + FromBlock: big.NewInt(0).SetUint64(fromBlock), + ToBlock: big.NewInt(0).SetUint64(fromBlock + batchSize), + Topics: [][]common.Hash{{emitterABI.Events["Log4"].ID}, {bytes1}, {bytes1}}, + } + err = fmt.Errorf("initial error") // to ensure our for loop runs at least once + for err != nil { + var ( + logsInBatch []types.Log + ) + ctx2, cancel := context.WithTimeout(ctx, timeout) + logsInBatch, err = chainClient.FilterLogs(ctx2, filterQuery) + cancel() + if err != nil { + l.Error().Err(err). + Interface("FilterQuery", filterQuery). + Str("Contract Address", triggerContract.Address().Hex()). + Str("Timeout", timeout.String()). + Msg("Error getting logs") + timeout = time.Duration(math.Min(float64(timeout)*2, float64(2*time.Minute))) + continue } + l.Debug(). + Interface("FilterQuery", filterQuery). + Str("Contract Address", triggerContract.Address().Hex()). + Str("Timeout", timeout.String()). + Msg("Collected logs") + logs = append(logs, logsInBatch...) } - upkeepDelays = append(upkeepDelays, delay) } + numberOfEventsEmitted = numberOfEventsEmitted + int64(len(logs)) } - l.Info().Interface("Upkeep Delays", upkeepDelays).Msg("Upkeep Delays") + l.Info().Int64("Number of Events Emitted", numberOfEventsEmitted).Msg("Number of Events Emitted") + + l.Info(). + Interface("Upkeep Delays Fast", upkeepDelaysFast). + Interface("Upkeep Delays Recovered", upkeepDelaysRecovery). + Msg("Upkeep Delays") var allUpkeepDelays []int64 + var allUpkeepDelaysFast []int64 + var allUpkeepDelaysRecovery []int64 - for _, upkeepDelay := range upkeepDelays { + for _, upkeepDelay := range upkeepDelaysFast { allUpkeepDelays = append(allUpkeepDelays, upkeepDelay...) + allUpkeepDelaysFast = append(allUpkeepDelaysFast, upkeepDelay...) } - avg, median, ninetyPct, ninetyNinePct, maximum := testreporters.IntListStats(allUpkeepDelays) - eventsMissed := numberOfEventsEmitted - len(allUpkeepDelays) + for _, upkeepDelay := range upkeepDelaysRecovery { + allUpkeepDelays = append(allUpkeepDelays, upkeepDelay...) + allUpkeepDelaysRecovery = append(allUpkeepDelaysRecovery, upkeepDelay...) + } + + avgF, medianF, ninetyPctF, ninetyNinePctF, maximumF := testreporters.IntListStats(allUpkeepDelaysFast) + avgR, medianR, ninetyPctR, ninetyNinePctR, maximumR := testreporters.IntListStats(allUpkeepDelaysRecovery) + eventsMissed := (numberOfEventsEmitted) - int64(len(allUpkeepDelays)) percentMissed := float64(eventsMissed) / float64(numberOfEventsEmitted) * 100 l.Info(). - Float64("Average", avg).Int64("Median", median). - Int64("90th Percentile", ninetyPct).Int64("99th Percentile", ninetyNinePct). - Int64("Max", maximum).Msg("Upkeep Delays in seconds") - + Float64("Average", avgF).Int64("Median", medianF). + Int64("90th Percentile", ninetyPctF).Int64("99th Percentile", ninetyNinePctF). + Int64("Max", maximumF).Msg("Upkeep Delays Fast Execution in seconds") + l.Info(). + Float64("Average", avgR).Int64("Median", medianR). + Int64("90th Percentile", ninetyPctR).Int64("99th Percentile", ninetyNinePctR). + Int64("Max", maximumR).Msg("Upkeep Delays Recovery Execution in seconds") l.Info(). Int("Total Perform Count", len(allUpkeepDelays)). - Int("Total Events Emitted", numberOfEventsEmitted). - Int("Total Events Missed", eventsMissed). + Int("Perform Count Fast Execution", len(allUpkeepDelaysFast)). + Int("Perform Count Recovery Execution", len(allUpkeepDelaysRecovery)). + Int64("Total Events Emitted", numberOfEventsEmitted). + Int64("Total Events Missed", eventsMissed). Float64("Percent Missed", percentMissed). Msg("Test completed") - testReport := fmt.Sprintf("Upkeep Delays in seconds\nAverage: %f\nMedian: %d\n90th Percentile: %d\n"+ - "99th Percentile: %d\nMax: %d\nTotal Perform Count: %d\n\nTotal Events Emitted: %d\nTotal Events Missed: %d\n"+ - "Percent Missed: %f\nTest Duration: %s\n", - avg, median, ninetyPct, ninetyNinePct, maximum, len(allUpkeepDelays), numberOfEventsEmitted, - eventsMissed, percentMissed, testDuration.String()) + testReportFormat := `Upkeep Delays in seconds - Fast Execution +Average: %f +Median: %d +90th Percentile: %d +99th Percentile: %d +Max: %d + +Upkeep Delays in seconds - Recovery Execution +Average: %f +Median: %d +90th Percentile: %d +99th Percentile: %d +Max: %d + +Total Perform Count: %d +Perform Count Fast Execution: %d +Perform Count Recovery Execution: %d +Total Log Triggering Events Emitted: %d +Total Events Missed: %d +Percent Missed: %f +Test Duration: %s` + + endTimeTestReport := time.Now() + testReDuration := endTimeTestReport.Sub(startTimeTestReport) + l.Info(). + Str("END_TIME", endTimeTestReport.String()). + Str("Duration", testReDuration.String()). + Msg("Test reporting ended") + + testReport := fmt.Sprintf(testReportFormat, avgF, medianF, ninetyPctF, ninetyNinePctF, maximumF, + avgR, medianR, ninetyPctR, ninetyNinePctR, maximumR, len(allUpkeepDelays), len(allUpkeepDelaysFast), + len(allUpkeepDelaysRecovery), numberOfEventsEmitted, eventsMissed, percentMissed, testExDuration.String()) - err = sendSlackNotification("Finished", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes), - strconv.FormatInt(startTime.UnixMilli(), 10), strconv.FormatInt(endTime.UnixMilli(), 10), - []slack.Block{extraBlockWithText("\bTest Report\b\n```" + testReport + "```")}) + _, err = sendSlackNotification("Finished", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes), + strconv.FormatInt(startTimeTestSetup.UnixMilli(), 10), strconv.FormatInt(time.Now().UnixMilli(), 10), + []slack.Block{extraBlockWithText("\bTest Report\b\n```" + testReport + "```")}, slack.MsgOptionTS(ts)) if err != nil { l.Error().Err(err).Msg("Error sending slack notification") } diff --git a/integration-tests/load/automationv2_1/gun.go b/integration-tests/load/automationv2_1/gun.go index a2863a6064b..c80c9cf7cc1 100644 --- a/integration-tests/load/automationv2_1/gun.go +++ b/integration-tests/load/automationv2_1/gun.go @@ -1,43 +1,104 @@ package automationv2_1 import ( + "math/big" + "sync" + "github.com/rs/zerolog" "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) +type LogTriggerConfig struct { + Address string + NumberOfEvents int64 + NumberOfSpamMatchingEvents int64 + NumberOfSpamNonMatchingEvents int64 +} + type LogTriggerGun struct { - triggerContract contracts.LogEmitter - upkeepContract contracts.KeeperConsumer - logger zerolog.Logger - numberOfEvents int + data [][]byte + addresses []string + multiCallAddress string + evmClient blockchain.EVMClient + logger zerolog.Logger +} + +func generateCallData(int1 int64, int2 int64, count int64) []byte { + abi, err := log_emitter.LogEmitterMetaData.GetAbi() + if err != nil { + panic(err) + } + data, err := abi.Pack("EmitLog4", big.NewInt(int1), big.NewInt(int2), big.NewInt(count)) + if err != nil { + panic(err) + } + return data } func NewLogTriggerUser( - triggerContract contracts.LogEmitter, - upkeepContract contracts.KeeperConsumer, logger zerolog.Logger, - numberOfEvents int, + TriggerConfigs []LogTriggerConfig, + evmClient blockchain.EVMClient, + multicallAddress string, ) *LogTriggerGun { + var data [][]byte + var addresses []string + + for _, c := range TriggerConfigs { + if c.NumberOfEvents > 0 { + d := generateCallData(1, 1, c.NumberOfEvents) + data = append(data, d) + addresses = append(addresses, c.Address) + } + if c.NumberOfSpamMatchingEvents > 0 { + d := generateCallData(1, 2, c.NumberOfSpamMatchingEvents) + data = append(data, d) + addresses = append(addresses, c.Address) + } + if c.NumberOfSpamNonMatchingEvents > 0 { + d := generateCallData(2, 2, c.NumberOfSpamNonMatchingEvents) + data = append(data, d) + addresses = append(addresses, c.Address) + } + } + return &LogTriggerGun{ - triggerContract: triggerContract, - upkeepContract: upkeepContract, - logger: logger, - numberOfEvents: numberOfEvents, + addresses: addresses, + data: data, + logger: logger, + multiCallAddress: multicallAddress, + evmClient: evmClient, } } -func (m *LogTriggerGun) Call(_ *wasp.Generator) *wasp.CallResult { - m.logger.Debug().Str("Trigger address", m.triggerContract.Address().String()).Msg("Triggering upkeep") - payload := make([]int, 0) - for i := 0; i < m.numberOfEvents; i++ { - payload = append(payload, 1) +func (m *LogTriggerGun) Call(_ *wasp.Generator) *wasp.Response { + var wg sync.WaitGroup + var dividedData [][][]byte + d := m.data + chunkSize := 100 + for i := 0; i < len(d); i += chunkSize { + end := i + chunkSize + if end > len(d) { + end = len(d) + } + dividedData = append(dividedData, d[i:end]) } - _, err := m.triggerContract.EmitLogInts(payload) - if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + for _, a := range dividedData { + wg.Add(1) + go func(a [][]byte, m *LogTriggerGun) *wasp.Response { + defer wg.Done() + _, err := contracts.MultiCallLogTriggerLoadGen(m.evmClient, m.multiCallAddress, m.addresses, a) + if err != nil { + return &wasp.Response{Error: err.Error(), Failed: true} + } + return &wasp.Response{} + }(a, m) } - - return &wasp.CallResult{} + wg.Wait() + return &wasp.Response{} } diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go index 3c08199a9cf..68ac909af90 100644 --- a/integration-tests/load/automationv2_1/helpers.go +++ b/integration-tests/load/automationv2_1/helpers.go @@ -31,7 +31,7 @@ func extraBlockWithText(text string) slack.Block { } func sendSlackNotification(header string, l zerolog.Logger, namespace string, numberOfNodes, - startingTime string, endingTime string, extraBlocks []slack.Block) error { + startingTime string, endingTime string, extraBlocks []slack.Block, msgOption slack.MsgOption) (string, error) { slackClient := slack.New(reportModel.SlackAPIKey) headerText := ":chainlink-keepers: Automation Load Test " + header + " :white_check_mark:" @@ -65,7 +65,7 @@ func sendSlackNotification(header string, l zerolog.Logger, namespace string, nu notificationBlocks = append(notificationBlocks, extraBlocks...) } - ts, err := reportModel.SendSlackMessage(slackClient, slack.MsgOptionBlocks(notificationBlocks...)) + ts, err := reportModel.SendSlackMessage(slackClient, slack.MsgOptionBlocks(notificationBlocks...), msgOption) l.Info().Str("ts", ts).Msg("Sent Slack Message") - return err + return ts, err } diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go index 3dafb458a50..62fe80ed02c 100644 --- a/integration-tests/load/functions/gateway_gun.go +++ b/integration-tests/load/functions/gateway_gun.go @@ -37,7 +37,7 @@ func NewGatewaySecretsSetGun(cfg *PerformanceConfig, method string, pKey *ecdsa. } } -func callSecretsSet(m *GatewaySecretsSetGun) *wasp.CallResult { +func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { randNum := strconv.Itoa(rand.Intn(100000)) randSlot := uint(rand.Intn(5)) version := uint64(time.Now().UnixNano()) @@ -57,7 +57,7 @@ func callSecretsSet(m *GatewaySecretsSetGun) *wasp.CallResult { secret, ) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } _, _, err = UploadS4Secrets(m.Resty, &S4SecretsCfg{ GatewayURL: m.Cfg.Common.GatewayURL, @@ -71,12 +71,12 @@ func callSecretsSet(m *GatewaySecretsSetGun) *wasp.CallResult { S4SetPayload: secrets, }) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } - return &wasp.CallResult{} + return &wasp.Response{} } -func callSecretsList(m *GatewaySecretsSetGun) *wasp.CallResult { +func callSecretsList(m *GatewaySecretsSetGun) *wasp.Response { randNum := strconv.Itoa(rand.Intn(100000)) randSlot := uint(rand.Intn(5)) version := uint64(time.Now().UnixNano()) @@ -92,14 +92,14 @@ func callSecretsList(m *GatewaySecretsSetGun) *wasp.CallResult { S4SetVersion: version, S4SetExpirationPeriod: expiration, }); err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } - return &wasp.CallResult{} + return &wasp.Response{} } // Call implements example gun call, assertions on response bodies should be done here -func (m *GatewaySecretsSetGun) Call(_ *wasp.Generator) *wasp.CallResult { - var res *wasp.CallResult +func (m *GatewaySecretsSetGun) Call(_ *wasp.Generator) *wasp.Response { + var res *wasp.Response switch m.Method { case "secrets_set": res = callSecretsSet(m) diff --git a/integration-tests/load/functions/request_gun.go b/integration-tests/load/functions/request_gun.go index bd4cf5f35aa..6b79a2f19ee 100644 --- a/integration-tests/load/functions/request_gun.go +++ b/integration-tests/load/functions/request_gun.go @@ -48,7 +48,7 @@ func NewSingleFunctionCallGun( } } -func (m *SingleFunctionCallGun) callReal() *wasp.CallResult { +func (m *SingleFunctionCallGun) callReal() *wasp.Response { err := m.ft.LoadTestClient.SendRequestWithDONHostedSecrets( m.times, m.source, @@ -59,12 +59,12 @@ func (m *SingleFunctionCallGun) callReal() *wasp.CallResult { m.jobId, ) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } - return &wasp.CallResult{} + return &wasp.Response{} } -func (m *SingleFunctionCallGun) callWithSecrets() *wasp.CallResult { +func (m *SingleFunctionCallGun) callWithSecrets() *wasp.Response { err := m.ft.LoadTestClient.SendRequestWithDONHostedSecrets( m.times, m.source, @@ -75,12 +75,12 @@ func (m *SingleFunctionCallGun) callWithSecrets() *wasp.CallResult { m.jobId, ) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } - return &wasp.CallResult{} + return &wasp.Response{} } -func (m *SingleFunctionCallGun) callWithHttp() *wasp.CallResult { +func (m *SingleFunctionCallGun) callWithHttp() *wasp.Response { err := m.ft.LoadTestClient.SendRequest( m.times, m.source, @@ -90,13 +90,13 @@ func (m *SingleFunctionCallGun) callWithHttp() *wasp.CallResult { m.jobId, ) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } - return &wasp.CallResult{} + return &wasp.Response{} } // Call implements example gun call, assertions on response bodies should be done here -func (m *SingleFunctionCallGun) Call(_ *wasp.Generator) *wasp.CallResult { +func (m *SingleFunctionCallGun) Call(_ *wasp.Generator) *wasp.Response { switch m.mode { case ModeSecretsOnlyPayload: return m.callWithSecrets() diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index c0be47ca836..e96eac3cf82 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" + chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) type FunctionsTest struct { diff --git a/integration-tests/load/ocr/README.md b/integration-tests/load/ocr/README.md index 3c231b50278..61951ba700f 100644 --- a/integration-tests/load/ocr/README.md +++ b/integration-tests/load/ocr/README.md @@ -1,21 +1,12 @@ -# OCR Load tests +### OCR Load tests ## Setup - These tests can connect to any cluster create with [chainlink-cluster](../../../charts/chainlink-cluster/README.md) -<<<<<<< HEAD -Create your cluster - -```sh -kubectl create ns my-cluster -devspace use namespace my-cluster -======= Create your cluster, if you already have one just use `kubefwd` ``` kubectl create ns cl-cluster devspace use namespace cl-cluster ->>>>>>> 06656fac80999d1539e16951a54b87c6df13a9c7 devspace deploy sudo kubefwd svc -n cl-cluster ``` @@ -26,7 +17,7 @@ If you haven't changed anything in [devspace.yaml](../../../charts/chainlink-clu ## Usage -```sh +``` export LOKI_TOKEN=... export LOKI_URL=... @@ -34,4 +25,4 @@ go test -v -run TestOCRLoad go test -v -run TestOCRVolume ``` -Check test configuration [here](config.toml) +Check test configuration [here](config.toml) \ No newline at end of file diff --git a/integration-tests/load/ocr/gun.go b/integration-tests/load/ocr/gun.go index a2eb1ff2200..ed92e328024 100644 --- a/integration-tests/load/ocr/gun.go +++ b/integration-tests/load/ocr/gun.go @@ -30,7 +30,7 @@ func NewGun(l zerolog.Logger, cc blockchain.EVMClient, ocrInstances []contracts. } } -func (m *Gun) Call(_ *wasp.Generator) *wasp.CallResult { +func (m *Gun) Call(_ *wasp.Generator) *wasp.Response { m.roundNum.Add(1) requestedRound := m.roundNum.Load() m.l.Info(). @@ -39,17 +39,17 @@ func (m *Gun) Call(_ *wasp.Generator) *wasp.CallResult { Msg("starting new round") err := m.ocrInstances[0].RequestNewRound() if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } for { time.Sleep(5 * time.Second) lr, err := m.ocrInstances[0].GetLatestRound(context.Background()) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } m.l.Info().Interface("LatestRound", lr).Msg("latest round") if lr.RoundId.Int64() >= requestedRound { - return &wasp.CallResult{} + return &wasp.Response{} } } } diff --git a/integration-tests/load/ocr/vu.go b/integration-tests/load/ocr/vu.go index 96be77c701a..d113f7eb3f9 100644 --- a/integration-tests/load/ocr/vu.go +++ b/integration-tests/load/ocr/vu.go @@ -105,17 +105,17 @@ func (m *VU) Call(l *wasp.Generator) { Msg("starting new round") err := m.ocrInstances[0].RequestNewRound() if err != nil { - l.ResponsesChan <- &wasp.CallResult{Error: err.Error(), Failed: true} + l.ResponsesChan <- &wasp.Response{Error: err.Error(), Failed: true} } for { time.Sleep(5 * time.Second) lr, err := m.ocrInstances[0].GetLatestRound(context.Background()) if err != nil { - l.ResponsesChan <- &wasp.CallResult{Error: err.Error(), Failed: true} + l.ResponsesChan <- &wasp.Response{Error: err.Error(), Failed: true} } m.l.Info().Interface("LatestRound", lr).Msg("latest round") if lr.RoundId.Int64() >= requestedRound { - l.ResponsesChan <- &wasp.CallResult{} + l.ResponsesChan <- &wasp.Response{} } } } diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index 8a5eb3c66de..fd8cb6195e8 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -38,7 +38,7 @@ func NewSingleHashGun( } // Call implements example gun call, assertions on response bodies should be done here -func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.CallResult { +func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { //todo - should work with multiple consumers and consumers having different keyhashes and wallets //randomly increase/decrease randomness request count per TX @@ -56,9 +56,9 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.CallResult { m.logger, ) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } - return &wasp.CallResult{} + return &wasp.Response{} } func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index ec0f945870d..c48f3488594 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -184,7 +184,6 @@ func TestVRFV2Performance(t *testing.T) { l.Error().Err(err).Msg("Error cleaning up test environment") } }). - WithLogStream(). Build() require.NoError(t, err, "error creating test env") diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 8ab278b73e9..77b60e30002 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -38,7 +38,7 @@ func NewSingleHashGun( } // Call implements example gun call, assertions on response bodies should be done here -func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.CallResult { +func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { //todo - should work with multiple consumers and consumers having different keyhashes and wallets //randomly increase/decrease randomness request count per TX @@ -58,9 +58,9 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.CallResult { m.logger, ) if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } - return &wasp.CallResult{} + return &wasp.Response{} } func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 6d298e075f0..74be537c753 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -189,7 +189,6 @@ func TestVRFV2PlusPerformance(t *testing.T) { l.Error().Err(err).Msg("Error cleaning up test environment") } }). - WithLogStream(). Build() require.NoError(t, err, "error creating test env") @@ -207,8 +206,6 @@ func TestVRFV2PlusPerformance(t *testing.T) { vrfv2PlusConfig, linkToken, mockETHLinkFeed, - //register proving key against EOA address in order to return funds to this address - env.EVMClient.GetDefaultWallet().Address(), 0, 1, vrfv2PlusConfig.NumberOfSubToCreate, diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index 97db2374bf3..6603fc1685d 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -1,12 +1,12 @@ package migration import ( - "os" "testing" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" ) @@ -14,6 +14,7 @@ func TestVersionUpgrade(t *testing.T) { t.Parallel() env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithStandardCleanup(). WithGeth(). WithCLNodes(1). Build() @@ -23,16 +24,11 @@ func TestVersionUpgrade(t *testing.T) { require.NoError(t, err, "Error getting upgrade image") upgradeVersion, err := osutil.GetEnv("UPGRADE_VERSION") require.NoError(t, err, "Error getting upgrade version") - - _ = os.Setenv("CHAINLINK_IMAGE", upgradeImage) - _ = os.Setenv("CHAINLINK_VERSION", upgradeVersion) - - // just restarting CL container with the same name, DB is still the same - // // [Database] // MigrateOnStartup = true // // by default - err = env.ClCluster.Nodes[0].Restart(env.ClCluster.Nodes[0].NodeConfig) + err = env.ClCluster.Nodes[0].UpgradeVersion(upgradeImage, upgradeVersion) require.NoError(t, err) + } diff --git a/integration-tests/scripts/buildTestMatrixList.sh b/integration-tests/scripts/buildTestMatrixList.sh index 7f058b5b659..f02362aa47a 100755 --- a/integration-tests/scripts/buildTestMatrixList.sh +++ b/integration-tests/scripts/buildTestMatrixList.sh @@ -40,24 +40,26 @@ jq -c '.tests[]' ${JSONFILE} | while read -r test; do effective_node_count=${node_count:-$NODE_COUNT} subTests=$(echo ${test} | jq -r '.run[]?.name // empty') output="" + + if [ $COUNTER -ne 1 ]; then + echo -n "," + fi # Loop through subtests, if any, and print in the desired format if [ -n "$subTests" ]; then + subTestString="" + subTestCounter=1 for subTest in $subTests; do - if [ $COUNTER -ne 1 ]; then - echo -n "," + if [ $subTestCounter -ne 1 ]; then + subTestString+="|" fi - matrix_output $COUNTER $MATRIX_JOB_NAME "${testName}/${subTest}" ${effective_node_label} ${effective_node_count} - ((COUNTER++)) + subTestString+="${testName}\/${subTest}" + ((subTestCounter++)) done - else - if [ $COUNTER -ne 1 ]; then - echo -n "," - fi - matrix_output $COUNTER $MATRIX_JOB_NAME "${testName}" ${effective_node_label} ${effective_node_count} - ((COUNTER++)) + testName="${subTestString}" fi - + matrix_output $COUNTER $MATRIX_JOB_NAME "${testName}" ${effective_node_label} ${effective_node_count} + ((COUNTER++)) done > "./tmpout.json" OUTPUT=$(cat ./tmpout.json) echo "[${OUTPUT}]" diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 1dbfc78ec87..70b6a8f6856 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -90,9 +90,9 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { "registry_2_1_with_logtrigger_and_mercury_v02": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) @@ -168,7 +168,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) } - }, "5m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer + }, "10m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer l.Info().Msgf("Total time taken to get 5 performs for each upkeep: %s", time.Since(startTime)) @@ -400,9 +400,9 @@ func TestAutomationAddFunds(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() a := setupAutomationTestDocker( @@ -557,9 +557,9 @@ func TestAutomationRegisterUpkeep(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) @@ -641,9 +641,9 @@ func TestAutomationPauseRegistry(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() a := setupAutomationTestDocker( @@ -710,9 +710,9 @@ func TestAutomationKeeperNodesDown(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) @@ -810,9 +810,9 @@ func TestAutomationPerformSimulation(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() a := setupAutomationTestDocker( @@ -873,9 +873,9 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) @@ -987,9 +987,9 @@ func TestUpdateCheckData(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for n, rv := range registryVersions { - name := n - registryVersion := rv + for name, registryVersion := range registryVersions { + name := name + registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) @@ -1097,7 +1097,6 @@ func setupAutomationTestDocker( WithMockAdapter(). WithFunding(big.NewFloat(testConfig.ChainlinkNodeFunding)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "Error deploying test environment for Mercury") env.ParallelTransactions(true) diff --git a/integration-tests/smoke/automation_test.go_test_list.json b/integration-tests/smoke/automation_test.go_test_list.json index ad6de592ede..b88684599c7 100644 --- a/integration-tests/smoke/automation_test.go_test_list.json +++ b/integration-tests/smoke/automation_test.go_test_list.json @@ -2,51 +2,73 @@ "tests": [ { "name": "TestAutomationBasic", - "label": "ubuntu20.04-32cores-128GB", - "nodes": 6 + "label": "ubuntu-latest", + "nodes": 2, + "run":[ + {"name":"registry_2_0"}, + {"name":"registry_2_1_conditional"} + ] + }, + { + "name": "TestAutomationBasic", + "label": "ubuntu-latest", + "nodes": 2, + "run":[ + {"name":"registry_2_1_logtrigger"}, + {"name":"registry_2_1_with_mercury_v02"} + ] + }, + { + "name": "TestAutomationBasic", + "label": "ubuntu-latest", + "nodes": 2, + "run":[ + {"name":"registry_2_1_with_mercury_v03"}, + {"name":"registry_2_1_with_logtrigger_and_mercury_v02"} + ] }, { "name": "TestSetUpkeepTriggerConfig" }, { "name": "TestAutomationAddFunds", - "label": "ubuntu20.04-32cores-128GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestAutomationPauseUnPause", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestAutomationRegisterUpkeep", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestAutomationPauseRegistry", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestAutomationKeeperNodesDown", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestAutomationPerformSimulation", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestAutomationCheckPerformGasLimit", - "label": "ubuntu20.04-32cores-128GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestUpdateCheckData", - "label": "ubuntu20.04-32cores-128GB", + "label": "ubuntu-latest", "nodes": 2 } ] -} +} \ No newline at end of file diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 751c2867676..df1b85882e9 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -25,7 +25,6 @@ func TestCronBasic(t *testing.T) { WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) @@ -72,7 +71,6 @@ func TestCronJobReplacement(t *testing.T) { WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 828350a9422..345971e8922 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -31,7 +31,6 @@ func TestFluxBasic(t *testing.T) { WithMockAdapter(). WithCLNodes(3). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index c71c6e31516..fd8dfc780af 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -26,7 +26,6 @@ func TestForwarderOCRBasic(t *testing.T) { WithCLNodes(6). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) @@ -68,7 +67,7 @@ func TestForwarderOCRBasic(t *testing.T) { err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String()) require.NoError(t, err, "failed to setup forwarder jobs") - err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l) + err = actions.WatchNewRound(1, ocrInstances, env.EVMClient, l) require.NoError(t, err) err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") @@ -79,7 +78,7 @@ func TestForwarderOCRBasic(t *testing.T) { err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err) - err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l) + err = actions.WatchNewRound(2, ocrInstances, env.EVMClient, l) require.NoError(t, err) err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index c2e2b12e51d..90dc20a3898 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -35,7 +35,6 @@ func TestForwarderOCR2Basic(t *testing.T) { WithCLNodes(6). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) @@ -90,7 +89,7 @@ func TestForwarderOCR2Basic(t *testing.T) { err = actions.ConfigureOCRv2AggregatorContracts(env.EVMClient, ocrv2Config, ocrInstances) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") - err = actions.StartNewOCR2Round(1, ocrInstances, env.EVMClient, time.Minute*10, l) + err = actions.WatchNewOCR2Round(1, ocrInstances, env.EVMClient, time.Minute*10, l) require.NoError(t, err) answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -101,7 +100,7 @@ func TestForwarderOCR2Basic(t *testing.T) { ocrRoundVal := (5 + i) % 10 err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, ocrRoundVal) require.NoError(t, err) - err = actions.StartNewOCR2Round(int64(i), ocrInstances, env.EVMClient, time.Minute*10, l) + err = actions.WatchNewOCR2Round(int64(i), ocrInstances, env.EVMClient, time.Minute*10, l) require.NoError(t, err) answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 1bc416f0456..330d041c8f6 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -1113,7 +1113,6 @@ func setupKeeperTest(t *testing.T) ( WithCLNodeConfig(clNodeConfig). WithFunding(big.NewFloat(.5)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "Error deploying test environment") diff --git a/integration-tests/smoke/keeper_test.go_test_list.json b/integration-tests/smoke/keeper_test.go_test_list.json index b874bc65ee0..b2f4aa00659 100644 --- a/integration-tests/smoke/keeper_test.go_test_list.json +++ b/integration-tests/smoke/keeper_test.go_test_list.json @@ -2,42 +2,42 @@ "tests": [ { "name": "TestKeeperBasicSmoke", - "label": "ubuntu20.04-32cores-128GB", + "label": "ubuntu-latest", "nodes": 3 }, { "name": "TestKeeperBlockCountPerTurn", - "label": "ubuntu20.04-32cores-128GB", + "label": "ubuntu-latest", "nodes": 3 }, { "name": "TestKeeperSimulation", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 2 }, { "name": "TestKeeperCheckPerformGasLimit", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 3 }, { "name": "TestKeeperRegisterUpkeep", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 3 }, { "name": "TestKeeperAddFunds", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 3 }, { "name": "TestKeeperRemove", - "label": "ubuntu20.04-32cores-128GB", + "label": "ubuntu-latest", "nodes": 3 }, { "name": "TestKeeperPauseRegistry", - "label": "ubuntu20.04-16cores-64GB", + "label": "ubuntu-latest", "nodes": 2 }, { @@ -45,7 +45,7 @@ }, { "name": "TestKeeperNodeDown", - "label": "ubuntu20.04-32cores-128GB", + "label": "ubuntu-latest", "nodes": 3 }, { @@ -58,4 +58,4 @@ "name": "TestKeeperJobReplacement" } ] -} +} \ No newline at end of file diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index a1a37c3b18e..2603b6e9e6a 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -11,15 +11,111 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" + "github.com/smartcontractkit/chainlink/v2/core/config/env" ) // Tests a basic OCRv2 median feed func TestOCRv2Basic(t *testing.T) { t.Parallel() + + for _, test := range []struct { + name string + env map[string]string + }{ + {"legacy", map[string]string{string(env.MedianPluginCmd): ""}}, + {"plugins", map[string]string{string(env.MedianPluginCmd): "chainlink-feeds"}}, + } { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + l := logging.GetTestLogger(t) + + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + + env, err := test_env.NewCLTestEnvBuilder(). + WithTestInstance(t). + WithPrivateEthereumNetwork(network). + WithMockAdapter(). + WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), + node.WithOCR2(), + node.WithP2Pv2(), + node.WithTracing(), + )). + WithCLNodeOptions(test_env.WithNodeEnvVars(test.env)). + WithCLNodes(6). + WithFunding(big.NewFloat(.1)). + WithStandardCleanup(). + Build() + require.NoError(t, err) + + env.ParallelTransactions(true) + + nodeClients := env.ClCluster.NodeAPIs() + bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] + + linkToken, err := env.ContractDeployer.DeployLinkTokenContract() + require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") + + err = actions.FundChainlinkNodesLocal(workerNodes, env.EVMClient, big.NewFloat(.05)) + require.NoError(t, err, "Error funding Chainlink nodes") + + // Gather transmitters + var transmitters []string + for _, node := range workerNodes { + addr, err := node.PrimaryEthAddress() + if err != nil { + require.NoError(t, fmt.Errorf("error getting node's primary ETH address: %w", err)) + } + transmitters = append(transmitters, addr) + } + + ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() + aggregatorContracts, err := actions.DeployOCRv2Contracts(1, linkToken, env.ContractDeployer, transmitters, env.EVMClient, ocrOffchainOptions) + require.NoError(t, err, "Error deploying OCRv2 aggregator contracts") + + err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, env.EVMClient.GetChainID().Uint64(), false) + require.NoError(t, err, "Error creating OCRv2 jobs") + + ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) + require.NoError(t, err, "Error building OCRv2 config") + + err = actions.ConfigureOCRv2AggregatorContracts(env.EVMClient, ocrv2Config, aggregatorContracts) + require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") + + err = actions.WatchNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l) + require.NoError(t, err, "Error starting new OCR2 round") + roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(1)) + require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") + require.Equal(t, int64(5), roundData.Answer.Int64(), + "Expected latest answer from OCR contract to be 5 but got %d", + roundData.Answer.Int64(), + ) + + err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) + require.NoError(t, err) + err = actions.WatchNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l) + require.NoError(t, err) + + roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2)) + require.NoError(t, err, "Error getting latest OCR answer") + require.Equal(t, int64(10), roundData.Answer.Int64(), + "Expected latest answer from OCR contract to be 10 but got %d", + roundData.Answer.Int64(), + ) + }) + } +} + +// Tests that just calling requestNewRound() will properly induce more rounds +func TestOCRv2Request(t *testing.T) { + t.Parallel() l := logging.GetTestLogger(t) network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) @@ -37,7 +133,6 @@ func TestOCRv2Basic(t *testing.T) { WithCLNodes(6). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) @@ -75,7 +170,7 @@ func TestOCRv2Basic(t *testing.T) { err = actions.ConfigureOCRv2AggregatorContracts(env.EVMClient, ocrv2Config, aggregatorContracts) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") - err = actions.StartNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l) + err = actions.WatchNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l) require.NoError(t, err, "Error starting new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(1)) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") @@ -84,17 +179,18 @@ func TestOCRv2Basic(t *testing.T) { roundData.Answer.Int64(), ) - err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) - require.NoError(t, err) - err = actions.StartNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l) - require.NoError(t, err) - - roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2)) - require.NoError(t, err, "Error getting latest OCR answer") - require.Equal(t, int64(10), roundData.Answer.Int64(), - "Expected latest answer from OCR contract to be 10 but got %d", - roundData.Answer.Int64(), - ) + // Keep the mockserver value the same and continually request new rounds + for round := 2; round <= 4; round++ { + err = actions.StartNewOCR2Round(int64(round), aggregatorContracts, env.EVMClient, time.Minute*5, l) + require.NoError(t, err, "Error starting new OCR2 round") + roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(int64(round))) + require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") + require.Equal(t, int64(5), roundData.Answer.Int64(), + "Expected round %d answer from OCR contract to be 5 but got %d", + round, + roundData.Answer.Int64(), + ) + } } func TestOCRv2JobReplacement(t *testing.T) { @@ -112,7 +208,6 @@ func TestOCRv2JobReplacement(t *testing.T) { WithCLNodes(6). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) @@ -150,7 +245,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = actions.ConfigureOCRv2AggregatorContracts(env.EVMClient, ocrv2Config, aggregatorContracts) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") - err = actions.StartNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l) + err = actions.WatchNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l) require.NoError(t, err, "Error starting new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(1)) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") @@ -161,7 +256,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) require.NoError(t, err) - err = actions.StartNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l) + err = actions.WatchNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l) require.NoError(t, err) roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2)) @@ -180,7 +275,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 15, env.EVMClient.GetChainID().Uint64(), false) require.NoError(t, err, "Error creating OCRv2 jobs") - err = actions.StartNewOCR2Round(3, aggregatorContracts, env.EVMClient, time.Minute*3, l) + err = actions.WatchNewOCR2Round(3, aggregatorContracts, env.EVMClient, time.Minute*3, l) require.NoError(t, err, "Error starting new OCR2 round") roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(3)) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index ba158923812..5f091835894 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -27,7 +27,6 @@ func TestOCRBasic(t *testing.T) { WithCLNodes(6). WithFunding(big.NewFloat(.5)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) @@ -47,7 +46,7 @@ func TestOCRBasic(t *testing.T) { err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID()) require.NoError(t, err) - err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l) + err = actions.WatchNewRound(1, ocrInstances, env.EVMClient, l) require.NoError(t, err) answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -56,7 +55,7 @@ func TestOCRBasic(t *testing.T) { err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err) - err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l) + err = actions.WatchNewRound(2, ocrInstances, env.EVMClient, l) require.NoError(t, err) answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -94,7 +93,7 @@ func TestOCRJobReplacement(t *testing.T) { err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID()) require.NoError(t, err) - err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l) + err = actions.WatchNewRound(1, ocrInstances, env.EVMClient, l) require.NoError(t, err) answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -103,7 +102,7 @@ func TestOCRJobReplacement(t *testing.T) { err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err) - err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l) + err = actions.WatchNewRound(2, ocrInstances, env.EVMClient, l) require.NoError(t, err) answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -120,7 +119,7 @@ func TestOCRJobReplacement(t *testing.T) { err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID()) require.NoError(t, err) - err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l) + err = actions.WatchNewRound(1, ocrInstances, env.EVMClient, l) require.NoError(t, err) answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 5cc21a28c2c..dc08b19b16f 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -29,7 +29,6 @@ func TestRunLogBasic(t *testing.T) { WithCLNodes(1). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 0554bd34760..51ea3828cfd 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -29,7 +29,6 @@ func TestVRFBasic(t *testing.T) { WithCLNodes(1). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) env.ParallelTransactions(true) @@ -119,7 +118,6 @@ func TestVRFJobReplacement(t *testing.T) { WithCLNodes(1). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err) env.ParallelTransactions(true) diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index a8edb2c51d9..6f69b579a4a 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -4,19 +4,21 @@ import ( "context" "math/big" "testing" + "time" + "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/kelseyhightower/envconfig" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" ) @@ -37,7 +39,6 @@ func TestVRFv2Basic(t *testing.T) { WithCLNodes(1). WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "error creating test env") @@ -113,23 +114,262 @@ func TestVRFv2Basic(t *testing.T) { require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) + + t.Run("Oracle Withdraw", func(t *testing.T) { + testConfig := vrfv2Config + subIDsForOracleWithDraw, err := vrfv2_actions.CreateFundSubsAndAddConsumers( + env, + testConfig, + linkToken, + vrfv2Contracts.Coordinator, + vrfv2Contracts.LoadTestConsumers, + 1, + ) + require.NoError(t, err) + + subIDForOracleWithdraw := subIDsForOracleWithDraw[0] + + fulfilledEventLink, err := vrfv2_actions.RequestRandomnessAndWaitForFulfillment( + vrfv2Contracts.LoadTestConsumers[0], + vrfv2Contracts.Coordinator, + vrfv2Data, + subIDForOracleWithdraw, + testConfig.RandomnessRequestCountPerRequest, + testConfig, + testConfig.RandomWordsFulfilledEventTimeout, + l, + ) + require.NoError(t, err) + + amountToWithdrawLink := fulfilledEventLink.Payment + + defaultWalletBalanceLinkBeforeOracleWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) + require.NoError(t, err) + + l.Info(). + Str("Returning to", defaultWalletAddress). + Str("Amount", amountToWithdrawLink.String()). + Msg("Invoking Oracle Withdraw for LINK") + + err = vrfv2Contracts.Coordinator.OracleWithdraw(common.HexToAddress(defaultWalletAddress), amountToWithdrawLink) + require.NoError(t, err, "Error withdrawing LINK from coordinator to default wallet") + + err = env.EVMClient.WaitForEvents() + require.NoError(t, err, vrfv2_actions.ErrWaitTXsComplete) + + defaultWalletBalanceLinkAfterOracleWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) + require.NoError(t, err) + + require.Equal( + t, + 1, + defaultWalletBalanceLinkAfterOracleWithdraw.Cmp(defaultWalletBalanceLinkBeforeOracleWithdraw), + "LINK funds were not returned after oracle withdraw", + ) + }) + t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { + testConfig := vrfv2Config + subIDsForCancelling, err := vrfv2_actions.CreateFundSubsAndAddConsumers( + env, + testConfig, + linkToken, + vrfv2Contracts.Coordinator, + vrfv2Contracts.LoadTestConsumers, + 1, + ) + require.NoError(t, err) + subIDForCancelling := subIDsForCancelling[0] + + testWalletAddress, err := actions.GenerateWallet() + require.NoError(t, err) + + testWalletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), testWalletAddress.String()) + require.NoError(t, err) + + subscriptionForCancelling, err := vrfv2Contracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling) + require.NoError(t, err, "error getting subscription information") + + subBalanceLink := subscriptionForCancelling.Balance + + l.Info(). + Str("Subscription Amount Link", subBalanceLink.String()). + Uint64("Returning funds from SubID", subIDForCancelling). + Str("Returning funds to", testWalletAddress.String()). + Msg("Canceling subscription and returning funds to subscription owner") + + tx, err := vrfv2Contracts.Coordinator.CancelSubscription(subIDForCancelling, testWalletAddress) + require.NoError(t, err, "Error canceling subscription") + + subscriptionCanceledEvent, err := vrfv2Contracts.Coordinator.WaitForSubscriptionCanceledEvent([]uint64{subIDForCancelling}, time.Second*30) + require.NoError(t, err, "error waiting for subscription canceled event") + + cancellationTxReceipt, err := env.EVMClient.GetTxReceipt(tx.Hash()) + require.NoError(t, err, "error getting tx cancellation Tx Receipt") + + txGasUsed := new(big.Int).SetUint64(cancellationTxReceipt.GasUsed) + cancellationTxFeeWei := new(big.Int).Mul(txGasUsed, cancellationTxReceipt.EffectiveGasPrice) + + l.Info(). + Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()). + Str("Effective Gas Price", cancellationTxReceipt.EffectiveGasPrice.String()). + Uint64("Gas Used", cancellationTxReceipt.GasUsed). + Msg("Cancellation TX Receipt") + + l.Info(). + Str("Returned Subscription Amount Link", subscriptionCanceledEvent.Amount.String()). + Uint64("SubID", subscriptionCanceledEvent.SubId). + Str("Returned to", subscriptionCanceledEvent.To.String()). + Msg("Subscription Canceled Event") + + require.Equal(t, subBalanceLink, subscriptionCanceledEvent.Amount, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription") + + testWalletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), testWalletAddress.String()) + require.NoError(t, err) + + //Verify that sub was deleted from Coordinator + _, err = vrfv2Contracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling) + require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration") + + subFundsReturnedLinkActual := new(big.Int).Sub(testWalletBalanceLinkAfterSubCancelling, testWalletBalanceLinkBeforeSubCancelling) + + l.Info(). + Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()). + Str("Sub Funds Returned Actual - Link", subFundsReturnedLinkActual.String()). + Str("Sub Balance - Link", subBalanceLink.String()). + Msg("Sub funds returned") + + require.Equal(t, 0, subBalanceLink.Cmp(subFundsReturnedLinkActual), "Returned LINK funds are not equal to sub balance that was cancelled") + }) + + t.Run("Owner Canceling Sub And Returning Funds While Having Pending Requests", func(t *testing.T) { + testConfig := vrfv2Config + + // Underfund subscription to force fulfillments to fail + testConfig.SubscriptionFundingAmountLink = float64(0.000000000000000001) // 1 Juel + + subIDsForCancelling, err := vrfv2_actions.CreateFundSubsAndAddConsumers( + env, + testConfig, + linkToken, + vrfv2Contracts.Coordinator, + vrfv2Contracts.LoadTestConsumers, + 1, + ) + require.NoError(t, err) + + subIDForCancelling := subIDsForCancelling[0] + + subscriptionForCancelling, err := vrfv2Contracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling) + require.NoError(t, err, "Error getting subscription information") + + vrfv2_actions.LogSubDetails(l, subscriptionForCancelling, subIDForCancelling, vrfv2Contracts.Coordinator) + + // No GetActiveSubscriptionIds function available - skipping check + + pendingRequestsExist, err := vrfv2Contracts.Coordinator.PendingRequestsExist(testcontext.Get(t), subIDForCancelling) + require.NoError(t, err) + require.False(t, pendingRequestsExist, "Pending requests should not exist") + + // Request randomness - should fail due to underfunded subscription + randomWordsFulfilledEventTimeout := 5 * time.Second + _, err = vrfv2_actions.RequestRandomnessAndWaitForFulfillment( + vrfv2Contracts.LoadTestConsumers[0], + vrfv2Contracts.Coordinator, + vrfv2Data, + subIDForCancelling, + testConfig.RandomnessRequestCountPerRequest, + testConfig, + randomWordsFulfilledEventTimeout, + l, + ) + require.Error(t, err, "Error should occur while waiting for fulfilment due to low sub balance") + + pendingRequestsExist, err = vrfv2Contracts.Coordinator.PendingRequestsExist(testcontext.Get(t), subIDForCancelling) + require.NoError(t, err) + require.True(t, pendingRequestsExist, "Pending requests should exist after unfilfulled requests due to low sub balance") + + walletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) + require.NoError(t, err) + + subscriptionForCancelling, err = vrfv2Contracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling) + require.NoError(t, err, "Error getting subscription information") + subBalanceLink := subscriptionForCancelling.Balance + + l.Info(). + Str("Subscription Amount Link", subBalanceLink.String()). + Uint64("Returning funds from SubID", subIDForCancelling). + Str("Returning funds to", defaultWalletAddress). + Msg("Canceling subscription and returning funds to subscription owner") + + // Call OwnerCancelSubscription + tx, err := vrfv2Contracts.Coordinator.OwnerCancelSubscription(subIDForCancelling) + require.NoError(t, err, "Error canceling subscription") + + subscriptionCanceledEvent, err := vrfv2Contracts.Coordinator.WaitForSubscriptionCanceledEvent([]uint64{subIDForCancelling}, time.Second*30) + require.NoError(t, err, "error waiting for subscription canceled event") + + cancellationTxReceipt, err := env.EVMClient.GetTxReceipt(tx.Hash()) + require.NoError(t, err, "error getting tx cancellation Tx Receipt") + + txGasUsed := new(big.Int).SetUint64(cancellationTxReceipt.GasUsed) + cancellationTxFeeWei := new(big.Int).Mul(txGasUsed, cancellationTxReceipt.EffectiveGasPrice) + + l.Info(). + Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()). + Str("Effective Gas Price", cancellationTxReceipt.EffectiveGasPrice.String()). + Uint64("Gas Used", cancellationTxReceipt.GasUsed). + Msg("Cancellation TX Receipt") + + l.Info(). + Str("Returned Subscription Amount Link", subscriptionCanceledEvent.Amount.String()). + Uint64("SubID", subscriptionCanceledEvent.SubId). + Str("Returned to", subscriptionCanceledEvent.To.String()). + Msg("Subscription Canceled Event") + + require.Equal(t, subBalanceLink, subscriptionCanceledEvent.Amount, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription") + + walletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) + require.NoError(t, err) + + // Verify that subscription was deleted from Coordinator contract + _, err = vrfv2Contracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling) + l.Info(). + Str("Expected error message", err.Error()) + require.Error(t, err, "Error did not occur when fetching deleted subscription from the Coordinator after owner cancelation") + + subFundsReturnedLinkActual := new(big.Int).Sub(walletBalanceLinkAfterSubCancelling, walletBalanceLinkBeforeSubCancelling) + l.Info(). + Str("Wallet Balance Before Owner Cancelation", walletBalanceLinkBeforeSubCancelling.String()). + Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()). + Str("Sub Funds Returned Actual - Link", subFundsReturnedLinkActual.String()). + Str("Sub Balance - Link", subBalanceLink.String()). + Str("Wallet Balance After Owner Cancelation", walletBalanceLinkAfterSubCancelling.String()). + Msg("Sub funds returned") + + require.Equal(t, 0, subBalanceLink.Cmp(subFundsReturnedLinkActual), "Returned LINK funds are not equal to sub balance that was cancelled") + + // Again, there is no GetActiveSubscriptionIds method on the v2 Coordinator contract, so we can't double check that the cancelled + // subID is no longer in the list of active subs + }) } func TestVRFv2MultipleSendingKeys(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + var vrfv2Config vrfv2_config.VRFV2Config - err := envconfig.Process("VRFV2", &vrfv2Config) + err = envconfig.Process("VRFV2", &vrfv2Config) require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). - WithGeth(). + WithPrivateEthereumNetwork(network). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "error creating test env") diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index a850cb4fe15..6cc4a07237f 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -42,7 +42,6 @@ func TestVRFv2Plus(t *testing.T) { WithCLNodes(1). WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "error creating test env") @@ -54,7 +53,7 @@ func TestVRFv2Plus(t *testing.T) { linkToken, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err, "error deploying LINK contract") - // register proving key against oracle address (sending key) in order to test oracleWithdraw + // default wallet address is used to test Withdraw defaultWalletAddress := env.EVMClient.GetDefaultWallet().Address() numberOfTxKeysToCreate := 2 @@ -63,7 +62,6 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusConfig, linkToken, mockETHLinkFeed, - defaultWalletAddress, numberOfTxKeysToCreate, 1, 1, @@ -523,9 +521,10 @@ func TestVRFv2Plus(t *testing.T) { "Active subscription ids should not contain sub id after sub cancellation", ) }) - t.Run("Oracle Withdraw", func(t *testing.T) { + + t.Run("Owner Withdraw", func(t *testing.T) { testConfig := vrfv2PlusConfig - subIDsForOracleWithDraw, err := vrfv2plus.CreateFundSubsAndAddConsumers( + subIDsForWithdraw, err := vrfv2plus.CreateFundSubsAndAddConsumers( env, testConfig, linkToken, @@ -534,13 +533,13 @@ func TestVRFv2Plus(t *testing.T) { 1, ) require.NoError(t, err) - subIDForOracleWithdraw := subIDsForOracleWithDraw[0] + subIDForWithdraw := subIDsForWithdraw[0] fulfilledEventLink, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( vrfv2PlusContracts.LoadTestConsumers[0], vrfv2PlusContracts.Coordinator, vrfv2PlusData, - subIDForOracleWithdraw, + subIDForWithdraw, false, testConfig.RandomnessRequestCountPerRequest, testConfig, @@ -553,7 +552,7 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusContracts.LoadTestConsumers[0], vrfv2PlusContracts.Coordinator, vrfv2PlusData, - subIDForOracleWithdraw, + subIDForWithdraw, true, testConfig.RandomnessRequestCountPerRequest, testConfig, @@ -563,10 +562,10 @@ func TestVRFv2Plus(t *testing.T) { require.NoError(t, err) amountToWithdrawLink := fulfilledEventLink.Payment - defaultWalletBalanceNativeBeforeOracleWithdraw, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress)) + defaultWalletBalanceNativeBeforeWithdraw, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress)) require.NoError(t, err) - defaultWalletBalanceLinkBeforeOracleWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) + defaultWalletBalanceLinkBeforeWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) require.NoError(t, err) l.Info(). @@ -574,9 +573,8 @@ func TestVRFv2Plus(t *testing.T) { Str("Amount", amountToWithdrawLink.String()). Msg("Invoking Oracle Withdraw for LINK") - err = vrfv2PlusContracts.Coordinator.OracleWithdraw( + err = vrfv2PlusContracts.Coordinator.Withdraw( common.HexToAddress(defaultWalletAddress), - amountToWithdrawLink, ) require.NoError(t, err, "error withdrawing LINK from coordinator to default wallet") amountToWithdrawNative := fulfilledEventNative.Payment @@ -586,24 +584,23 @@ func TestVRFv2Plus(t *testing.T) { Str("Amount", amountToWithdrawNative.String()). Msg("Invoking Oracle Withdraw for Native") - err = vrfv2PlusContracts.Coordinator.OracleWithdrawNative( + err = vrfv2PlusContracts.Coordinator.WithdrawNative( common.HexToAddress(defaultWalletAddress), - amountToWithdrawNative, ) require.NoError(t, err, "error withdrawing Native tokens from coordinator to default wallet") err = env.EVMClient.WaitForEvents() require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete) - defaultWalletBalanceNativeAfterOracleWithdraw, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress)) + defaultWalletBalanceNativeAfterWithdraw, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress)) require.NoError(t, err) - defaultWalletBalanceLinkAfterOracleWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) + defaultWalletBalanceLinkAfterWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress) require.NoError(t, err) //not possible to verify exact amount of Native/LINK returned as defaultWallet is used in other tests in parallel which might affect the balance - require.Equal(t, 1, defaultWalletBalanceNativeAfterOracleWithdraw.Cmp(defaultWalletBalanceNativeBeforeOracleWithdraw), "Native funds were not returned after oracle withdraw native") - require.Equal(t, 1, defaultWalletBalanceLinkAfterOracleWithdraw.Cmp(defaultWalletBalanceLinkBeforeOracleWithdraw), "LINK funds were not returned after oracle withdraw") + require.Equal(t, 1, defaultWalletBalanceNativeAfterWithdraw.Cmp(defaultWalletBalanceNativeBeforeWithdraw), "Native funds were not returned after oracle withdraw native") + require.Equal(t, 1, defaultWalletBalanceLinkAfterWithdraw.Cmp(defaultWalletBalanceLinkBeforeWithdraw), "LINK funds were not returned after oracle withdraw") }) } @@ -611,17 +608,19 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - err := envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) + err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). - WithGeth(). + WithPrivateEthereumNetwork(network). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "error creating test env") @@ -633,16 +632,12 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { linkToken, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err, "error deploying LINK contract") - // register proving key against oracle address (sending key) in order to test oracleWithdraw - defaultWalletAddress := env.EVMClient.GetDefaultWallet().Address() - numberOfTxKeysToCreate := 2 vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment( env, vrfv2PlusConfig, linkToken, mockETHLinkFeed, - defaultWalletAddress, numberOfTxKeysToCreate, 1, 1, @@ -702,17 +697,20 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { func TestVRFv2PlusMigration(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - err := envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) + err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). - WithGeth(). + WithPrivateEthereumNetwork(network). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "error creating test env") env.ParallelTransactions(true) @@ -723,15 +721,11 @@ func TestVRFv2PlusMigration(t *testing.T) { linkAddress, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err, "error deploying LINK contract") - nativeTokenPrimaryKeyAddress, err := env.ClCluster.NodeAPIs()[0].PrimaryEthAddress() - require.NoError(t, err, "error getting primary eth address") - vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment( env, vrfv2PlusConfig, linkAddress, mockETHLinkFeedAddress, - nativeTokenPrimaryKeyAddress, 0, 2, 1, @@ -761,7 +755,7 @@ func TestVRFv2PlusMigration(t *testing.T) { err = env.EVMClient.WaitForEvents() require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete) - _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfv2PlusData.VRFKey, vrfv2PlusData.PrimaryEthAddress, newCoordinator) + _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfv2PlusData.VRFKey, newCoordinator) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfv2plus.ErrRegisteringProvingKey, err)) err = newCoordinator.SetConfig( diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go index 7436c05a107..d8536c1395e 100644 --- a/integration-tests/types/config/node/core.go +++ b/integration-tests/types/config/node/core.go @@ -12,6 +12,8 @@ import ( "github.com/segmentio/ksuid" commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -22,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/smartcontractkit/chainlink/v2/core/utils/config" it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" ) diff --git a/integration-tests/universal/log_poller/gun.go b/integration-tests/universal/log_poller/gun.go index 39286f1b53e..a75209aa101 100644 --- a/integration-tests/universal/log_poller/gun.go +++ b/integration-tests/universal/log_poller/gun.go @@ -39,7 +39,7 @@ func NewLogEmitterGun( } } -func (m *LogEmitterGun) Call(l *wasp.Generator) *wasp.CallResult { +func (m *LogEmitterGun) Call(l *wasp.Generator) *wasp.Response { localCounter := 0 logEmitter := (*m.contract) address := logEmitter.Address() @@ -58,7 +58,7 @@ func (m *LogEmitterGun) Call(l *wasp.Generator) *wasp.CallResult { } if err != nil { - return &wasp.CallResult{Error: err.Error(), Failed: true} + return &wasp.Response{Error: err.Error(), Failed: true} } localCounter++ } @@ -69,11 +69,11 @@ func (m *LogEmitterGun) Call(l *wasp.Generator) *wasp.CallResult { defer counter.mu.Unlock() counter.value += localCounter } else { - return &wasp.CallResult{ + return &wasp.Response{ Error: "SharedData did not contain a Counter", Failed: true, } } - return &wasp.CallResult{} + return &wasp.Response{} } diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 1abd98632f1..40040fd0aee 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -1060,7 +1060,6 @@ func setupLogPollerTestDocker( WithChainOptions(logPolllerSettingsFn). EVMClientNetworkOptions(evmClientSettingsFn). WithStandardCleanup(). - WithLogStream(). Build() require.NoError(t, err, "Error deploying test environment") diff --git a/internal/testdb/testdb.go b/internal/testdb/testdb.go new file mode 100644 index 00000000000..9b531166113 --- /dev/null +++ b/internal/testdb/testdb.go @@ -0,0 +1,56 @@ +package testdb + +import ( + "database/sql" + "errors" + "fmt" + "net/url" + + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" +) + +const ( + // PristineDBName is a clean copy of test DB with migrations. + PristineDBName = "chainlink_test_pristine" + // TestDBNamePrefix is a common prefix that will be auto-removed by the dangling DB cleanup process. + TestDBNamePrefix = "chainlink_test_" +) + +// CreateOrReplace creates a database named with a common prefix and the given suffix, and returns the URL. +// If the database already exists, it will be dropped and re-created. +// If withTemplate is true, the pristine DB will be used as a template. +func CreateOrReplace(parsed url.URL, suffix string, withTemplate bool) (string, error) { + if parsed.Path == "" { + return "", errors.New("path missing from database URL") + } + + // Match the naming schema that our dangling DB cleanup methods expect + dbname := TestDBNamePrefix + suffix + if l := len(dbname); l > 63 { + return "", fmt.Errorf("dbname %v too long (%d), max is 63 bytes. Try a shorter suffix", dbname, l) + } + // Cannot drop test database if we are connected to it, so we must connect + // to a different one. 'postgres' should be present on all postgres installations + parsed.Path = "/postgres" + db, err := sql.Open(string(dialects.Postgres), parsed.String()) + if err != nil { + return "", fmt.Errorf("in order to drop the test database, we need to connect to a separate database"+ + " called 'postgres'. But we are unable to open 'postgres' database: %+v\n", err) + } + defer db.Close() + + _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", dbname)) + if err != nil { + return "", fmt.Errorf("unable to drop postgres migrations test database: %v", err) + } + if withTemplate { + _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s WITH TEMPLATE %s", dbname, PristineDBName)) + } else { + _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbname)) + } + if err != nil { + return "", fmt.Errorf("unable to create postgres test database with name '%s': %v", dbname, err) + } + parsed.Path = fmt.Sprintf("/%s", dbname) + return parsed.String(), nil +} diff --git a/lintconf.yaml b/lintconf.yaml new file mode 100644 index 00000000000..ff37371d476 --- /dev/null +++ b/lintconf.yaml @@ -0,0 +1,46 @@ +--- +# 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/main_test.go b/main_test.go index 032ec4718a2..15b17e32654 100644 --- a/main_test.go +++ b/main_test.go @@ -1,17 +1,41 @@ package main import ( + "fmt" + "net/url" "os" + "path/filepath" + "strconv" + "strings" "testing" + "github.com/google/uuid" + "github.com/hashicorp/consul/sdk/freeport" "github.com/rogpeppe/go-internal/testscript" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/static" + "github.com/smartcontractkit/chainlink/v2/internal/testdb" "github.com/smartcontractkit/chainlink/v2/tools/txtar" ) +// special files can be included to allocate additional test resources +const ( + // testDBName triggers initializing of a test database. + // The URL will be set as the value of an env var named by the file. + // + // -- testdb.txt -- + // CL_DATABASE_URL + testDBName = "testdb.txt" + // testPortName triggers injection of a free port as the value of an env var named by the file. + // + // -- testport.txt -- + // PORT + testPortName = "testport.txt" +) + func TestMain(m *testing.M) { os.Exit(testscript.RunMain(m, map[string]func() int{ "chainlink": core.Main, @@ -22,11 +46,14 @@ func TestScripts(t *testing.T) { t.Parallel() visitor := txtar.NewDirVisitor("testdata/scripts", txtar.Recurse, func(path string) error { - t.Run(path, func(t *testing.T) { + t.Run(strings.TrimPrefix(path, "testdata/scripts/"), func(t *testing.T) { t.Parallel() + testscript.Run(t, testscript.Params{ - Dir: path, - Setup: commonEnv, + Dir: path, + Setup: commonEnv, + ContinueOnError: true, + //UpdateScripts: true, // uncomment to update golden files }) }) return nil @@ -35,9 +62,62 @@ func TestScripts(t *testing.T) { require.NoError(t, visitor.Walk()) } -func commonEnv(env *testscript.Env) error { - env.Setenv("HOME", "$WORK/home") - env.Setenv("VERSION", static.Version) - env.Setenv("COMMIT_SHA", static.Sha) +func commonEnv(te *testscript.Env) error { + te.Setenv("HOME", "$WORK/home") + te.Setenv("VERSION", static.Version) + te.Setenv("COMMIT_SHA", static.Sha) + + b, err := os.ReadFile(filepath.Join(te.WorkDir, testPortName)) + if err != nil && !os.IsNotExist(err) { + return fmt.Errorf("failed to read file %s: %w", testPortName, err) + } else if err == nil { + envVarName := strings.TrimSpace(string(b)) + te.T().Log("test port requested:", envVarName) + + port, ret, err2 := takeFreePort() + if err2 != nil { + return err2 + } + te.Defer(ret) + + te.Setenv(envVarName, strconv.Itoa(port)) + } + + b, err = os.ReadFile(filepath.Join(te.WorkDir, testDBName)) + if err != nil && !os.IsNotExist(err) { + return fmt.Errorf("failed to read file %s: %w", testDBName, err) + } else if err == nil { + envVarName := strings.TrimSpace(string(b)) + te.T().Log("test database requested:", envVarName) + + u2, err2 := initDB() + if err2 != nil { + return err2 + } + + te.Setenv(envVarName, u2) + } return nil } + +func takeFreePort() (int, func(), error) { + ports, err := freeport.Take(1) + if err != nil { + return 0, nil, fmt.Errorf("failed to get free port: %w", err) + } + return ports[0], func() { freeport.Return(ports) }, nil +} + +func initDB() (string, error) { + u, err := url.Parse(string(env.DatabaseURL.Get())) + if err != nil { + return "", fmt.Errorf("failed to parse url: %w", err) + } + + name := strings.ReplaceAll(uuid.NewString(), "-", "_") + "_test" + u2, err := testdb.CreateOrReplace(*u, name, true) + if err != nil { + return "", fmt.Errorf("failed to create DB: %w", err) + } + return u2, nil +} diff --git a/testdata/scripts/health/default.txtar b/testdata/scripts/health/default.txtar new file mode 100644 index 00000000000..15be9da1fe6 --- /dev/null +++ b/testdata/scripts/health/default.txtar @@ -0,0 +1,119 @@ +# start node +exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' +exec chainlink node -c config.toml start -p password -a creds & + +# initialize client +env NODEURL=http://localhost:$PORT +exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL +exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check + +exec chainlink --remote-node-url $NODEURL health +cmp stdout out.txt + +exec chainlink --remote-node-url $NODEURL health -json +cp stdout compact.json +exec jq . compact.json +cmp stdout out.json + +-- testdb.txt -- +CL_DATABASE_URL +-- testport.txt -- +PORT + +-- password -- +T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ +-- creds -- +notreal@fakeemail.ch +fj293fbBnlQ!f9vNs + +-- config.toml.tmpl -- +[Webserver] +HTTPPort = $PORT + +-- out.txt -- +-JobSpawner +-Mailbox.Monitor +-Mercury.WSRPCPool +-Mercury.WSRPCPool.CacheSet +-PipelineORM +-PipelineRunner +-PromReporter +-TelemetryManager + +-- out.json -- +{ + "data": [ + { + "type": "checks", + "id": "JobSpawner", + "attributes": { + "name": "JobSpawner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mailbox.Monitor", + "attributes": { + "name": "Mailbox.Monitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool", + "attributes": { + "name": "Mercury.WSRPCPool", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool.CacheSet", + "attributes": { + "name": "Mercury.WSRPCPool.CacheSet", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineORM", + "attributes": { + "name": "PipelineORM", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineRunner", + "attributes": { + "name": "PipelineRunner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PromReporter", + "attributes": { + "name": "PromReporter", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "TelemetryManager", + "attributes": { + "name": "TelemetryManager", + "status": "passing", + "output": "" + } + } + ] +} diff --git a/testdata/scripts/health/help.txtar b/testdata/scripts/health/help.txtar new file mode 100644 index 00000000000..07eb0509e73 --- /dev/null +++ b/testdata/scripts/health/help.txtar @@ -0,0 +1,13 @@ +exec chainlink health --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink health - Prints a health report + +USAGE: + chainlink health [command options] [arguments...] + +OPTIONS: + --json, -j json output + diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar new file mode 100644 index 00000000000..6a6adb895cb --- /dev/null +++ b/testdata/scripts/health/multi-chain.txtar @@ -0,0 +1,299 @@ +# start node +exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' +exec chainlink node -c config.toml start -p password -a creds & + +# initialize client +env NODEURL=http://localhost:$PORT +exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL +exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check + +exec chainlink --remote-node-url $NODEURL health +cmp stdout out.txt + +exec chainlink --remote-node-url $NODEURL health -json +cp stdout compact.json +exec jq . compact.json +cmp stdout out.json + +-- testdb.txt -- +CL_DATABASE_URL +-- testport.txt -- +PORT + +-- password -- +T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ +-- creds -- +notreal@fakeemail.ch +fj293fbBnlQ!f9vNs + +-- config.toml.tmpl -- +[Webserver] +HTTPPort = $PORT + +[[Cosmos]] +ChainID = 'Foo' + +[[Cosmos.Nodes]] +Name = 'primary' +TendermintURL = 'http://tender.mint' + +[[EVM]] +ChainID = '1' + +[[EVM.Nodes]] +Name = 'fake' +WSURL = 'wss://foo.bar/ws' +HTTPURL = 'https://foo.bar' + +[[Solana]] +ChainID = 'Bar' + +[[Solana.Nodes]] +Name = 'primary' +URL = 'http://solana.web' + +[[Starknet]] +ChainID = 'Baz' + +[[Starknet.Nodes]] +Name = 'primary' +URL = 'http://stark.node' + +-- out.txt -- +-Cosmos.Foo.Chain +-Cosmos.Foo.Txm +-EVM.1 +-EVM.1.BalanceMonitor +-EVM.1.HeadBroadcaster +-EVM.1.HeadTracker +!EVM.1.HeadTracker.HeadListener + Listener is not connected +-EVM.1.LogBroadcaster +-EVM.1.Txm +-EVM.1.Txm.BlockHistoryEstimator +-EVM.1.Txm.Broadcaster +-EVM.1.Txm.Confirmer +-EVM.1.Txm.WrappedEvmEstimator +-JobSpawner +-Mailbox.Monitor +-Mercury.WSRPCPool +-Mercury.WSRPCPool.CacheSet +-PipelineORM +-PipelineRunner +-PromReporter +-Solana.Bar +-StarkNet.Baz +-TelemetryManager + +-- out.json -- +{ + "data": [ + { + "type": "checks", + "id": "Cosmos.Foo.Chain", + "attributes": { + "name": "Cosmos.Foo.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Cosmos.Foo.Txm", + "attributes": { + "name": "Cosmos.Foo.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1", + "attributes": { + "name": "EVM.1", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.BalanceMonitor", + "attributes": { + "name": "EVM.1.BalanceMonitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadBroadcaster", + "attributes": { + "name": "EVM.1.HeadBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadTracker", + "attributes": { + "name": "EVM.1.HeadTracker", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadTracker.HeadListener", + "attributes": { + "name": "EVM.1.HeadTracker.HeadListener", + "status": "failing", + "output": "Listener is not connected" + } + }, + { + "type": "checks", + "id": "EVM.1.LogBroadcaster", + "attributes": { + "name": "EVM.1.LogBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm", + "attributes": { + "name": "EVM.1.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.BlockHistoryEstimator", + "attributes": { + "name": "EVM.1.Txm.BlockHistoryEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Broadcaster", + "attributes": { + "name": "EVM.1.Txm.Broadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Confirmer", + "attributes": { + "name": "EVM.1.Txm.Confirmer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.WrappedEvmEstimator", + "attributes": { + "name": "EVM.1.Txm.WrappedEvmEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "JobSpawner", + "attributes": { + "name": "JobSpawner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mailbox.Monitor", + "attributes": { + "name": "Mailbox.Monitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool", + "attributes": { + "name": "Mercury.WSRPCPool", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool.CacheSet", + "attributes": { + "name": "Mercury.WSRPCPool.CacheSet", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineORM", + "attributes": { + "name": "PipelineORM", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineRunner", + "attributes": { + "name": "PipelineRunner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PromReporter", + "attributes": { + "name": "PromReporter", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar", + "attributes": { + "name": "Solana.Bar", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz", + "attributes": { + "name": "StarkNet.Baz", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "TelemetryManager", + "attributes": { + "name": "TelemetryManager", + "status": "passing", + "output": "" + } + } + ] +} diff --git a/testdata/scripts/help.txtar b/testdata/scripts/help.txtar index 1484aceb5df..e4c19f3987d 100644 --- a/testdata/scripts/help.txtar +++ b/testdata/scripts/help.txtar @@ -17,6 +17,7 @@ COMMANDS: blocks Commands for managing blocks bridges Commands for Bridges communicating with External Adapters config Commands for the node's configuration + health Prints a health report jobs Commands for managing Jobs keys Commands for managing various types of keys used by the Chainlink node node, local Commands for admin actions that must be run locally diff --git a/testdata/scripts/keys/eth/create/help.txtar b/testdata/scripts/keys/eth/create/help.txtar new file mode 100644 index 00000000000..d089b220ae4 --- /dev/null +++ b/testdata/scripts/keys/eth/create/help.txtar @@ -0,0 +1,14 @@ +exec chainlink keys eth create --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink keys eth create - Create a key in the node's keystore alongside the existing key; to create an original key, just run the node + +USAGE: + chainlink keys eth create [command options] [arguments...] + +OPTIONS: + --evm-chain-id value, --evmChainID value Chain ID for the key. If left blank, default chain will be used. + --max-gas-price-gwei value, --maxGasPriceGWei value Optional maximum gas price (GWei) for the creating key. (default: 0) + diff --git a/testdata/scripts/keys/eth/list/help.txtar b/testdata/scripts/keys/eth/list/help.txtar new file mode 100644 index 00000000000..d7156fd3e69 --- /dev/null +++ b/testdata/scripts/keys/eth/list/help.txtar @@ -0,0 +1,9 @@ +exec chainlink keys eth list --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink keys eth list - List available Ethereum accounts with their ETH & LINK balances and other metadata + +USAGE: + chainlink keys eth list [arguments...] \ No newline at end of file diff --git a/testdata/scripts/keys/eth/list/unavailable.txtar b/testdata/scripts/keys/eth/list/unavailable.txtar new file mode 100644 index 00000000000..912ad75c1e4 --- /dev/null +++ b/testdata/scripts/keys/eth/list/unavailable.txtar @@ -0,0 +1,38 @@ +# start node +exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' +exec chainlink node -c config.toml start -p password -a creds & + +# initialize client +env NODEURL=http://localhost:$PORT +exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL +exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check + +exec chainlink --remote-node-url $NODEURL keys eth list +! stdout 'ETH: ' +! stdout 'LINK: ' +! stdout '' +stdout 'ETH: Unknown' +stdout 'LINK: Unknown' + +-- testdb.txt -- +CL_DATABASE_URL +-- testport.txt -- +PORT + +-- password -- +T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ +-- creds -- +notreal@fakeemail.ch +fj293fbBnlQ!f9vNs + +-- config.toml.tmpl -- +[Webserver] +HTTPPort = $PORT + +[[EVM]] +ChainID = '99' + +[[EVM.Nodes]] +Name = 'fake' +WSURL = 'wss://foo.bar/ws' +HTTPURL = 'https://foo.bar' diff --git a/testdata/scripts/node/db/migrate/db.txtar b/testdata/scripts/node/db/migrate/db.txtar new file mode 100644 index 00000000000..f040a937fd0 --- /dev/null +++ b/testdata/scripts/node/db/migrate/db.txtar @@ -0,0 +1,6 @@ +exec chainlink node db migrate +! stdout . +stderr 'goose: no migrations to run. current version:' + +-- testdb.txt -- +CL_DATABASE_URL diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index c9f86e43b29..32a7e5f71b3 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -240,6 +240,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + Invalid configuration: invalid secrets: 2 errors: - Database.URL: empty: must be provided and non-empty - Password.Keystore: empty: must be provided and non-empty diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 1ae283c8a8a..9cca8764eed 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -284,6 +284,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' AutoCreateKey = true 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 dcb2d05ce39..d1658a1772d 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -284,6 +284,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index fee173d3083..18ac99db785 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -284,6 +284,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 5acbad83f8c..f048e35547e 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -274,6 +274,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index b54fc899bbd..47c63e4c03e 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -281,6 +281,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 710e29d4983..c6daa829ddb 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -263,6 +263,9 @@ LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' LatestReportDeadline = '5s' +[Mercury.TLS] +CertFile = '' + # Configuration warning: Tracing.TLSCertPath: invalid value (something): must be empty when Tracing.Mode is 'unencrypted' Valid configuration.